示例#1
0
    void object::test<7>()
    {
        // Index of test file being tested
        const std::size_t fileIdx = 0;

        std::string src(data_ + SEP);
        src += rasters_.at(fileIdx).file_;

        GDALDatasetH dsSrc = GDALOpen(src.c_str(), GA_ReadOnly);
        ensure("Can't open source dataset: " + src, nullptr != dsSrc);

        std::string dst(data_tmp_ + SEP);
        dst += rasters_.at(fileIdx).file_;
        dst += ".grd";

        GDALDatasetH dsDst = nullptr;
        dsDst = GDALCreateCopy(drv_, dst.c_str(), dsSrc, FALSE, nullptr, nullptr, nullptr);
        GDALClose(dsSrc);
        ensure("Can't copy dataset", nullptr != dsDst);

        std::string proj(GDALGetProjectionRef(dsDst));
        ensure_equals("Projection definition is not available", proj.empty(), false);

        std::string expect(
            "PROJCS[\"NAD27 / UTM zone 11N\",GEOGCS[\"NAD27\","
            "DATUM[\"North_American_Datum_1927\",SPHEROID[\"Clarke 1866\","
            "6378206.4,294.978698213898,AUTHORITY[\"EPSG\",\"7008\"]],"
            "AUTHORITY[\"EPSG\",\"6267\"]],PRIMEM[\"Greenwich\",0],"
            "UNIT[\"Degree\",0.0174532925199433]],"
            "PROJECTION[\"Transverse_Mercator\"],"
            "PARAMETER[\"latitude_of_origin\",0],"
            "PARAMETER[\"central_meridian\",-117],"
            "PARAMETER[\"scale_factor\",0.9996],"
            "PARAMETER[\"false_easting\",500000],"
            "PARAMETER[\"false_northing\",0],"
            "UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],"
            "AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]");

        ensure_equals("Projection does not match expected", proj, expect);

        GDALRasterBandH band = GDALGetRasterBand(dsDst, rasters_.at(fileIdx).band_);
        ensure("Can't get raster band", nullptr != band);

        const int xsize = GDALGetRasterXSize(dsDst);
        const int ysize = GDALGetRasterYSize(dsDst);
        const int checksum = GDALChecksumImage(band, 0, 0, xsize, ysize);

        std::stringstream os;
        os << "Checksums for '" << dst << "' not equal";
        ensure_equals(os.str().c_str(), checksum, rasters_.at(fileIdx).checksum_);

        GDALClose(dsDst);

    }
GDALDataset* geGdalVSI::VsiGdalCreateCopyWrap(GDALDriverH hdriver,
                                              std::string* const vsifile,
                                              GDALDatasetH hdataset,
                                              int bstrict,
                                              char **papszoptions,
                                              GDALProgressFunc progressfunc,
                                              void *progressdata) {
  GDALDatasetH hvsi_ds;
  khMutex &mutex = GetMutex();
  khLockGuard lock(mutex);
  *vsifile = UniqueVSIFilename();
  hvsi_ds = GDALCreateCopy(hdriver, (*vsifile).c_str(), hdataset, bstrict,
                           papszoptions, progressfunc, progressdata);
  return static_cast<GDALDataset*>(hvsi_ds);
}
示例#3
0
/* Makes a copy of a dataset, and opens it for writing.. */
GDALDatasetH
make_me_a_sandwitch (GDALDatasetH * in_dataset, const char *copy_file_name)
{
  char **papszOptions = NULL;
  const char *pszFormat = "GTiff";
  GDALDriverH hDriver;
  GDALDatasetH out_gdalfile;
  hDriver = GDALGetDriverByName (pszFormat);
  papszOptions = CSLSetNameValue (papszOptions, "TILED", "YES");
  papszOptions = CSLSetNameValue (papszOptions, "COMPRESS", "DEFLATE");

  /*Perhaps controversal - default to bigtiff... */
  papszOptions = CSLSetNameValue (papszOptions, "BIGTIFF", "YES");

  return GDALCreateCopy (hDriver, copy_file_name, *in_dataset, FALSE,
			 papszOptions, NULL, NULL);
}
示例#4
0
static ERL_NIF_TERM gdal_nif_tile_to_binary(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    gdal_tile_handle* ti;
    if (!enif_get_resource(env, argv[0], gdal_tile_RESOURCE, (void**)&ti)) {
        return enif_make_badarg(env);
    }

    ErlNifBinary tilefilenameBin;
    if (!enif_inspect_iolist_as_binary(env, argv[1], &tilefilenameBin) || (tilefilenameBin.size >= FILENAME_LEN)) {
        return make_error_msg(env, "filename error, maybe too long");
    }

    char rasterFormatCode[16] = "";
    if (enif_get_string(env, argv[2], rasterFormatCode, 16, ERL_NIF_LATIN1) <= 0) {
        return enif_make_badarg(env);
    }

    char tilefilename[FILENAME_LEN] = "";
    memcpy(tilefilename, tilefilenameBin.data, tilefilenameBin.size);
    DEBUG("passed tilefilename: %s\r\n", tilefilename);

    GDALDriverH hOutDriver = GDALGetDriverByName(rasterFormatCode);
    if ( ! ti->options_resampling || (strcmp("antialias", ti->options_resampling) != 0) ) {
        char vsimemFileName[128] = "";
        sprintf(vsimemFileName, "/vsimem/%s", tilefilename);
        GDALDatasetH tileBinDataset = GDALCreateCopy(hOutDriver,
                                                     vsimemFileName, ti->dstile, 
                                                     FALSE, NULL, NULL, NULL);
        vsi_l_offset binDataLength;
        int bUnlinkAndSeize = FALSE;
        GByte* binData = VSIGetMemFileBuffer(vsimemFileName, &binDataLength, bUnlinkAndSeize);
        DEBUG("vsimem: %s, bin len: %d\r\n", vsimemFileName, binDataLength);

        ERL_NIF_TERM binTerm;
        unsigned char* buf = enif_make_new_binary(env, binDataLength, &binTerm);
        memcpy(buf, binData, binDataLength);
 //       CPLFree(binData);

        GDALClose(tileBinDataset);
        return enif_make_tuple2(env, ATOM_OK, binTerm);
    }

    return make_error_msg(env, "wrong resampling");
}
示例#5
0
// Depracated
static ERL_NIF_TERM gdal_nif_save_tile(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    gdal_tile_handle* ti;
    if (!enif_get_resource(env, argv[0], gdal_tile_RESOURCE, (void**)&ti)) {
        return enif_make_badarg(env);
    }
    
    char tilefilename[256] = "";
    if (enif_get_string(env, argv[1], tilefilename, 256, ERL_NIF_LATIN1) <= 0) {
        return enif_make_badarg(env);
    }

    GDALDriverH hOutDriver = GDALGetDriverByName("PNG");
    if ( ! ti->options_resampling || (strcmp("antialias", ti->options_resampling) != 0) ) {
        GDALDatasetH tileDataset = GDALCreateCopy(hOutDriver,
                                                  tilefilename, ti->dstile, 
                                                  FALSE, NULL, NULL, NULL);
        GDALClose(tileDataset);
    }

    return ATOM_OK;
}
示例#6
0
int main( int argc, char ** argv )

{
    GDALDatasetH	hDataset, hOutDS;
    int			i;
    const char		*pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
    GDALDriverH		hDriver;
    GDALDataType	eOutputType = GDT_Unknown;
    char                **papszCreateOptions = NULL;
    GDALProgressFunc    pfnProgress = GDALTermProgress;
    int                 nLUTBins = 256;
    const char         *pszMethod = "minmax";
//    double              dfStdDevMult = 0.0;
    double             *padfScaleMin = NULL;
    double             *padfScaleMax = NULL;
    int               **papanLUTs = NULL;
    int                 iBand;
    const char         *pszConfigFile = NULL;

    /* Check strict compilation and runtime library version as we use C++ API */
    if (! GDAL_CHECK_VERSION(argv[0]))
        exit(1);
/* -------------------------------------------------------------------- */
/*      Register standard GDAL drivers, and process generic GDAL        */
/*      command options.                                                */
/* -------------------------------------------------------------------- */
    GDALAllRegister();
    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    if( argc < 1 )
        exit( -argc );

/* -------------------------------------------------------------------- */
/*      Handle command line arguments.                                  */
/* -------------------------------------------------------------------- */
    for( i = 1; i < argc; i++ )
    {
        if( EQUAL(argv[i], "--utility_version") )
        {
            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
            return 0;
        }
        else if( EQUAL(argv[i],"-of") && i < argc-1 )
            pszFormat = argv[++i];

        else if( EQUAL(argv[i],"-ot") && i < argc-1 )
        {
            int	iType;
            
            for( iType = 1; iType < GDT_TypeCount; iType++ )
            {
                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
                             argv[i+1]) )
                {
                    eOutputType = (GDALDataType) iType;
                }
            }

            if( eOutputType == GDT_Unknown )
            {
                printf( "Unknown output pixel type: %s\n", argv[i+1] );
                Usage();
                GDALDestroyDriverManager();
                exit( 2 );
            }
            i++;
        }

        else if( EQUALN(argv[i],"-s_nodata",9) )
        {
            // TODO
            i += 1;
        }   

        else if( EQUAL(argv[i],"-co") && i < argc-1 )
        {
            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
        }   

        else if( EQUALN(argv[i],"-src_scale",10) && i < argc-2)
        {
            // TODO
            i += 2;
        }

        else if( EQUALN(argv[i],"-dst_scale",10) && i < argc-2 )
        {
            // TODO
            i += 2;
        }

        else if( EQUAL(argv[i],"-config") && i < argc-1 )
        {
            pszConfigFile = argv[++i];
        }

        else if( EQUAL(argv[i],"-equalize") )
        {
            pszMethod = "equalize";
        }

        else if( EQUAL(argv[i],"-quiet") )
        {
            pfnProgress = GDALDummyProgress;
        }

        else if( argv[i][0] == '-' )
        {
            printf( "Option %s incomplete, or not recognised.\n\n", 
                    argv[i] );
            Usage();
            GDALDestroyDriverManager();
            exit( 2 );
        }
        else if( pszSource == NULL )
        {
            pszSource = argv[i];
        }
        else if( pszDest == NULL )
        {
            pszDest = argv[i];
        }

        else
        {
            printf( "Too many command options.\n\n" );
            Usage();
            GDALDestroyDriverManager();
            exit( 2 );
        }
    }

    if( pszSource == NULL )
    {
        Usage();
        GDALDestroyDriverManager();
        exit( 10 );
    }

/* -------------------------------------------------------------------- */
/*      Attempt to open source file.                                    */
/* -------------------------------------------------------------------- */

    hDataset = GDALOpenShared( pszSource, GA_ReadOnly );
    
    if( hDataset == NULL )
    {
        fprintf( stderr,
                 "GDALOpen failed - %d\n%s\n",
                 CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
        GDALDestroyDriverManager();
        exit( 1 );
    }

    int nBandCount = GDALGetRasterCount(hDataset);

/* -------------------------------------------------------------------- */
/*      Find the output driver.                                         */
/* -------------------------------------------------------------------- */
    hDriver = GDALGetDriverByName( pszFormat );
    if( hDriver == NULL )
    {
        int	iDr;
        
        printf( "Output driver `%s' not recognised.\n", pszFormat );
        printf( "The following format drivers are configured and support output:\n" );
        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
        {
            GDALDriverH hDriver = GDALGetDriver(iDr);

            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
                || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
                                        NULL ) != NULL )
            {
                printf( "  %s: %s\n",
                        GDALGetDriverShortName( hDriver  ),
                        GDALGetDriverLongName( hDriver ) );
            }
        }
        printf( "\n" );
        Usage();
        
        GDALClose( hDataset );
        GDALDestroyDriverManager();
        CSLDestroy( argv );
        CSLDestroy( papszCreateOptions );
        exit( 1 );
    }

/* -------------------------------------------------------------------- */
/*      If histogram equalization is requested, do it now.              */
/* -------------------------------------------------------------------- */
    if( EQUAL(pszMethod,"equalize") )
    {
        ComputeEqualizationLUTs( hDataset, nLUTBins, 
                                 &padfScaleMin, &padfScaleMax, 
                                 &papanLUTs, pfnProgress );
    }

/* -------------------------------------------------------------------- */
/*      If we have a config file, assume it is for input and read       */
/*      it.                                                             */
/* -------------------------------------------------------------------- */
    else if( pszConfigFile != NULL )
    {
        char **papszLines = CSLLoad( pszConfigFile );
        if( CSLCount(papszLines) == 0 )
            exit( 1 );

        if( CSLCount(papszLines) != nBandCount )
        {
            fprintf( stderr, "Did not get %d lines in config file as expected.\n", nBandCount );
            exit( 1 );
        }

        padfScaleMin = (double *) CPLCalloc(nBandCount,sizeof(double));
        padfScaleMax = (double *) CPLCalloc(nBandCount,sizeof(double));

        for( iBand = 0; iBand < nBandCount; iBand++ )
        {
            int iLUT;
            char **papszTokens = CSLTokenizeString( papszLines[iBand] );

            if( CSLCount(papszTokens) < 3 
                || atoi(papszTokens[0]) != iBand+1 )
            {
                fprintf( stderr, "Line %d seems to be corrupt.\n", iBand+1 );
                exit( 1 );
            }

            // Process scale min/max

            padfScaleMin[iBand] = atof(papszTokens[1]);
            padfScaleMax[iBand] = atof(papszTokens[2]);

            if( CSLCount(papszTokens) == 3 )
                continue;

            // process lut
            if( iBand == 0 )
            {
                nLUTBins = CSLCount(papszTokens) - 3;
                papanLUTs = (int **) CPLCalloc(sizeof(int*),nBandCount);
            }

            papanLUTs[iBand] = (int *) CPLCalloc(nLUTBins,sizeof(int));

            for( iLUT = 0; iLUT < nLUTBins; iLUT++ )
                papanLUTs[iBand][iLUT] = atoi(papszTokens[iLUT+3]);

            CSLDestroy( papszTokens );
        }
    }

/* -------------------------------------------------------------------- */
/*      If there is no destination, just report the scaling values      */
/*      and luts.                                                       */
/* -------------------------------------------------------------------- */
    if( pszDest == NULL )
    {
        FILE *fpConfig = stdout;
        if( pszConfigFile )
            fpConfig = fopen( pszConfigFile, "w" );
        
        for( iBand = 0; iBand < nBandCount; iBand++ )
        {
            fprintf( fpConfig, "%d:Band ", iBand+1 );
            if( padfScaleMin != NULL )
                fprintf( fpConfig, "%g:ScaleMin %g:ScaleMax ", 
                         padfScaleMin[iBand], padfScaleMax[iBand] );

            if( papanLUTs )
            {
                int iLUT;

                for( iLUT = 0; iLUT < nLUTBins; iLUT++ )
                    fprintf( fpConfig, "%d ", papanLUTs[iBand][iLUT] );
            }
            fprintf( fpConfig, "\n" );
        }

        if( pszConfigFile )
            fclose( fpConfig );

        exit( 0 );
    }

    if (padfScaleMin == NULL || padfScaleMax == NULL)
    {
        fprintf( stderr, "-equalize or -config filename command line options must be specified.\n");
        exit(1);
    }

/* ==================================================================== */
/*      Create a virtual dataset.                                       */
/* ==================================================================== */
    VRTDataset *poVDS;
    EnhanceCBInfo *pasEInfo = (EnhanceCBInfo *) 
        CPLCalloc(nBandCount, sizeof(EnhanceCBInfo));
        
/* -------------------------------------------------------------------- */
/*      Make a virtual clone.                                           */
/* -------------------------------------------------------------------- */
    poVDS = new VRTDataset( GDALGetRasterXSize(hDataset),
                            GDALGetRasterYSize(hDataset) );

    if( GDALGetGCPCount(hDataset) == 0 )
    {
        const char *pszProjection;
        double adfGeoTransform[6];

        pszProjection = GDALGetProjectionRef( hDataset );
        if( pszProjection != NULL && strlen(pszProjection) > 0 )
            poVDS->SetProjection( pszProjection );

        if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
            poVDS->SetGeoTransform( adfGeoTransform );
    }
    else
    {
        poVDS->SetGCPs( GDALGetGCPCount(hDataset), 
                        GDALGetGCPs(hDataset),
                        GDALGetGCPProjection( hDataset ) );
    }
    
    poVDS->SetMetadata( ((GDALDataset*)hDataset)->GetMetadata() );

    for( iBand = 0; iBand < nBandCount; iBand++ )
    {
        VRTSourcedRasterBand   *poVRTBand;
        GDALRasterBand  *poSrcBand;
        GDALDataType    eBandType;

        poSrcBand = ((GDALDataset *) hDataset)->GetRasterBand(iBand+1);

/* -------------------------------------------------------------------- */
/*      Select output data type to match source.                        */
/* -------------------------------------------------------------------- */
        if( eOutputType == GDT_Unknown )
            eBandType = GDT_Byte;
        else
            eBandType = eOutputType;

/* -------------------------------------------------------------------- */
/*      Create this band.                                               */
/* -------------------------------------------------------------------- */
        poVDS->AddBand( eBandType, NULL );
        poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand( iBand+1 );
            
/* -------------------------------------------------------------------- */
/*      Create a function based source with info on how to apply the    */
/*      enhancement.                                                    */
/* -------------------------------------------------------------------- */
        pasEInfo[iBand].poSrcBand = poSrcBand;
        pasEInfo[iBand].eWrkType = eBandType;
        pasEInfo[iBand].dfScaleMin = padfScaleMin[iBand];
        pasEInfo[iBand].dfScaleMax = padfScaleMax[iBand];
        pasEInfo[iBand].nLUTBins = nLUTBins;

        if( papanLUTs )
            pasEInfo[iBand].panLUT = papanLUTs[iBand];
        
        poVRTBand->AddFuncSource( EnhancerCallback, pasEInfo + iBand );

/* -------------------------------------------------------------------- */
/*      copy over some other information of interest.                   */
/* -------------------------------------------------------------------- */
        poVRTBand->CopyCommonInfoFrom( poSrcBand );
    }

/* -------------------------------------------------------------------- */
/*      Write to the output file using CopyCreate().                    */
/* -------------------------------------------------------------------- */
    hOutDS = GDALCreateCopy( hDriver, pszDest, (GDALDatasetH) poVDS,
                             FALSE, papszCreateOptions, 
                             pfnProgress, NULL );
    if( hOutDS != NULL )
        GDALClose( hOutDS );

    GDALClose( (GDALDatasetH) poVDS );
        
    GDALClose( hDataset );
    
/* -------------------------------------------------------------------- */
/*      Cleanup and exit.                                               */
/* -------------------------------------------------------------------- */
    GDALDumpOpenDatasets( stderr );
    GDALDestroyDriverManager();
    CSLDestroy( argv );
    CSLDestroy( papszCreateOptions );

    exit( 0 );
}
CPLErr RasterliteDataset::CreateOverviewLevel(int nOvrFactor,
                                              GDALProgressFunc pfnProgress,
                                              void * pProgressData)
{

    double dfXResolution = padfXResolutions[0] * nOvrFactor;
    double dfYResolution = padfXResolutions[0] * nOvrFactor;
    
    CPLString osSQL;

    int nBlockXSize = 256;
    int nBlockYSize = 256;
    int nOvrXSize = nRasterXSize / nOvrFactor;
    int nOvrYSize = nRasterYSize / nOvrFactor;
    
    if (nOvrXSize == 0 || nOvrYSize == 0)
        return CE_Failure;
    
    int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize;
    int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize;
    
    const char* pszDriverName = "GTiff";
    GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
    if (hTileDriver == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
        return CE_Failure;
    }
    
    GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
    if (hMemDriver == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
        return CE_Failure;
    }   

    GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
    GByte* pabyMEMDSBuffer =
        (GByte*)VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize);
    if (pabyMEMDSBuffer == NULL)
    {
        return CE_Failure;
    }
    
    char** papszTileDriverOptions = NULL;
    
    CPLString osTempFileName;
    osTempFileName.Printf("/vsimem/%p", hDS);
    
    int nTileId = 0;
    int nBlocks = 0;
    int nTotalBlocks = nXBlocks * nYBlocks;
    
    CPLString osRasterLayer;
    osRasterLayer.Printf("%s_rasters", osTableName.c_str());
    
    CPLString osMetatadataLayer;
    osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
    
    OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
    OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
    
    CPLString osSourceName = "unknown";
    
    osSQL.Printf("SELECT source_name FROM \"%s\" WHERE "
                 "pixel_x_size >= %.15f AND pixel_x_size <= %.15f AND "
                 "pixel_y_size >= %.15f AND pixel_y_size <= %.15f LIMIT 1",
                 osMetatadataLayer.c_str(),
                 padfXResolutions[0] - 1e-15, padfXResolutions[0] + 1e-15,
                 padfYResolutions[0] - 1e-15, padfYResolutions[0] + 1e-15);
    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
    if (hSQLLyr)
    {
        OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
        if (hFeat)
        {
            const char* pszVal = OGR_F_GetFieldAsString(hFeat, 0);
            if (pszVal)
                osSourceName = pszVal;
            OGR_F_Destroy(hFeat);
        }
        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
    }
    
/* -------------------------------------------------------------------- */
/*      Compute up to which existing overview level we can use for      */
/*      computing the requested overview                                */
/* -------------------------------------------------------------------- */
    int iLev;
    nLimitOvrCount = 0;
    for(iLev=1;iLev<nResolutions;iLev++)
    {
        if (!(padfXResolutions[iLev] < dfXResolution - 1e-10 &&
              padfYResolutions[iLev] < dfYResolution - 1e-10))
        {
            break;
        }
        nLimitOvrCount++;
    }
    
/* -------------------------------------------------------------------- */
/*      Iterate over blocks to add data into raster and metadata tables */
/* -------------------------------------------------------------------- */

    OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
    
    CPLErr eErr = CE_None;
    int nBlockXOff, nBlockYOff;
    for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
    {
        for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
        {
/* -------------------------------------------------------------------- */
/*      Create in-memory tile                                           */
/* -------------------------------------------------------------------- */
            int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
            if ((nBlockXOff+1) * nBlockXSize > nOvrXSize)
                nReqXSize = nOvrXSize - nBlockXOff * nBlockXSize;
            if ((nBlockYOff+1) * nBlockYSize > nOvrYSize)
                nReqYSize = nOvrYSize - nBlockYOff * nBlockYSize;
            
            eErr = RasterIO(GF_Read,
                            nBlockXOff * nBlockXSize * nOvrFactor,
                            nBlockYOff * nBlockYSize * nOvrFactor,
                            nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
                            pabyMEMDSBuffer, nReqXSize, nReqYSize,
                            eDataType, nBands, NULL,
                            0, 0, 0);
            if (eErr != CE_None)
            {
                break;
            }
            
            GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
                                              nReqXSize, nReqYSize, 0, 
                                              eDataType, NULL);
            if (hMemDS == NULL)
            {
                eErr = CE_Failure;
                break;
            }
            
            int iBand;
            for(iBand = 0; iBand < nBands; iBand ++)
            {
                char** papszOptions = NULL;
                char szTmp[64];
                memset(szTmp, 0, sizeof(szTmp));
                CPLPrintPointer(szTmp,
                                pabyMEMDSBuffer + iBand * nDataTypeSize *
                                nReqXSize * nReqYSize, sizeof(szTmp));
                papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szTmp);
                GDALAddBand(hMemDS, eDataType, papszOptions);
                CSLDestroy(papszOptions);
            }
            
            GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
                                        osTempFileName.c_str(), hMemDS, FALSE,
                                        papszTileDriverOptions, NULL, NULL);

            GDALClose(hMemDS);
            if (hOutDS)
                GDALClose(hOutDS);
            else
            {
                eErr = CE_Failure;
                break;
            }

/* -------------------------------------------------------------------- */
/*      Insert new entry into raster table                              */
/* -------------------------------------------------------------------- */

            vsi_l_offset nDataLength;
            GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
                                                   &nDataLength, FALSE);

            OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
            OGR_F_SetFieldBinary(hFeat, 0, (int)nDataLength, pabyData);
            
            OGR_L_CreateFeature(hRasterLayer, hFeat);
            /* Query raster ID to set it as the ID of the associated metadata */
            int nRasterID = (int)OGR_F_GetFID(hFeat);
            
            OGR_F_Destroy(hFeat);
            
            VSIUnlink(osTempFileName.c_str());
            
/* -------------------------------------------------------------------- */
/*      Insert new entry into metadata table                            */
/* -------------------------------------------------------------------- */
            
            hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
            OGR_F_SetFID(hFeat, nRasterID);
            OGR_F_SetFieldString(hFeat, 0, osSourceName);
            OGR_F_SetFieldInteger(hFeat, 1, nTileId ++);
            OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
            OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
            OGR_F_SetFieldDouble(hFeat, 4, dfXResolution);
            OGR_F_SetFieldDouble(hFeat, 5, dfYResolution);
            
            double minx, maxx, maxy, miny;
            minx = adfGeoTransform[0] +
                (nBlockXSize * nBlockXOff) * dfXResolution;
            maxx = adfGeoTransform[0] +
                (nBlockXSize * nBlockXOff + nReqXSize) * dfXResolution;
            maxy = adfGeoTransform[3] +
                (nBlockYSize * nBlockYOff) * (-dfYResolution);
            miny = adfGeoTransform[3] +
                (nBlockYSize * nBlockYOff + nReqYSize) * (-dfYResolution);
            
            OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
            OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
            OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
            OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
            OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
            OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
            
            OGR_F_SetGeometryDirectly(hFeat, hRectangle);
            
            OGR_L_CreateFeature(hMetadataLayer, hFeat);
            OGR_F_Destroy(hFeat);
            
            nBlocks++;
            if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
                                            NULL, pProgressData))
                eErr = CE_Failure;
        }
    }
    
    nLimitOvrCount = -1;
    
    if (eErr == CE_None)
        OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
    else
        OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
    
    VSIFree(pabyMEMDSBuffer);
    
/* -------------------------------------------------------------------- */
/*      Update raster_pyramids table                                    */
/* -------------------------------------------------------------------- */
    if (eErr == CE_None)
    {
        OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
        if (hRasterPyramidsLyr == NULL)
        {
            osSQL.Printf   ("CREATE TABLE raster_pyramids ("
                            "table_prefix TEXT NOT NULL,"
                            "pixel_x_size DOUBLE NOT NULL,"
                            "pixel_y_size DOUBLE NOT NULL,"
                            "tile_count INTEGER NOT NULL)");
            OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
            
            /* Re-open the DB to take into account the new tables*/
            OGRReleaseDataSource(hDS);
            
            CPLString osOldVal = CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "FALSE");
            CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", "TRUE");
            hDS = OGROpen(osFileName.c_str(), TRUE, NULL);
            CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", osOldVal.c_str());
        }

        /* Insert base resolution into raster_pyramids if not already done */
        int bHasBaseResolution = FALSE;
        osSQL.Printf("SELECT * FROM raster_pyramids WHERE "
                     "table_prefix = '%s' AND pixel_x_size >= %.15f AND pixel_x_size <= %.15f AND "
                     "pixel_y_size >= %.15f AND pixel_y_size <= %.15f",
                     osTableName.c_str(),
                     padfXResolutions[0] - 1e-15, padfXResolutions[0] + 1e-15,
                     padfYResolutions[0] - 1e-15, padfYResolutions[0] + 1e-15);
        hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
        if (hSQLLyr)
        {
            OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
            if (hFeat)
            {
                bHasBaseResolution = TRUE;
                OGR_F_Destroy(hFeat);
            }
            OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
        }

        if (!bHasBaseResolution)
        {
            osSQL.Printf("SELECT COUNT(*) FROM \"%s\" WHERE "
                          "pixel_x_size >= %.15f AND pixel_x_size <= %.15f AND "
                          "pixel_y_size >= %.15f AND pixel_y_size <= %.15f",
                          osMetatadataLayer.c_str(),
                          padfXResolutions[0] - 1e-15, padfXResolutions[0] + 1e-15,
                          padfYResolutions[0] - 1e-15, padfYResolutions[0] + 1e-15);

            int nBlocksMainRes = 0;

            hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
            if (hSQLLyr)
            {
                OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
                if (hFeat)
                {
                    nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0);
                    OGR_F_Destroy(hFeat);
                }
                OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
            }

            osSQL.Printf("INSERT INTO raster_pyramids "
                         "( table_prefix, pixel_x_size, pixel_y_size, tile_count ) "
                         "VALUES ( '%s', %.18f, %.18f, %d )",
                         osTableName.c_str(), padfXResolutions[0], padfYResolutions[0],
                         nBlocksMainRes);
            OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
        }

        osSQL.Printf("INSERT INTO raster_pyramids "
                     "( table_prefix, pixel_x_size, pixel_y_size, tile_count ) "
                     "VALUES ( '%s', %.18f, %.18f, %d )",
                     osTableName.c_str(), dfXResolution, dfYResolution,
                     nTotalBlocks);
        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
    }

    return eErr;
}
GDALDataset *
RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
                       int bStrict, char ** papszOptions, 
                       GDALProgressFunc pfnProgress, void * pProgressData )
{
    int nBands = poSrcDS->GetRasterCount();
    if (nBands == 0)
    {
        CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0");
        return NULL;
    }
    
    const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
    GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
    if ( hTileDriver == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
        return NULL;
    }
    
    GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
    if (hMemDriver == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
        return NULL;
    }   

    int nXSize = GDALGetRasterXSize(poSrcDS);
    int nYSize = GDALGetRasterYSize(poSrcDS);
    
    double adfGeoTransform[6];
    if (poSrcDS->GetGeoTransform(adfGeoTransform) != CE_None)
    {
        adfGeoTransform[0] = 0;
        adfGeoTransform[1] = 1;
        adfGeoTransform[2] = 0;
        adfGeoTransform[3] = 0;
        adfGeoTransform[4] = 0;
        adfGeoTransform[5] = -1;
    }
    else if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot use geotransform with rotational terms");
        return NULL;
    }

    int bTiled = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
    int nBlockXSize, nBlockYSize;
    if (bTiled)
    {
        nBlockXSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
        nBlockYSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
        if (nBlockXSize < 64) nBlockXSize = 64;
        else if (nBlockXSize > 4096)  nBlockXSize = 4096;
        if (nBlockYSize < 64) nBlockYSize = 64;
        else if (nBlockYSize > 4096)  nBlockYSize = 4096;
    }
    else
    {
        nBlockXSize = nXSize;
        nBlockYSize = nYSize;
    }
    
/* -------------------------------------------------------------------- */
/*      Analyze arguments                                               */
/* -------------------------------------------------------------------- */
    
    CPLString osDBName;
    CPLString osTableName;
    VSIStatBuf sBuf;
    int bExists;

    /* Skip optionnal RASTERLITE: prefix */
    const char* pszFilenameWithoutPrefix = pszFilename;
    if (EQUALN(pszFilename, "RASTERLITE:", 11))
        pszFilenameWithoutPrefix += 11;
    
    char** papszTokens = CSLTokenizeStringComplex( 
                pszFilenameWithoutPrefix, ", ", FALSE, FALSE );
    int nTokens = CSLCount(papszTokens);
    if (nTokens == 0)
    {
        osDBName = pszFilenameWithoutPrefix;
        osTableName = CPLGetBasename(pszFilenameWithoutPrefix);
    }
    else
    {
        osDBName = papszTokens[0];
        
        int i;
        for(i=1;i<nTokens;i++)
        {
            if (EQUALN(papszTokens[i], "table=", 6))
                osTableName = papszTokens[i] + 6;
            else
            {
                CPLError(CE_Warning, CPLE_AppDefined,
                         "Invalid option : %s", papszTokens[i]);
            }
        }
    }
    
    CSLDestroy(papszTokens);
    papszTokens = NULL;
    
    bExists = (VSIStat(osDBName.c_str(), &sBuf) == 0);

    if (osTableName.size() == 0)
    {
        if (bExists)
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "Database already exists. Explicit table name must be specified");
            return NULL;
        }
        osTableName = CPLGetBasename(osDBName.c_str());
    }    
    
    CPLString osRasterLayer;
    osRasterLayer.Printf("%s_rasters", osTableName.c_str());
    
    CPLString osMetatadataLayer;
    osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());

/* -------------------------------------------------------------------- */
/*      Create or open the SQLite DB                                    */
/* -------------------------------------------------------------------- */
    
    if (OGRGetDriverCount() == 0)
        OGRRegisterAll();
        
    OGRSFDriverH hSQLiteDriver = OGRGetDriverByName("SQLite");
    if (hSQLiteDriver == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load OGR SQLite driver");
        return NULL;
    }   
    
    OGRDataSourceH hDS;
    
    CPLString osOldVal =
        CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "FALSE");
    CPLSetConfigOption("SQLITE_LIST_ALL_TABLES", "TRUE");
    if (!bExists)
    {
        char** papszOGROptions = CSLAddString(NULL, "SPATIALITE=YES");
        hDS = OGR_Dr_CreateDataSource(hSQLiteDriver,
                                      osDBName.c_str(), papszOGROptions);
        CSLDestroy(papszOGROptions);
    }
    else
    {
        hDS = OGROpen(osDBName.c_str(), TRUE, NULL);
    }
    CPLSetConfigOption("SQLITE_LIST_ALL_TABLES", osOldVal.c_str());
    
    if (hDS == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "Cannot load or create SQLite database");
        return NULL;
    }

    CPLString osSQL;
    
/* -------------------------------------------------------------------- */
/*      Get the SRID for the SRS                                        */
/* -------------------------------------------------------------------- */
    int nSRSId = RasterliteInsertSRID(hDS, poSrcDS->GetProjectionRef());

/* -------------------------------------------------------------------- */
/*      Create or wipe existing tables                                  */
/* -------------------------------------------------------------------- */
    int bWipeExistingData =
        CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "WIPE", "NO"));
        
    hDS = RasterliteCreateTables(hDS, osTableName.c_str(),
                                 nSRSId, bWipeExistingData);
    if (hDS == NULL)
        return NULL;

    OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
    OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
    if (hRasterLayer == NULL || hMetadataLayer == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "Cannot find metadata and/or raster tables");
        OGRReleaseDataSource(hDS);
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Check if there is overlapping data and warn the user            */
/* -------------------------------------------------------------------- */
    double minx = adfGeoTransform[0];
    double maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1];
    double maxy = adfGeoTransform[3];
    double miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5];
    
    osSQL.Printf("SELECT COUNT(geometry) FROM \"%s\" "
                 "WHERE rowid IN "
                 "(SELECT pkid FROM \"idx_%s_metadata_geometry\" "
                  "WHERE xmin < %.15f AND xmax > %.15f "
                  "AND ymin < %.15f  AND ymax > %.15f) "
                 "AND pixel_x_size >= %.15f AND pixel_x_size <= %.15f AND "
                 "pixel_y_size >= %.15f AND pixel_y_size <= %.15f",
                  osMetatadataLayer.c_str(),
                  osTableName.c_str(),
                  maxx, minx, maxy, miny,
                  adfGeoTransform[1] - 1e-15, adfGeoTransform[1] + 1e-15,
                  - adfGeoTransform[5] - 1e-15, - adfGeoTransform[5] + 1e-15);
    
    int nOverlappingGeoms = 0;
    OGRLayerH hCountLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
    if (hCountLyr)
    {
        OGRFeatureH hFeat = OGR_L_GetNextFeature(hCountLyr);
        if (hFeat)
        {
            nOverlappingGeoms = OGR_F_GetFieldAsInteger(hFeat, 0);
            OGR_F_Destroy(hFeat);
        }
        OGR_DS_ReleaseResultSet(hDS, hCountLyr);
    }
    
    if (nOverlappingGeoms != 0)
    {
        CPLError(CE_Warning, CPLE_AppDefined,
                 "Raster tiles already exist in the %s table within "
                 "the extent of the data to be inserted in",
                 osTableName.c_str());
    }
   
/* -------------------------------------------------------------------- */
/*      Iterate over blocks to add data into raster and metadata tables */
/* -------------------------------------------------------------------- */
    int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize;
    int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize;

    GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
    GByte* pabyMEMDSBuffer =
        (GByte*)VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize);
    if (pabyMEMDSBuffer == NULL)
    {
        OGRReleaseDataSource(hDS);
        return NULL;
    }
    
    CPLString osTempFileName;
    osTempFileName.Printf("/vsimem/%p", hDS);
    
    int nTileId = 0;
    int nBlocks = 0;
    int nTotalBlocks = nXBlocks * nYBlocks;

    char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);
    
    OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
    
    CPLErr eErr = CE_None;
    int nBlockXOff, nBlockYOff;
    for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
    {
        for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
        {
/* -------------------------------------------------------------------- */
/*      Create in-memory tile                                           */
/* -------------------------------------------------------------------- */
            int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
            if ((nBlockXOff+1) * nBlockXSize > nXSize)
                nReqXSize = nXSize - nBlockXOff * nBlockXSize;
            if ((nBlockYOff+1) * nBlockYSize > nYSize)
                nReqYSize = nYSize - nBlockYOff * nBlockYSize;

            eErr = poSrcDS->RasterIO(GF_Read,
                                     nBlockXOff * nBlockXSize,
                                     nBlockYOff * nBlockYSize,
                                     nReqXSize, nReqYSize,
                                     pabyMEMDSBuffer, nReqXSize, nReqYSize,
                                     eDataType, nBands, NULL,
                                     0, 0, 0);
            if (eErr != CE_None)
            {
                break;
            }
            
            GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
                                              nReqXSize, nReqYSize, 0, 
                                              eDataType, NULL);
            if (hMemDS == NULL)
            {
                eErr = CE_Failure;
                break;
            }
            
            int iBand;
            for(iBand = 0; iBand < nBands; iBand ++)
            {
                char** papszMEMDSOptions = NULL;
                char szTmp[64];
                memset(szTmp, 0, sizeof(szTmp));
                CPLPrintPointer(szTmp,
                                pabyMEMDSBuffer + iBand * nDataTypeSize *
                                nReqXSize * nReqYSize, sizeof(szTmp));
                papszMEMDSOptions = CSLSetNameValue(papszMEMDSOptions, "DATAPOINTER", szTmp);
                GDALAddBand(hMemDS, eDataType, papszMEMDSOptions);
                CSLDestroy(papszMEMDSOptions);
            }
            
            GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
                                        osTempFileName.c_str(), hMemDS, FALSE,
                                        papszTileDriverOptions, NULL, NULL);

            GDALClose(hMemDS);
            if (hOutDS)
                GDALClose(hOutDS);
            else
            {
                eErr = CE_Failure;
                break;
            }

/* -------------------------------------------------------------------- */
/*      Insert new entry into raster table                              */
/* -------------------------------------------------------------------- */

            vsi_l_offset nDataLength;
            GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
                                                   &nDataLength, FALSE);

            OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
            OGR_F_SetFieldBinary(hFeat, 0, (int)nDataLength, pabyData);
            
            OGR_L_CreateFeature(hRasterLayer, hFeat);
            /* Query raster ID to set it as the ID of the associated metadata */
            int nRasterID = (int)OGR_F_GetFID(hFeat);
            
            OGR_F_Destroy(hFeat);
            
            VSIUnlink(osTempFileName.c_str());
            
/* -------------------------------------------------------------------- */
/*      Insert new entry into metadata table                            */
/* -------------------------------------------------------------------- */
            
            hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
            OGR_F_SetFID(hFeat, nRasterID);
            OGR_F_SetFieldString(hFeat, 0, GDALGetDescription(poSrcDS));
            OGR_F_SetFieldInteger(hFeat, 1, nTileId ++);
            OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
            OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
            OGR_F_SetFieldDouble(hFeat, 4, adfGeoTransform[1]);
            OGR_F_SetFieldDouble(hFeat, 5, -adfGeoTransform[5]);
            
            minx = adfGeoTransform[0] +
                (nBlockXSize * nBlockXOff) * adfGeoTransform[1];
            maxx = adfGeoTransform[0] +
                (nBlockXSize * nBlockXOff + nReqXSize) * adfGeoTransform[1];
            maxy = adfGeoTransform[3] +
                (nBlockYSize * nBlockYOff) * adfGeoTransform[5];
            miny = adfGeoTransform[3] +
                (nBlockYSize * nBlockYOff + nReqYSize) * adfGeoTransform[5];
            
            OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
            OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
            OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
            OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
            OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
            OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
            
            OGR_F_SetGeometryDirectly(hFeat, hRectangle);
            
            OGR_L_CreateFeature(hMetadataLayer, hFeat);
            OGR_F_Destroy(hFeat);
            
            nBlocks++;
            if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
                                            NULL, pProgressData))
                eErr = CE_Failure;
        }
    }
    
    if (eErr == CE_None)
        OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
    else
        OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
    
    CSLDestroy(papszTileDriverOptions);
    
    VSIFree(pabyMEMDSBuffer);
    
    OGRReleaseDataSource(hDS);
        
    return (GDALDataset*) GDALOpen(pszFilename, GA_Update);
}
CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
                                              int nOvrFactor,
                                              char** papszOptions,
                                              GDALProgressFunc pfnProgress,
                                              void * pProgressData)
{

    double dfXResolution = padfXResolutions[0] * nOvrFactor;
    double dfYResolution = padfXResolutions[0] * nOvrFactor;
    
    CPLString osSQL;

    int nOvrXSize = nRasterXSize / nOvrFactor;
    int nOvrYSize = nRasterYSize / nOvrFactor;
    
    if (nOvrXSize == 0 || nOvrYSize == 0)
        return CE_Failure;

    int bTiled = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
    int nBlockXSize, nBlockYSize;
    if (bTiled)
    {
        nBlockXSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
        nBlockYSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
        if (nBlockXSize < 64) nBlockXSize = 64;
        else if (nBlockXSize > 4096)  nBlockXSize = 4096;
        if (nBlockYSize < 64) nBlockYSize = 64;
        else if (nBlockYSize > 4096)  nBlockYSize = 4096;
    }
    else
    {
        nBlockXSize = nOvrXSize;
        nBlockYSize = nOvrYSize;
    }
    
    int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize;
    int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize;
    
    const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
    if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
    {
        CPLError(CE_Failure, CPLE_AppDefined, "GDAL %s driver cannot be used as underlying driver",
                 pszDriverName);
        return CE_Failure;
    }
    GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
    if (hTileDriver == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
        return CE_Failure;
    }

    GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
    if (hMemDriver == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
        return CE_Failure;
    }   

    GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
    GByte* pabyMEMDSBuffer =
        (GByte*)VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize);
    if (pabyMEMDSBuffer == NULL)
    {
        return CE_Failure;
    }
    
    CPLString osTempFileName;
    osTempFileName.Printf("/vsimem/%p", hDS);
    
    int nTileId = 0;
    int nBlocks = 0;
    int nTotalBlocks = nXBlocks * nYBlocks;
    
    CPLString osRasterLayer;
    osRasterLayer.Printf("%s_rasters", osTableName.c_str());
    
    CPLString osMetatadataLayer;
    osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
    
    OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
    OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
    
    CPLString osSourceName = "unknown";
    
    osSQL.Printf("SELECT source_name FROM \"%s\" WHERE "
                 "%s LIMIT 1",
                 osMetatadataLayer.c_str(),
                 RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
    if (hSQLLyr)
    {
        OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
        if (hFeat)
        {
            const char* pszVal = OGR_F_GetFieldAsString(hFeat, 0);
            if (pszVal)
                osSourceName = pszVal;
            OGR_F_Destroy(hFeat);
        }
        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
    }
    
/* -------------------------------------------------------------------- */
/*      Compute up to which existing overview level we can use for      */
/*      computing the requested overview                                */
/* -------------------------------------------------------------------- */
    int iLev;
    nLimitOvrCount = 0;
    for(iLev=1;iLev<nResolutions;iLev++)
    {
        if (!(padfXResolutions[iLev] < dfXResolution - 1e-10 &&
              padfYResolutions[iLev] < dfYResolution - 1e-10))
        {
            break;
        }
        nLimitOvrCount++;
    }
/* -------------------------------------------------------------------- */
/*      Allocate buffer for tile of previous overview level             */
/* -------------------------------------------------------------------- */

    GDALDataset* poPrevOvrLevel =
        (papoOverviews != NULL && iLev >= 2 && iLev <= nResolutions && papoOverviews[iLev-2]) ?
            papoOverviews[iLev-2] : this;
    double dfRatioPrevOvr = poPrevOvrLevel->GetRasterBand(1)->GetXSize() / nOvrXSize;
    int nPrevOvrBlockXSize = (int)(nBlockXSize * dfRatioPrevOvr + 0.5);
    int nPrevOvrBlockYSize = (int)(nBlockYSize * dfRatioPrevOvr + 0.5);
    GByte* pabyPrevOvrMEMDSBuffer = NULL;

    if( !EQUALN(pszResampling, "NEAR", 4))
    {
        pabyPrevOvrMEMDSBuffer =
            (GByte*)VSIMalloc3(nPrevOvrBlockXSize, nPrevOvrBlockYSize, nBands * nDataTypeSize);
        if (pabyPrevOvrMEMDSBuffer == NULL)
        {
            VSIFree(pabyMEMDSBuffer);
            return CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Iterate over blocks to add data into raster and metadata tables */
/* -------------------------------------------------------------------- */

    char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);

    OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
    
    CPLErr eErr = CE_None;
    int nBlockXOff, nBlockYOff;
    for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
    {
        for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
        {
            GDALDatasetH hPrevOvrMemDS = NULL;

/* -------------------------------------------------------------------- */
/*      Create in-memory tile                                           */
/* -------------------------------------------------------------------- */
            int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
            if ((nBlockXOff+1) * nBlockXSize > nOvrXSize)
                nReqXSize = nOvrXSize - nBlockXOff * nBlockXSize;
            if ((nBlockYOff+1) * nBlockYSize > nOvrYSize)
                nReqYSize = nOvrYSize - nBlockYOff * nBlockYSize;

            if( pabyPrevOvrMEMDSBuffer != NULL )
            {
                int nPrevOvrReqXSize =
                    (int)(nReqXSize * dfRatioPrevOvr + 0.5);
                int nPrevOvrReqYSize =
                    (int)(nReqYSize * dfRatioPrevOvr + 0.5);

                eErr = RasterIO(GF_Read,
                                nBlockXOff * nBlockXSize * nOvrFactor,
                                nBlockYOff * nBlockYSize * nOvrFactor,
                                nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
                                pabyPrevOvrMEMDSBuffer, nPrevOvrReqXSize, nPrevOvrReqYSize,
                                eDataType, nBands, NULL,
                                0, 0, 0, NULL);

                if (eErr != CE_None)
                {
                    break;
                }

                hPrevOvrMemDS = GDALCreate(hMemDriver, "MEM:::",
                                           nPrevOvrReqXSize, nPrevOvrReqYSize, 0,
                                           eDataType, NULL);

                if (hPrevOvrMemDS == NULL)
                {
                    eErr = CE_Failure;
                    break;
                }

                int iBand;
                for(iBand = 0; iBand < nBands; iBand ++)
                {
                    char** papszOptions = NULL;
                    char szTmp[64];
                    memset(szTmp, 0, sizeof(szTmp));
                    CPLPrintPointer(szTmp,
                                    pabyPrevOvrMEMDSBuffer + iBand * nDataTypeSize *
                                    nPrevOvrReqXSize * nPrevOvrReqYSize, sizeof(szTmp));
                    papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szTmp);
                    GDALAddBand(hPrevOvrMemDS, eDataType, papszOptions);
                    CSLDestroy(papszOptions);
                }
            }
            else
            {
                eErr = RasterIO(GF_Read,
                                nBlockXOff * nBlockXSize * nOvrFactor,
                                nBlockYOff * nBlockYSize * nOvrFactor,
                                nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
                                pabyMEMDSBuffer, nReqXSize, nReqYSize,
                                eDataType, nBands, NULL,
                                0, 0, 0, NULL);
                if (eErr != CE_None)
                {
                    break;
                }
            }

            GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
                                              nReqXSize, nReqYSize, 0, 
                                              eDataType, NULL);
            if (hMemDS == NULL)
            {
                eErr = CE_Failure;
                break;
            }
            
            int iBand;
            for(iBand = 0; iBand < nBands; iBand ++)
            {
                char** papszOptions = NULL;
                char szTmp[64];
                memset(szTmp, 0, sizeof(szTmp));
                CPLPrintPointer(szTmp,
                                pabyMEMDSBuffer + iBand * nDataTypeSize *
                                nReqXSize * nReqYSize, sizeof(szTmp));
                papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szTmp);
                GDALAddBand(hMemDS, eDataType, papszOptions);
                CSLDestroy(papszOptions);
            }

            if( hPrevOvrMemDS != NULL )
            {
                for(iBand = 0; iBand < nBands; iBand ++)
                {
                    GDALRasterBandH hDstOvrBand = GDALGetRasterBand(hMemDS, iBand+1);

                    eErr = GDALRegenerateOverviews( GDALGetRasterBand(hPrevOvrMemDS, iBand+1),
                                                    1, &hDstOvrBand,
                                                    pszResampling,
                                                    NULL, NULL );
                    if( eErr != CE_None )
                        break;
                }

                GDALClose(hPrevOvrMemDS);
            }

            GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
                                        osTempFileName.c_str(), hMemDS, FALSE,
                                        papszTileDriverOptions, NULL, NULL);

            GDALClose(hMemDS);
            if (hOutDS)
                GDALClose(hOutDS);
            else
            {
                eErr = CE_Failure;
                break;
            }

/* -------------------------------------------------------------------- */
/*      Insert new entry into raster table                              */
/* -------------------------------------------------------------------- */

            vsi_l_offset nDataLength;
            GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
                                                   &nDataLength, FALSE);

            OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
            OGR_F_SetFieldBinary(hFeat, 0, (int)nDataLength, pabyData);
            
            OGR_L_CreateFeature(hRasterLayer, hFeat);
            /* Query raster ID to set it as the ID of the associated metadata */
            int nRasterID = (int)OGR_F_GetFID(hFeat);
            
            OGR_F_Destroy(hFeat);
            
            VSIUnlink(osTempFileName.c_str());
            
/* -------------------------------------------------------------------- */
/*      Insert new entry into metadata table                            */
/* -------------------------------------------------------------------- */
            
            hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
            OGR_F_SetFID(hFeat, nRasterID);
            OGR_F_SetFieldString(hFeat, 0, osSourceName);
            OGR_F_SetFieldInteger(hFeat, 1, nTileId ++);
            OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
            OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
            OGR_F_SetFieldDouble(hFeat, 4, dfXResolution);
            OGR_F_SetFieldDouble(hFeat, 5, dfYResolution);
            
            double minx, maxx, maxy, miny;
            minx = adfGeoTransform[0] +
                (nBlockXSize * nBlockXOff) * dfXResolution;
            maxx = adfGeoTransform[0] +
                (nBlockXSize * nBlockXOff + nReqXSize) * dfXResolution;
            maxy = adfGeoTransform[3] +
                (nBlockYSize * nBlockYOff) * (-dfYResolution);
            miny = adfGeoTransform[3] +
                (nBlockYSize * nBlockYOff + nReqYSize) * (-dfYResolution);
            
            OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
            OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
            OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
            OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
            OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
            OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
            
            OGR_F_SetGeometryDirectly(hFeat, hRectangle);
            
            OGR_L_CreateFeature(hMetadataLayer, hFeat);
            OGR_F_Destroy(hFeat);
            
            nBlocks++;
            if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
                                            NULL, pProgressData))
                eErr = CE_Failure;
        }
    }

    nLimitOvrCount = -1;
    
    if (eErr == CE_None)
        OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
    else
        OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
    
    VSIFree(pabyMEMDSBuffer);
    VSIFree(pabyPrevOvrMEMDSBuffer);

    CSLDestroy(papszTileDriverOptions);
    papszTileDriverOptions = NULL;

/* -------------------------------------------------------------------- */
/*      Update raster_pyramids table                                    */
/* -------------------------------------------------------------------- */
    if (eErr == CE_None)
    {
        OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
        if (hRasterPyramidsLyr == NULL)
        {
            osSQL.Printf   ("CREATE TABLE raster_pyramids ("
                            "table_prefix TEXT NOT NULL,"
                            "pixel_x_size DOUBLE NOT NULL,"
                            "pixel_y_size DOUBLE NOT NULL,"
                            "tile_count INTEGER NOT NULL)");
            OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
            
            /* Re-open the DB to take into account the new tables*/
            OGRReleaseDataSource(hDS);
            
            hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), GA_Update);

            hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
            if (hRasterPyramidsLyr == NULL)
                return CE_Failure;
        }
        OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hRasterPyramidsLyr);

        /* Insert base resolution into raster_pyramids if not already done */
        int bHasBaseResolution = FALSE;
        osSQL.Printf("SELECT * FROM raster_pyramids WHERE "
                     "table_prefix = '%s' AND %s",
                     osTableName.c_str(),
                     RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
        hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
        if (hSQLLyr)
        {
            OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
            if (hFeat)
            {
                bHasBaseResolution = TRUE;
                OGR_F_Destroy(hFeat);
            }
            OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
        }

        if (!bHasBaseResolution)
        {
            osSQL.Printf("SELECT COUNT(*) FROM \"%s\" WHERE %s",
                          osMetatadataLayer.c_str(),
                          RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());

            int nBlocksMainRes = 0;

            hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
            if (hSQLLyr)
            {
                OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
                if (hFeat)
                {
                    nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0);
                    OGR_F_Destroy(hFeat);
                }
                OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
            }

            OGRFeatureH hFeat = OGR_F_Create( hFDefn );
            OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
            OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), padfXResolutions[0]);
            OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), padfYResolutions[0]);
            OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nBlocksMainRes);
            OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat);
            OGR_F_Destroy(hFeat);
        }

        OGRFeatureH hFeat = OGR_F_Create( hFDefn );
        OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
        OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), dfXResolution);
        OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), dfYResolution);
        OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nTotalBlocks);
        OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat);
        OGR_F_Destroy(hFeat);
    }

    return eErr;
}
示例#10
0
int msSaveImageGDAL( mapObj *map, imageObj *image, char *filename )

{
  int  bFileIsTemporary = MS_FALSE;
  GDALDatasetH hMemDS, hOutputDS;
  GDALDriverH  hMemDriver, hOutputDriver;
  int          nBands = 1;
  int          iLine;
  GByte       *pabyAlphaLine = NULL;
  char        **papszOptions = NULL;
  outputFormatObj *format = image->format;
  rasterBufferObj rb;
  GDALDataType eDataType = GDT_Byte;
  int bUseXmp = MS_FALSE;

  msGDALInitialize();
  memset(&rb,0,sizeof(rasterBufferObj));

#ifdef USE_EXEMPI
  if( map != NULL ) {
    bUseXmp = msXmpPresent(map);
  }
#endif


  /* -------------------------------------------------------------------- */
  /*      Identify the proposed output driver.                            */
  /* -------------------------------------------------------------------- */
  msAcquireLock( TLOCK_GDAL );
  hOutputDriver = GDALGetDriverByName( format->driver+5 );
  if( hOutputDriver == NULL ) {
    msReleaseLock( TLOCK_GDAL );
    msSetError( MS_MISCERR, "Failed to find %s driver.",
                "msSaveImageGDAL()", format->driver+5 );
    return MS_FAILURE;
  }

  /* -------------------------------------------------------------------- */
  /*      We will need to write the output to a temporary file and        */
  /*      then stream to stdout if no filename is passed.  If the         */
  /*      driver supports virtualio then we hold the temporary file in    */
  /*      memory, otherwise we try to put it in a reasonable temporary    */
  /*      file location.                                                  */
  /* -------------------------------------------------------------------- */
  if( filename == NULL ) {
    const char *pszExtension = format->extension;
    if( pszExtension == NULL )
      pszExtension = "img.tmp";

    if( bUseXmp == MS_FALSE && GDALGetMetadataItem( hOutputDriver, GDAL_DCAP_VIRTUALIO, NULL )
        != NULL ) {
      CleanVSIDir( "/vsimem/msout" );
      filename = msTmpFile(map, NULL, "/vsimem/msout/", pszExtension );
    }

    if( filename == NULL && map != NULL)
      filename = msTmpFile(map, map->mappath,NULL,pszExtension);
    else if( filename == NULL ) {
      filename = msTmpFile(map, NULL, NULL, pszExtension );
    }

    bFileIsTemporary = MS_TRUE;
  }

  /* -------------------------------------------------------------------- */
  /*      Establish the characteristics of our memory, and final          */
  /*      dataset.                                                        */
  /* -------------------------------------------------------------------- */

  if( format->imagemode == MS_IMAGEMODE_RGB ) {
    nBands = 3;
    assert( MS_RENDERER_PLUGIN(format) && format->vtable->supports_pixel_buffer );
    format->vtable->getRasterBufferHandle(image,&rb);
  } else if( format->imagemode == MS_IMAGEMODE_RGBA ) {
    pabyAlphaLine = (GByte *) calloc(image->width,1);
    if (pabyAlphaLine == NULL) {
      msReleaseLock( TLOCK_GDAL );
      msSetError( MS_MEMERR, "Out of memory allocating %u bytes.\n", "msSaveImageGDAL()", image->width);
      return MS_FAILURE;
    }
    nBands = 4;
    assert( MS_RENDERER_PLUGIN(format) && format->vtable->supports_pixel_buffer );
    format->vtable->getRasterBufferHandle(image,&rb);
  } else if( format->imagemode == MS_IMAGEMODE_INT16 ) {
    nBands = format->bands;
    eDataType = GDT_Int16;
  } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) {
    nBands = format->bands;
    eDataType = GDT_Float32;
  } else if( format->imagemode == MS_IMAGEMODE_BYTE ) {
    nBands = format->bands;
    eDataType = GDT_Byte;
  } else {
#ifdef USE_GD
    assert( format->imagemode == MS_IMAGEMODE_PC256
            && format->renderer == MS_RENDER_WITH_GD );
#else
    {
      msReleaseLock( TLOCK_GDAL );
      msSetError( MS_MEMERR, "GD not compiled in. This is a bug.", "msSaveImageGDAL()");
      return MS_FAILURE;
    }
#endif

  }

  /* -------------------------------------------------------------------- */
  /*      Create a memory dataset which we can use as a source for a      */
  /*      CreateCopy().                                                   */
  /* -------------------------------------------------------------------- */
  hMemDriver = GDALGetDriverByName( "MEM" );
  if( hMemDriver == NULL ) {
    msReleaseLock( TLOCK_GDAL );
    msSetError( MS_MISCERR, "Failed to find MEM driver.",
                "msSaveImageGDAL()" );
    return MS_FAILURE;
  }

  hMemDS = GDALCreate( hMemDriver, "msSaveImageGDAL_temp",
                       image->width, image->height, nBands,
                       eDataType, NULL );
  if( hMemDS == NULL ) {
    msReleaseLock( TLOCK_GDAL );
    msSetError( MS_MISCERR, "Failed to create MEM dataset.",
                "msSaveImageGDAL()" );
    return MS_FAILURE;
  }

  /* -------------------------------------------------------------------- */
  /*      Copy the gd image into the memory dataset.                      */
  /* -------------------------------------------------------------------- */
  for( iLine = 0; iLine < image->height; iLine++ ) {
    int iBand;

    for( iBand = 0; iBand < nBands; iBand++ ) {
      GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 );

      if( format->imagemode == MS_IMAGEMODE_INT16 ) {
        GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                      image->img.raw_16bit + iLine * image->width
                      + iBand * image->width * image->height,
                      image->width, 1, GDT_Int16, 2, 0 );

      } else if( format->imagemode == MS_IMAGEMODE_FLOAT32 ) {
        GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                      image->img.raw_float + iLine * image->width
                      + iBand * image->width * image->height,
                      image->width, 1, GDT_Float32, 4, 0 );
      } else if( format->imagemode == MS_IMAGEMODE_BYTE ) {
        GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                      image->img.raw_byte + iLine * image->width
                      + iBand * image->width * image->height,
                      image->width, 1, GDT_Byte, 1, 0 );
      }
#ifdef USE_GD
      else if(format->renderer == MS_RENDER_WITH_GD) {
        gdImagePtr img = (gdImagePtr)image->img.plugin;
        GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                      img->pixels[iLine],
                      image->width, 1, GDT_Byte, 0, 0 );
      }
#endif
      else {
        GByte *pabyData;
        unsigned char *pixptr = NULL;
        assert( rb.type == MS_BUFFER_BYTE_RGBA );
        switch(iBand) {
          case 0:
            pixptr = rb.data.rgba.r;
            break;
          case 1:
            pixptr = rb.data.rgba.g;
            break;
          case 2:
            pixptr = rb.data.rgba.b;
            break;
          case 3:
            pixptr = rb.data.rgba.a;
            break;
        }
        assert(pixptr);
        if( pixptr == NULL ) {
          msReleaseLock( TLOCK_GDAL );
          msSetError( MS_MISCERR, "Missing RGB or A buffer.\n",
                      "msSaveImageGDAL()" );
          return MS_FAILURE;
        }

        pabyData = (GByte *)(pixptr + iLine*rb.data.rgba.row_step);

        if( rb.data.rgba.a == NULL || iBand == 3 ) {
          GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                        pabyData, image->width, 1, GDT_Byte,
                        rb.data.rgba.pixel_step, 0 );
        } else { /* We need to un-pre-multiple RGB by alpha. */
          GByte *pabyUPM = (GByte*) malloc(image->width);
          GByte *pabyAlpha= (GByte *)(rb.data.rgba.a + iLine*rb.data.rgba.row_step);
          int i;

          for( i = 0; i < image->width; i++ ) {
            int alpha = pabyAlpha[i*rb.data.rgba.pixel_step];

            if( alpha == 0 )
              pabyUPM[i] = 0;
            else {
              int result = (pabyData[i*rb.data.rgba.pixel_step] * 255) / alpha;

              if( result > 255 )
                result = 255;

              pabyUPM[i] = result;
            }
          }

          GDALRasterIO( hBand, GF_Write, 0, iLine, image->width, 1,
                        pabyUPM, image->width, 1, GDT_Byte, 1, 0 );
          free( pabyUPM );
        }
      }
    }
  }

  if( pabyAlphaLine != NULL )
    free( pabyAlphaLine );

  /* -------------------------------------------------------------------- */
  /*      Attach the palette if appropriate.                              */
  /* -------------------------------------------------------------------- */
#ifdef USE_GD
  if( format->renderer == MS_RENDER_WITH_GD ) {
    GDALColorEntry sEntry;
    int  iColor;
    GDALColorTableH hCT;
    gdImagePtr img = (gdImagePtr)image->img.plugin;
    hCT = GDALCreateColorTable( GPI_RGB );

    for( iColor = 0; iColor < img->colorsTotal; iColor++ ) {
      sEntry.c1 = img->red[iColor];
      sEntry.c2 = img->green[iColor];
      sEntry.c3 = img->blue[iColor];

      if( iColor == gdImageGetTransparent( img ) )
        sEntry.c4 = 0;
      else if( iColor == 0
               && gdImageGetTransparent( img ) == -1
               && format->transparent )
        sEntry.c4 = 0;
      else
        sEntry.c4 = 255;

      GDALSetColorEntry( hCT, iColor, &sEntry );
    }

    GDALSetRasterColorTable( GDALGetRasterBand( hMemDS, 1 ), hCT );

    GDALDestroyColorTable( hCT );
  } else
#endif
    if( format->imagemode == MS_IMAGEMODE_RGB ) {
      GDALSetRasterColorInterpretation(
        GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand );
      GDALSetRasterColorInterpretation(
        GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand );
      GDALSetRasterColorInterpretation(
        GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand );
    } else if( format->imagemode == MS_IMAGEMODE_RGBA ) {
      GDALSetRasterColorInterpretation(
        GDALGetRasterBand( hMemDS, 1 ), GCI_RedBand );
      GDALSetRasterColorInterpretation(
        GDALGetRasterBand( hMemDS, 2 ), GCI_GreenBand );
      GDALSetRasterColorInterpretation(
        GDALGetRasterBand( hMemDS, 3 ), GCI_BlueBand );
      GDALSetRasterColorInterpretation(
        GDALGetRasterBand( hMemDS, 4 ), GCI_AlphaBand );
    }

  /* -------------------------------------------------------------------- */
  /*      Assign the projection and coordinate system to the memory       */
  /*      dataset.                                                        */
  /* -------------------------------------------------------------------- */

  if( map != NULL ) {
    char *pszWKT;

    GDALSetGeoTransform( hMemDS, map->gt.geotransform );

    pszWKT = msProjectionObj2OGCWKT( &(map->projection) );
    if( pszWKT != NULL ) {
      GDALSetProjection( hMemDS, pszWKT );
      msFree( pszWKT );
    }
  }

  /* -------------------------------------------------------------------- */
  /*      Possibly assign a nodata value.                                 */
  /* -------------------------------------------------------------------- */
  if( msGetOutputFormatOption(format,"NULLVALUE",NULL) != NULL ) {
    int iBand;
    const char *nullvalue = msGetOutputFormatOption(format,
                            "NULLVALUE",NULL);

    for( iBand = 0; iBand < nBands; iBand++ ) {
      GDALRasterBandH hBand = GDALGetRasterBand( hMemDS, iBand+1 );
      GDALSetRasterNoDataValue( hBand, atof(nullvalue) );
    }
  }

  /* -------------------------------------------------------------------- */
  /*  Try to save resolution in the output file.                          */
  /* -------------------------------------------------------------------- */
  if( image->resolution > 0 ) {
    char res[30];

    sprintf( res, "%lf", image->resolution );
    GDALSetMetadataItem( hMemDS, "TIFFTAG_XRESOLUTION", res, NULL );
    GDALSetMetadataItem( hMemDS, "TIFFTAG_YRESOLUTION", res, NULL );
    GDALSetMetadataItem( hMemDS, "TIFFTAG_RESOLUTIONUNIT", "2", NULL );
  }

  /* -------------------------------------------------------------------- */
  /*      Create a disk image in the selected output format from the      */
  /*      memory image.                                                   */
  /* -------------------------------------------------------------------- */
  papszOptions = (char**)calloc(sizeof(char *),(format->numformatoptions+1));
  if (papszOptions == NULL) {
    msReleaseLock( TLOCK_GDAL );
    msSetError( MS_MEMERR, "Out of memory allocating %u bytes.\n", "msSaveImageGDAL()",
                (unsigned int)(sizeof(char *)*(format->numformatoptions+1)));
    return MS_FAILURE;
  }

  memcpy( papszOptions, format->formatoptions,
          sizeof(char *) * format->numformatoptions );

  hOutputDS = GDALCreateCopy( hOutputDriver, filename, hMemDS, FALSE,
                              papszOptions, NULL, NULL );

  free( papszOptions );

  if( hOutputDS == NULL ) {
    GDALClose( hMemDS );
    msReleaseLock( TLOCK_GDAL );
    msSetError( MS_MISCERR, "Failed to create output %s file.\n%s",
                "msSaveImageGDAL()", format->driver+5,
                CPLGetLastErrorMsg() );
    return MS_FAILURE;
  }

  /* closing the memory DS also frees all associated resources. */
  GDALClose( hMemDS );

  GDALClose( hOutputDS );
  msReleaseLock( TLOCK_GDAL );


  /* -------------------------------------------------------------------- */
  /*      Are we writing license info into the image?                     */
  /*      If so, add it to the temp file on disk now.                     */
  /* -------------------------------------------------------------------- */
#ifdef USE_EXEMPI
  if ( bUseXmp == MS_TRUE ) {
    if( msXmpWrite(map, filename) == MS_FAILURE ) {
      /* Something bad happened. */
      msSetError( MS_MISCERR, "XMP write to %s failed.\n",
                  "msSaveImageGDAL()", filename);
      return MS_FAILURE;
    }
  }
#endif

  /* -------------------------------------------------------------------- */
  /*      Is this supposed to be a temporary file?  If so, stream to      */
  /*      stdout and delete the file.                                     */
  /* -------------------------------------------------------------------- */
  if( bFileIsTemporary ) {
    FILE *fp;
    unsigned char block[4000];
    int bytes_read;

    if( msIO_needBinaryStdout() == MS_FAILURE )
      return MS_FAILURE;

    /* We aren't sure how far back GDAL exports the VSI*L API, so
       we only use it if we suspect we need it.  But we do need it if
       holding temporary file in memory. */
    fp = VSIFOpenL( filename, "rb" );
    if( fp == NULL ) {
      msSetError( MS_MISCERR,
                  "Failed to open %s for streaming to stdout.",
                  "msSaveImageGDAL()", filename );
      return MS_FAILURE;
    }

    while( (bytes_read = VSIFReadL(block, 1, sizeof(block), fp)) > 0 )
      msIO_fwrite( block, 1, bytes_read, stdout );

    VSIFCloseL( fp );

    VSIUnlink( filename );
    CleanVSIDir( "/vsimem/msout" );

    free( filename );
  }

  return MS_SUCCESS;
}
示例#11
0
int main( int argc, char *argv[] )
{
	if( argc < 5 ) {
		usage();
		return 1;
	}
	int 	i, row, col;
	char	*in[MAXFILES];
	char	*out;
	int 	imgs_per_year;
	int		n_imgs;
	int 	n_null_pix;
	GDALDatasetH hD[MAXFILES+1];
	GDALAllRegister();
	GDALDriverH hDr[MAXFILES+1];
	GDALRasterBandH hB[MAXFILES+1];
	float *l[MAXFILES+1];
	int nX, nY;

	out	 	= argv[1];

	printf("Loading input files:\n");
	n_imgs = argc - 2;
	for (i=0;i<n_imgs;i++){
		printf("%i / %i %s\r",i,n_imgs,argv[i+2]);
		in[i]	= argv[i+2];
		hD[i]	= GDALOpen(in[i],GA_ReadOnly);
		hDr[i]	= GDALGetDatasetDriver(hD[i]);
		hB[i]	= GDALGetRasterBand(hD[i],1);
		nX		= GDALGetRasterBandXSize(hB[0]);
		l[i]	= (float *) malloc(sizeof(float)*nX);
	}
	nY = GDALGetRasterBandYSize(hB[0]);

	//Creating output file 
	hD[n_imgs] = GDALCreateCopy( hDr[0], out,hD[0],FALSE,NULL,NULL,NULL);
	hB[n_imgs] = GDALGetRasterBand(hD[n_imgs],1);
	l[n_imgs] = (float *) malloc(sizeof(float)*nX);
	
	//Accessing the data rowxrow
	//---------------------------
	for(row=0;row<nY;row++){
		for (i=0;i<n_imgs;i++){
			GDALRasterIO(hB[i],GF_Read,0,row,nX,1,l[i],nX,1,GDT_Float32,0,0);
		}
		//Processing the data cellxcell
		//-----------------------------
		for(col=0;col<nX;col++){
			if(l[i][col] < 0) l[n_imgs][col] = -28768 ;
			else{
				l[n_imgs][col] = 0.0;
				n_null_pix = 0;
				for (i=0;i<n_imgs;i++){
					if(l[i][col] > 1) n_null_pix++;
					else l[n_imgs][col] += l[i][col];
				}
				l[n_imgs][col] /= (n_imgs - n_null_pix);
			}
		}
		for(col=0;col<nX;col++){
				l[n_imgs][col] *= 32000 ;
				/*to recover any positive pixel*/
				//if(l[n_imgs][col]>0&&l[n_imgs][col]<1)
				//	l[n_imgs][col]=1;
		}
		GDALRasterIO(hB[n_imgs],GF_Write,0,row,nX,1,l[n_imgs],nX,1,GDT_Float32,0,0);
	}
	for (i=0;i<n_imgs+1;i++){
		if( l[i] != NULL ) free( l[i] );
		GDALClose(hD[i]);
	}
}
static int ProxyMain(int argc, char **argv)

{
    GDALDatasetH     hDataset, hOutDS;
    int              i;
    int              nRasterXSize, nRasterYSize;
    const char       *pszSource = NULL, *pszDest = NULL, *pszFormat = "GTiff";
    GDALDriverH      hDriver;
    int              *panBandList = NULL;    /* negative value of panBandList[i] means mask band of ABS(panBandList[i]) */
    int              nBandCount   = 0, bDefBands = TRUE;
    double           adfGeoTransform[6];
    GDALDataType     eOutputType          = GDT_Unknown;
    int              nOXSize              = 0, nOYSize = 0;
    char             *pszOXSize           = NULL, *pszOYSize = NULL;
    char             **papszCreateOptions = NULL;
    int              anSrcWin[4], bStrict = FALSE;
    const char       *pszProjection;
    int              bScale        = FALSE, bHaveScaleSrc = FALSE, bUnscale = FALSE;
    double           dfScaleSrcMin = 0.0, dfScaleSrcMax = 255.0;
    double           dfScaleDstMin = 0.0, dfScaleDstMax = 255.0;
    double           dfULX, dfULY, dfLRX, dfLRY;
    char             **papszMetadataOptions = NULL;
    char             *pszOutputSRS          = NULL;
    int              bQuiet                 = FALSE, bGotBounds = FALSE;
    GDALProgressFunc pfnProgress            = GDALTermProgress;
    int              nGCPCount              = 0;
    GDAL_GCP         *pasGCPs               = NULL;
    int              iSrcFileArg            = -1, iDstFileArg = -1;
    int              bCopySubDatasets       = FALSE;
    double           adfULLR[4]             = { 0, 0, 0, 0 };
    int              bSetNoData             = FALSE;
    int              bUnsetNoData           = FALSE;
    double           dfNoDataReal           = 0.0;
    int              nRGBExpand             = 0;
    int              bParsedMaskArgument    = FALSE;
    int              eMaskMode              = MASK_AUTO;
    int              nMaskBand              = 0; /* negative value means mask band of ABS(nMaskBand) */
    int              bStats                 = FALSE, bApproxStats = FALSE;


    anSrcWin[0] = 0;
    anSrcWin[1] = 0;
    anSrcWin[2] = 0;
    anSrcWin[3] = 0;

    dfULX = dfULY = dfLRX = dfLRY = 0.0;

    /* Check strict compilation and runtime library version as we use C++ API */
    if (!GDAL_CHECK_VERSION(argv[0]))
        exit(1);

    /* Must process GDAL_SKIP before GDALAllRegister(), but we can't call */
    /* GDALGeneralCmdLineProcessor before it needs the drivers to be registered */
    /* for the --format or --formats options */
    for (i = 1; i < argc; i++)
    {
        if (EQUAL(argv[i], "--config") && i + 2 < argc && EQUAL(argv[i + 1], "GDAL_SKIP"))
        {
            CPLSetConfigOption(argv[i + 1], argv[i + 2]);

            i += 2;
        }
    }

/* -------------------------------------------------------------------- */
/*      Register standard GDAL drivers, and process generic GDAL        */
/*      command options.                                                */
/* -------------------------------------------------------------------- */
    GDALAllRegister();
    argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
    if (argc < 1)
        exit(-argc);

/* -------------------------------------------------------------------- */
/*      Handle command line arguments.                                  */
/* -------------------------------------------------------------------- */
    for (i = 1; i < argc; i++)
    {
        if (EQUAL(argv[i], "--utility_version"))
        {
            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
            return 0;
        }
        else if (EQUAL(argv[i], "-of") && i < argc - 1)
            pszFormat = argv[++i];

        else if (EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet"))
        {
            bQuiet      = TRUE;
            pfnProgress = GDALDummyProgress;
        }

        else if (EQUAL(argv[i], "-ot") && i < argc - 1)
        {
            int iType;

            for (iType = 1; iType < GDT_TypeCount; iType++)
            {
                if (GDALGetDataTypeName((GDALDataType)iType) != NULL
                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
                             argv[i + 1]))
                {
                    eOutputType = (GDALDataType) iType;
                }
            }

            if (eOutputType == GDT_Unknown)
            {
                printf("Unknown output pixel type: %s\n", argv[i + 1]);
                Usage();
                GDALDestroyDriverManager();
                exit(2);
            }

            i++;
        }
        else if (EQUAL(argv[i], "-b") && i < argc - 1)
        {
            const char *pszBand = argv[i + 1];
            int        bMask    = FALSE;
            if (EQUAL(pszBand, "mask"))
                pszBand = "mask,1";

            if (EQUALN(pszBand, "mask,", 5))
            {
                bMask    = TRUE;
                pszBand += 5;
                /* If we use tha source mask band as a regular band */
                /* don't create a target mask band by default */
                if (!bParsedMaskArgument)
                    eMaskMode = MASK_DISABLED;
            }

            int nBand = atoi(pszBand);
            if (nBand < 1)
            {
                printf("Unrecognizable band number (%s).\n", argv[i + 1]);
                Usage();
                GDALDestroyDriverManager();
                exit(2);
            }

            i++;

            nBandCount++;
            panBandList = (int*)
                          CPLRealloc(panBandList, sizeof(int) * nBandCount);
            panBandList[nBandCount - 1] = nBand;
            if (bMask)
                panBandList[nBandCount - 1] *= -1;

            if (panBandList[nBandCount - 1] != nBandCount)
                bDefBands = FALSE;
        }
        else if (EQUAL(argv[i], "-mask") && i < argc - 1)
        {
            bParsedMaskArgument = TRUE;
            const char *pszBand = argv[i + 1];
            if (EQUAL(pszBand, "none"))
            {
                eMaskMode = MASK_DISABLED;
            }
            else if (EQUAL(pszBand, "auto"))
            {
                eMaskMode = MASK_AUTO;
            }
            else
            {
                int bMask = FALSE;
                if (EQUAL(pszBand, "mask"))
                    pszBand = "mask,1";

                if (EQUALN(pszBand, "mask,", 5))
                {
                    bMask    = TRUE;
                    pszBand += 5;
                }

                int nBand = atoi(pszBand);
                if (nBand < 1)
                {
                    printf("Unrecognizable band number (%s).\n", argv[i + 1]);
                    Usage();
                    GDALDestroyDriverManager();
                    exit(2);
                }

                eMaskMode = MASK_USER;
                nMaskBand = nBand;
                if (bMask)
                    nMaskBand *= -1;
            }

            i++;
        }
        else if (EQUAL(argv[i], "-not_strict"))
            bStrict = FALSE;

        else if (EQUAL(argv[i], "-strict"))
            bStrict = TRUE;

        else if (EQUAL(argv[i], "-sds"))
            bCopySubDatasets = TRUE;

        else if (EQUAL(argv[i], "-gcp") && i < argc - 4)
        {
            char *endptr = NULL;
            /* -gcp pixel line easting northing [elev] */

            nGCPCount++;
            pasGCPs = (GDAL_GCP*)
                      CPLRealloc(pasGCPs, sizeof(GDAL_GCP) * nGCPCount);
            GDALInitGCPs(1, pasGCPs + nGCPCount - 1);

            pasGCPs[nGCPCount - 1].dfGCPPixel = CPLAtofM(argv[++i]);
            pasGCPs[nGCPCount - 1].dfGCPLine  = CPLAtofM(argv[++i]);
            pasGCPs[nGCPCount - 1].dfGCPX     = CPLAtofM(argv[++i]);
            pasGCPs[nGCPCount - 1].dfGCPY     = CPLAtofM(argv[++i]);
            if (argv[i + 1] != NULL
                && (CPLStrtod(argv[i + 1], &endptr) != 0.0 || argv[i + 1][0] == '0'))
            {
                /* Check that last argument is really a number and not a filename */
                /* looking like a number (see ticket #863) */
                if (endptr && *endptr == 0)
                    pasGCPs[nGCPCount - 1].dfGCPZ = CPLAtofM(argv[++i]);
            }

            /* should set id and info? */
        }

        else if (EQUAL(argv[i], "-a_nodata") && i < argc - 1)
        {
            if (EQUAL(argv[i + 1], "none"))
            {
                bUnsetNoData = TRUE;
            }
            else
            {
                bSetNoData   = TRUE;
                dfNoDataReal = CPLAtofM(argv[i + 1]);
            }

            i += 1;
        }

        else if (EQUAL(argv[i], "-a_ullr") && i < argc - 4)
        {
            adfULLR[0] = CPLAtofM(argv[i + 1]);
            adfULLR[1] = CPLAtofM(argv[i + 2]);
            adfULLR[2] = CPLAtofM(argv[i + 3]);
            adfULLR[3] = CPLAtofM(argv[i + 4]);

            bGotBounds = TRUE;

            i += 4;
        }

        else if (EQUAL(argv[i], "-co") && i < argc - 1)
        {
            papszCreateOptions = CSLAddString(papszCreateOptions, argv[++i]);
        }

        else if (EQUAL(argv[i], "-scale"))
        {
            bScale = TRUE;
            if (i < argc - 2 && ArgIsNumeric(argv[i + 1]))
            {
                bHaveScaleSrc = TRUE;
                dfScaleSrcMin = CPLAtofM(argv[i + 1]);
                dfScaleSrcMax = CPLAtofM(argv[i + 2]);
                i            += 2;
            }

            if (i < argc - 2 && bHaveScaleSrc && ArgIsNumeric(argv[i + 1]))
            {
                dfScaleDstMin = CPLAtofM(argv[i + 1]);
                dfScaleDstMax = CPLAtofM(argv[i + 2]);
                i            += 2;
            }
            else
            {
                dfScaleDstMin = 0.0;
                dfScaleDstMax = 255.999;
            }
        }

        else if (EQUAL(argv[i], "-unscale"))
        {
            bUnscale = TRUE;
        }

        else if (EQUAL(argv[i], "-mo") && i < argc - 1)
        {
            papszMetadataOptions = CSLAddString(papszMetadataOptions,
                                                argv[++i]);
        }

        else if (EQUAL(argv[i], "-outsize") && i < argc - 2)
        {
            pszOXSize = argv[++i];
            pszOYSize = argv[++i];
        }

        else if (EQUAL(argv[i], "-srcwin") && i < argc - 4)
        {
            anSrcWin[0] = atoi(argv[++i]);
            anSrcWin[1] = atoi(argv[++i]);
            anSrcWin[2] = atoi(argv[++i]);
            anSrcWin[3] = atoi(argv[++i]);
        }

        else if (EQUAL(argv[i], "-projwin") && i < argc - 4)
        {
            dfULX = CPLAtofM(argv[++i]);
            dfULY = CPLAtofM(argv[++i]);
            dfLRX = CPLAtofM(argv[++i]);
            dfLRY = CPLAtofM(argv[++i]);
        }

        else if (EQUAL(argv[i], "-a_srs") && i < argc - 1)
        {
            OGRSpatialReference oOutputSRS;

            if (oOutputSRS.SetFromUserInput(argv[i + 1]) != OGRERR_NONE)
            {
                fprintf(stderr, "Failed to process SRS definition: %s\n",
                        argv[i + 1]);
                GDALDestroyDriverManager();
                exit(1);
            }

            oOutputSRS.exportToWkt(&pszOutputSRS);
            i++;
        }

        else if (EQUAL(argv[i], "-expand") && i < argc - 1)
        {
            if (EQUAL(argv[i + 1], "gray"))
                nRGBExpand = 1;
            else if (EQUAL(argv[i + 1], "rgb"))
                nRGBExpand = 3;
            else if (EQUAL(argv[i + 1], "rgba"))
                nRGBExpand = 4;
            else
            {
                printf("Value %s unsupported. Only gray, rgb or rgba are supported.\n\n",
                       argv[i]);
                Usage();
                GDALDestroyDriverManager();
                exit(2);
            }

            i++;
        }

        else if (EQUAL(argv[i], "-stats"))
        {
            bStats       = TRUE;
            bApproxStats = FALSE;
        }
        else if (EQUAL(argv[i], "-approx_stats"))
        {
            bStats       = TRUE;
            bApproxStats = TRUE;
        }

        else if (argv[i][0] == '-')
        {
            printf("Option %s incomplete, or not recognised.\n\n",
                   argv[i]);
            Usage();
            GDALDestroyDriverManager();
            exit(2);
        }
        else if (pszSource == NULL)
        {
            iSrcFileArg = i;
            pszSource   = argv[i];
        }
        else if (pszDest == NULL)
        {
            pszDest     = argv[i];
            iDstFileArg = i;
        }

        else
        {
            printf("Too many command options.\n\n");
            Usage();
            GDALDestroyDriverManager();
            exit(2);
        }
    }

    if (pszDest == NULL)
    {
        Usage();
        GDALDestroyDriverManager();
        exit(10);
    }

    if (strcmp(pszSource, pszDest) == 0)
    {
        fprintf(stderr, "Source and destination datasets must be different.\n");
        GDALDestroyDriverManager();
        exit(1);
    }

    if (strcmp(pszDest, "/vsistdout/") == 0)
    {
        bQuiet      = TRUE;
        pfnProgress = GDALDummyProgress;
    }

/* -------------------------------------------------------------------- */
/*      Attempt to open source file.                                    */
/* -------------------------------------------------------------------- */

    hDataset = GDALOpenShared(pszSource, GA_ReadOnly);

    if (hDataset == NULL)
    {
        fprintf(stderr,
                "GDALOpen failed - %d\n%s\n",
                CPLGetLastErrorNo(), CPLGetLastErrorMsg());
        GDALDestroyDriverManager();
        exit(1);
    }

/* -------------------------------------------------------------------- */
/*      Handle subdatasets.                                             */
/* -------------------------------------------------------------------- */
    if (!bCopySubDatasets
        && CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0
        && GDALGetRasterCount(hDataset) == 0)
    {
        fprintf(stderr,
                "Input file contains subdatasets. Please, select one of them for reading.\n");
        GDALClose(hDataset);
        GDALDestroyDriverManager();
        exit(1);
    }

    if (CSLCount(GDALGetMetadata(hDataset, "SUBDATASETS")) > 0
        && bCopySubDatasets)
    {
        char **papszSubdatasets = GDALGetMetadata(hDataset, "SUBDATASETS");
        char *pszSubDest        = (char*) CPLMalloc(strlen(pszDest) + 32);
        int  i;
        int  bOldSubCall    = bSubCall;
        char **papszDupArgv = CSLDuplicate(argv);
        int  nRet           = 0;

        CPLFree(papszDupArgv[iDstFileArg]);
        papszDupArgv[iDstFileArg] = pszSubDest;
        bSubCall                  = TRUE;

        for (i = 0; papszSubdatasets[i] != NULL; i += 2)
        {
            CPLFree(papszDupArgv[iSrcFileArg]);
            papszDupArgv[iSrcFileArg] = CPLStrdup(strstr(papszSubdatasets[i], "=") + 1);
            sprintf(pszSubDest, "%s%d", pszDest, i / 2 + 1);
            nRet = ProxyMain(argc, papszDupArgv);
            if (nRet != 0)
                break;
        }

        CSLDestroy(papszDupArgv);

        bSubCall = bOldSubCall;
        CSLDestroy(argv);

        GDALClose(hDataset);

        if (!bSubCall)
        {
            GDALDumpOpenDatasets(stderr);
            GDALDestroyDriverManager();
        }

        return nRet;
    }

/* -------------------------------------------------------------------- */
/*      Collect some information from the source file.                  */
/* -------------------------------------------------------------------- */
    nRasterXSize = GDALGetRasterXSize(hDataset);
    nRasterYSize = GDALGetRasterYSize(hDataset);

    if (!bQuiet)
        printf("Input file size is %d, %d\n", nRasterXSize, nRasterYSize);

    if (anSrcWin[2] == 0 && anSrcWin[3] == 0)
    {
        anSrcWin[2] = nRasterXSize;
        anSrcWin[3] = nRasterYSize;
    }

/* -------------------------------------------------------------------- */
/*      Build band list to translate                                    */
/* -------------------------------------------------------------------- */
    if (nBandCount == 0)
    {
        nBandCount = GDALGetRasterCount(hDataset);
        if (nBandCount == 0)
        {
            fprintf(stderr, "Input file has no bands, and so cannot be translated.\n");
            GDALDestroyDriverManager();
            exit(1);
        }

        panBandList = (int*) CPLMalloc(sizeof(int) * nBandCount);

        for (i = 0; i < nBandCount; i++)
            panBandList[i] = i + 1;
    }
    else
    {
        for (i = 0; i < nBandCount; i++)
        {
            if (ABS(panBandList[i]) > GDALGetRasterCount(hDataset))
            {
                fprintf(stderr,
                        "Band %d requested, but only bands 1 to %d available.\n",
                        ABS(panBandList[i]), GDALGetRasterCount(hDataset));
                GDALDestroyDriverManager();
                exit(2);
            }
        }

        if (nBandCount != GDALGetRasterCount(hDataset))
            bDefBands = FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Compute the source window from the projected source window      */
/*      if the projected coordinates were provided.  Note that the      */
/*      projected coordinates are in ulx, uly, lrx, lry format,         */
/*      while the anSrcWin is xoff, yoff, xsize, ysize with the         */
/*      xoff,yoff being the ulx, uly in pixel/line.                     */
/* -------------------------------------------------------------------- */
    if (dfULX != 0.0 || dfULY != 0.0
        || dfLRX != 0.0 || dfLRY != 0.0)
    {
        double adfGeoTransform[6];

        GDALGetGeoTransform(hDataset, adfGeoTransform);

        if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0)
        {
            fprintf(stderr,
                    "The -projwin option was used, but the geotransform is\n"
                    "rotated.  This configuration is not supported.\n");
            GDALClose(hDataset);
            CPLFree(panBandList);
            GDALDestroyDriverManager();
            exit(1);
        }

        anSrcWin[0] = (int)
                      ((dfULX - adfGeoTransform[0]) / adfGeoTransform[1] + 0.001);
        anSrcWin[1] = (int)
                      ((dfULY - adfGeoTransform[3]) / adfGeoTransform[5] + 0.001);

        anSrcWin[2] = (int) ((dfLRX - dfULX) / adfGeoTransform[1] + 0.5);
        anSrcWin[3] = (int) ((dfLRY - dfULY) / adfGeoTransform[5] + 0.5);

        if (!bQuiet)
            fprintf(stdout,
                    "Computed -srcwin %d %d %d %d from projected window.\n",
                    anSrcWin[0],
                    anSrcWin[1],
                    anSrcWin[2],
                    anSrcWin[3]);

        if (anSrcWin[0] < 0 || anSrcWin[1] < 0
            || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hDataset)
            || anSrcWin[1] + anSrcWin[3] > GDALGetRasterYSize(hDataset))
        {
            fprintf(stderr,
                    "Computed -srcwin falls outside raster size of %dx%d.\n",
                    GDALGetRasterXSize(hDataset),
                    GDALGetRasterYSize(hDataset));
            exit(1);
        }
    }

/* -------------------------------------------------------------------- */
/*      Verify source window.                                           */
/* -------------------------------------------------------------------- */
    if (anSrcWin[0] < 0 || anSrcWin[1] < 0
        || anSrcWin[2] <= 0 || anSrcWin[3] <= 0
        || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hDataset)
        || anSrcWin[1] + anSrcWin[3] > GDALGetRasterYSize(hDataset))
    {
        fprintf(stderr,
                "-srcwin %d %d %d %d falls outside raster size of %dx%d\n"
                "or is otherwise illegal.\n",
                anSrcWin[0],
                anSrcWin[1],
                anSrcWin[2],
                anSrcWin[3],
                GDALGetRasterXSize(hDataset),
                GDALGetRasterYSize(hDataset));
        exit(1);
    }

/* -------------------------------------------------------------------- */
/*      Find the output driver.                                         */
/* -------------------------------------------------------------------- */
    hDriver = GDALGetDriverByName(pszFormat);
    if (hDriver == NULL)
    {
        int iDr;

        printf("Output driver `%s' not recognised.\n", pszFormat);
        printf("The following format drivers are configured and support output:\n");

        for (iDr = 0; iDr < GDALGetDriverCount(); iDr++)
        {
            GDALDriverH hDriver = GDALGetDriver(iDr);

            if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL) != NULL
                || GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATECOPY,
                                       NULL) != NULL)
            {
                printf("  %s: %s\n",
                       GDALGetDriverShortName(hDriver),
                       GDALGetDriverLongName(hDriver));
            }
        }

        printf("\n");
        Usage();

        GDALClose(hDataset);
        CPLFree(panBandList);
        GDALDestroyDriverManager();
        CSLDestroy(argv);
        CSLDestroy(papszCreateOptions);
        exit(1);
    }

/* -------------------------------------------------------------------- */
/*      The short form is to CreateCopy().  We use this if the input    */
/*      matches the whole dataset.  Eventually we should rewrite        */
/*      this entire program to use virtual datasets to construct a      */
/*      virtual input source to copy from.                              */
/* -------------------------------------------------------------------- */


    int bSpatialArrangementPreserved = (
        anSrcWin[0] == 0 && anSrcWin[1] == 0
        && anSrcWin[2] == GDALGetRasterXSize(hDataset)
        && anSrcWin[3] == GDALGetRasterYSize(hDataset)
        && pszOXSize == NULL && pszOYSize == NULL);

    if (eOutputType == GDT_Unknown
        && !bScale && !bUnscale
        && CSLCount(papszMetadataOptions) == 0 && bDefBands
        && eMaskMode == MASK_AUTO
        && bSpatialArrangementPreserved
        && nGCPCount == 0 && !bGotBounds
        && pszOutputSRS == NULL && !bSetNoData && !bUnsetNoData
        && nRGBExpand == 0 && !bStats)
    {
        hOutDS = GDALCreateCopy(hDriver, pszDest, hDataset,
                                bStrict, papszCreateOptions,
                                pfnProgress, NULL);

        if (hOutDS != NULL)
            GDALClose(hOutDS);

        GDALClose(hDataset);

        CPLFree(panBandList);

        if (!bSubCall)
        {
            GDALDumpOpenDatasets(stderr);
            GDALDestroyDriverManager();
        }

        CSLDestroy(argv);
        CSLDestroy(papszCreateOptions);

        return hOutDS == NULL;
    }

/* -------------------------------------------------------------------- */
/*      Establish some parameters.                                      */
/* -------------------------------------------------------------------- */
    if (pszOXSize == NULL)
    {
        nOXSize = anSrcWin[2];
        nOYSize = anSrcWin[3];
    }
    else
    {
        nOXSize = (int) ((pszOXSize[strlen(pszOXSize) - 1] == '%'
                          ? CPLAtofM(pszOXSize) / 100 * anSrcWin[2] : atoi(pszOXSize)));
        nOYSize = (int) ((pszOYSize[strlen(pszOYSize) - 1] == '%'
                          ? CPLAtofM(pszOYSize) / 100 * anSrcWin[3] : atoi(pszOYSize)));
    }

/* ==================================================================== */
/*      Create a virtual dataset.                                       */
/* ==================================================================== */
    VRTDataset *poVDS;

/* -------------------------------------------------------------------- */
/*      Make a virtual clone.                                           */
/* -------------------------------------------------------------------- */
    poVDS = (VRTDataset*) VRTCreate(nOXSize, nOYSize);

    if (nGCPCount == 0)
    {
        if (pszOutputSRS != NULL)
        {
            poVDS->SetProjection(pszOutputSRS);
        }
        else
        {
            pszProjection = GDALGetProjectionRef(hDataset);
            if (pszProjection != NULL && strlen(pszProjection) > 0)
                poVDS->SetProjection(pszProjection);
        }
    }

    if (bGotBounds)
    {
        adfGeoTransform[0] = adfULLR[0];
        adfGeoTransform[1] = (adfULLR[2] - adfULLR[0]) / nOXSize;
        adfGeoTransform[2] = 0.0;
        adfGeoTransform[3] = adfULLR[1];
        adfGeoTransform[4] = 0.0;
        adfGeoTransform[5] = (adfULLR[3] - adfULLR[1]) / nOYSize;

        poVDS->SetGeoTransform(adfGeoTransform);
    }

    else if (GDALGetGeoTransform(hDataset, adfGeoTransform) == CE_None
             && nGCPCount == 0)
    {
        adfGeoTransform[0] += anSrcWin[0] * adfGeoTransform[1]
                              + anSrcWin[1] * adfGeoTransform[2];
        adfGeoTransform[3] += anSrcWin[0] * adfGeoTransform[4]
                              + anSrcWin[1] * adfGeoTransform[5];

        adfGeoTransform[1] *= anSrcWin[2] / (double) nOXSize;
        adfGeoTransform[2] *= anSrcWin[3] / (double) nOYSize;
        adfGeoTransform[4] *= anSrcWin[2] / (double) nOXSize;
        adfGeoTransform[5] *= anSrcWin[3] / (double) nOYSize;

        poVDS->SetGeoTransform(adfGeoTransform);
    }

    if (nGCPCount != 0)
    {
        const char *pszGCPProjection = pszOutputSRS;

        if (pszGCPProjection == NULL)
            pszGCPProjection = GDALGetGCPProjection(hDataset);

        if (pszGCPProjection == NULL)
            pszGCPProjection = "";

        poVDS->SetGCPs(nGCPCount, pasGCPs, pszGCPProjection);

        GDALDeinitGCPs(nGCPCount, pasGCPs);
        CPLFree(pasGCPs);
    }

    else if (GDALGetGCPCount(hDataset) > 0)
    {
        GDAL_GCP *pasGCPs;
        int      nGCPs = GDALGetGCPCount(hDataset);

        pasGCPs = GDALDuplicateGCPs(nGCPs, GDALGetGCPs(hDataset));

        for (i = 0; i < nGCPs; i++)
        {
            pasGCPs[i].dfGCPPixel -= anSrcWin[0];
            pasGCPs[i].dfGCPLine  -= anSrcWin[1];
            pasGCPs[i].dfGCPPixel *= (nOXSize / (double) anSrcWin[2]);
            pasGCPs[i].dfGCPLine  *= (nOYSize / (double) anSrcWin[3]);
        }

        poVDS->SetGCPs(nGCPs, pasGCPs,
                       GDALGetGCPProjection(hDataset));

        GDALDeinitGCPs(nGCPs, pasGCPs);
        CPLFree(pasGCPs);
    }

/* -------------------------------------------------------------------- */
/*      Transfer generally applicable metadata.                         */
/* -------------------------------------------------------------------- */
    poVDS->SetMetadata(((GDALDataset*)hDataset)->GetMetadata());
    AttachMetadata((GDALDatasetH) poVDS, papszMetadataOptions);

    const char *pszInterleave = GDALGetMetadataItem(hDataset, "INTERLEAVE", "IMAGE_STRUCTURE");
    if (pszInterleave)
        poVDS->SetMetadataItem("INTERLEAVE", pszInterleave, "IMAGE_STRUCTURE");

/* -------------------------------------------------------------------- */
/*      Transfer metadata that remains valid if the spatial             */
/*      arrangement of the data is unaltered.                           */
/* -------------------------------------------------------------------- */
    if (bSpatialArrangementPreserved)
    {
        char **papszMD;

        papszMD = ((GDALDataset*)hDataset)->GetMetadata("RPC");
        if (papszMD != NULL)
            poVDS->SetMetadata(papszMD, "RPC");

        papszMD = ((GDALDataset*)hDataset)->GetMetadata("GEOLOCATION");
        if (papszMD != NULL)
            poVDS->SetMetadata(papszMD, "GEOLOCATION");
    }

    int nSrcBandCount = nBandCount;

    if (nRGBExpand != 0)
    {
        GDALRasterBand *poSrcBand;
        poSrcBand = ((GDALDataset*)
                     hDataset)->GetRasterBand(ABS(panBandList[0]));
        if (panBandList[0] < 0)
            poSrcBand = poSrcBand->GetMaskBand();

        GDALColorTable *poColorTable = poSrcBand->GetColorTable();
        if (poColorTable == NULL)
        {
            fprintf(stderr, "Error : band %d has no color table\n", ABS(panBandList[0]));
            GDALClose(hDataset);
            CPLFree(panBandList);
            GDALDestroyDriverManager();
            CSLDestroy(argv);
            CSLDestroy(papszCreateOptions);
            exit(1);
        }

        /* Check that the color table only contains gray levels */
        /* when using -expand gray */
        if (nRGBExpand == 1)
        {
            int nColorCount = poColorTable->GetColorEntryCount();
            int nColor;

            for (nColor = 0; nColor < nColorCount; nColor++)
            {
                const GDALColorEntry *poEntry = poColorTable->GetColorEntry(nColor);
                if (poEntry->c1 != poEntry->c2 || poEntry->c1 != poEntry->c2)
                {
                    fprintf(stderr, "Warning : color table contains non gray levels colors\n");
                    break;
                }
            }
        }

        if (nBandCount == 1)
            nBandCount = nRGBExpand;
        else if (nBandCount == 2 && (nRGBExpand == 3 || nRGBExpand == 4))
            nBandCount = nRGBExpand;
        else
        {
            fprintf(stderr, "Error : invalid use of -expand option.\n");
            exit(1);
        }
    }

    int bFilterOutStatsMetadata =
        (bScale || bUnscale || !bSpatialArrangementPreserved || nRGBExpand != 0);

/* ==================================================================== */
/*      Process all bands.                                              */
/* ==================================================================== */
    for (i = 0; i < nBandCount; i++)
    {
        VRTSourcedRasterBand *poVRTBand;
        GDALRasterBand       *poSrcBand;
        GDALDataType         eBandType;
        int                  nComponent = 0;

        int nSrcBand;
        if (nRGBExpand != 0)
        {
            if (nSrcBandCount == 2 && nRGBExpand == 4 && i == 3)
                nSrcBand = panBandList[1];
            else
            {
                nSrcBand   = panBandList[0];
                nComponent = i + 1;
            }
        }
        else
            nSrcBand = panBandList[i];

        poSrcBand = ((GDALDataset*) hDataset)->GetRasterBand(ABS(nSrcBand));

/* -------------------------------------------------------------------- */
/*      Select output data type to match source.                        */
/* -------------------------------------------------------------------- */
        if (eOutputType == GDT_Unknown)
            eBandType = poSrcBand->GetRasterDataType();
        else
            eBandType = eOutputType;

/* -------------------------------------------------------------------- */
/*      Create this band.                                               */
/* -------------------------------------------------------------------- */
        poVDS->AddBand(eBandType, NULL);
        poVRTBand = (VRTSourcedRasterBand*) poVDS->GetRasterBand(i + 1);
        if (nSrcBand < 0)
        {
            poVRTBand->AddMaskBandSource(poSrcBand);
            continue;
        }

/* -------------------------------------------------------------------- */
/*      Do we need to collect scaling information?                      */
/* -------------------------------------------------------------------- */
        double dfScale = 1.0, dfOffset = 0.0;

        if (bScale && !bHaveScaleSrc)
        {
            double adfCMinMax[2];
            GDALComputeRasterMinMax(poSrcBand, TRUE, adfCMinMax);
            dfScaleSrcMin = adfCMinMax[0];
            dfScaleSrcMax = adfCMinMax[1];
        }

        if (bScale)
        {
            if (dfScaleSrcMax == dfScaleSrcMin)
                dfScaleSrcMax += 0.1;

            if (dfScaleDstMax == dfScaleDstMin)
                dfScaleDstMax += 0.1;

            dfScale = (dfScaleDstMax - dfScaleDstMin)
                      / (dfScaleSrcMax - dfScaleSrcMin);
            dfOffset = -1 * dfScaleSrcMin * dfScale + dfScaleDstMin;
        }

        if (bUnscale)
        {
            dfScale  = poSrcBand->GetScale();
            dfOffset = poSrcBand->GetOffset();
        }

/* -------------------------------------------------------------------- */
/*      Create a simple or complex data source depending on the         */
/*      translation type required.                                      */
/* -------------------------------------------------------------------- */
        if (bUnscale || bScale || (nRGBExpand != 0 && i < nRGBExpand))
        {
            poVRTBand->AddComplexSource(poSrcBand,
                                        anSrcWin[0], anSrcWin[1],
                                        anSrcWin[2], anSrcWin[3],
                                        0, 0, nOXSize, nOYSize,
                                        dfOffset, dfScale,
                                        VRT_NODATA_UNSET,
                                        nComponent);
        }
        else
            poVRTBand->AddSimpleSource(poSrcBand,
                                       anSrcWin[0], anSrcWin[1],
                                       anSrcWin[2], anSrcWin[3],
                                       0, 0, nOXSize, nOYSize);

/* -------------------------------------------------------------------- */
/*      In case of color table translate, we only set the color         */
/*      interpretation other info copied by CopyBandInfo are            */
/*      not relevant in RGB expansion.                                  */
/* -------------------------------------------------------------------- */
        if (nRGBExpand == 1)
        {
            poVRTBand->SetColorInterpretation(GCI_GrayIndex);
        }
        else if (nRGBExpand != 0 && i < nRGBExpand)
        {
            poVRTBand->SetColorInterpretation((GDALColorInterp) (GCI_RedBand + i));
        }

/* -------------------------------------------------------------------- */
/*      copy over some other information of interest.                   */
/* -------------------------------------------------------------------- */
        else
        {
            CopyBandInfo(poSrcBand, poVRTBand,
                         !bStats && !bFilterOutStatsMetadata,
                         !bUnscale,
                         !bSetNoData && !bUnsetNoData);
        }

/* -------------------------------------------------------------------- */
/*      Set a forcable nodata value?                                    */
/* -------------------------------------------------------------------- */
        if (bSetNoData)
        {
            double dfVal    = dfNoDataReal;
            int    bClamped = FALSE, bRounded = FALSE;

#define CLAMP(val, type, minval, maxval)                                          \
    do { if (val < minval) { bClamped = TRUE; val = minval;                       \
         }                                                                        \
         else if (val > maxval) { bClamped = TRUE; val = maxval; }                \
         else if (val != (type)val) { bRounded = TRUE; val = (type)(val + 0.5); } \
    }                                                                             \
    while (0)

            switch (eBandType)
            {
            case GDT_Byte:
                CLAMP(dfVal, GByte, 0.0, 255.0);
                break;

            case GDT_Int16:
                CLAMP(dfVal, GInt16, -32768.0, 32767.0);
                break;

            case GDT_UInt16:
                CLAMP(dfVal, GUInt16, 0.0, 65535.0);
                break;

            case GDT_Int32:
                CLAMP(dfVal, GInt32, -2147483648.0, 2147483647.0);
                break;

            case GDT_UInt32:
                CLAMP(dfVal, GUInt32, 0.0, 4294967295.0);
                break;

            default:
                break;
            }

            if (bClamped)
            {
                printf("for band %d, nodata value has been clamped "
                       "to %.0f, the original value being out of range.\n",
                       i + 1, dfVal);
            }
            else if (bRounded)
            {
                printf("for band %d, nodata value has been rounded "
                       "to %.0f, %s being an integer datatype.\n",
                       i + 1, dfVal,
                       GDALGetDataTypeName(eBandType));
            }

            poVRTBand->SetNoDataValue(dfVal);
        }

        if (eMaskMode == MASK_AUTO &&
            (GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) & GMF_PER_DATASET) == 0 &&
            (poSrcBand->GetMaskFlags() & (GMF_ALL_VALID | GMF_NODATA)) == 0)
        {
            if (poVRTBand->CreateMaskBand(poSrcBand->GetMaskFlags()) == CE_None)
            {
                VRTSourcedRasterBand *hMaskVRTBand =
                    (VRTSourcedRasterBand*)poVRTBand->GetMaskBand();
                hMaskVRTBand->AddMaskBandSource(poSrcBand,
                                                anSrcWin[0], anSrcWin[1],
                                                anSrcWin[2], anSrcWin[3],
                                                0, 0, nOXSize, nOYSize);
            }
        }
    }

    if (eMaskMode == MASK_USER)
    {
        GDALRasterBand *poSrcBand =
            (GDALRasterBand*)GDALGetRasterBand(hDataset, ABS(nMaskBand));
        if (poSrcBand && poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
        {
            VRTSourcedRasterBand *hMaskVRTBand = (VRTSourcedRasterBand*)
                                                 GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
            if (nMaskBand > 0)
                hMaskVRTBand->AddSimpleSource(poSrcBand,
                                              anSrcWin[0], anSrcWin[1],
                                              anSrcWin[2], anSrcWin[3],
                                              0, 0, nOXSize, nOYSize);
            else
                hMaskVRTBand->AddMaskBandSource(poSrcBand,
                                                anSrcWin[0], anSrcWin[1],
                                                anSrcWin[2], anSrcWin[3],
                                                0, 0, nOXSize, nOYSize);
        }
    }
    else if (eMaskMode == MASK_AUTO && nSrcBandCount > 0 &&
             GDALGetMaskFlags(GDALGetRasterBand(hDataset, 1)) == GMF_PER_DATASET)
    {
        if (poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
        {
            VRTSourcedRasterBand *hMaskVRTBand = (VRTSourcedRasterBand*)
                                                 GDALGetMaskBand(GDALGetRasterBand((GDALDatasetH)poVDS, 1));
            hMaskVRTBand->AddMaskBandSource((GDALRasterBand*)GDALGetRasterBand(hDataset, 1),
                                            anSrcWin[0], anSrcWin[1],
                                            anSrcWin[2], anSrcWin[3],
                                            0, 0, nOXSize, nOYSize);
        }
    }

/* -------------------------------------------------------------------- */
/*      Compute stats if required.                                      */
/* -------------------------------------------------------------------- */
    if (bStats)
    {
        for (i = 0; i < poVDS->GetRasterCount(); i++)
        {
            double dfMin, dfMax, dfMean, dfStdDev;
            poVDS->GetRasterBand(i + 1)->ComputeStatistics(bApproxStats,
                                                           &dfMin, &dfMax, &dfMean, &dfStdDev, GDALDummyProgress, NULL);
        }
    }

/* -------------------------------------------------------------------- */
/*      Write to the output file using CopyCreate().                    */
/* -------------------------------------------------------------------- */
    hOutDS = GDALCreateCopy(hDriver, pszDest, (GDALDatasetH) poVDS,
                            bStrict, papszCreateOptions,
                            pfnProgress, NULL);
    if (hOutDS != NULL)
    {
        int bHasGotErr = FALSE;
        CPLErrorReset();
        GDALFlushCache(hOutDS);
        if (CPLGetLastErrorType() != CE_None)
            bHasGotErr = TRUE;

        GDALClose(hOutDS);
        if (bHasGotErr)
            hOutDS = NULL;
    }

    GDALClose((GDALDatasetH) poVDS);

    GDALClose(hDataset);

    CPLFree(panBandList);

    CPLFree(pszOutputSRS);

    if (!bSubCall)
    {
        GDALDumpOpenDatasets(stderr);
        GDALDestroyDriverManager();
    }

    CSLDestroy(argv);
    CSLDestroy(papszCreateOptions);

    return hOutDS == NULL;
}
示例#13
0
int main( int argc, char *argv[] )
{
	if( argc < 3 ) {
		usage();
		return 1;
	}
	//Loading the input files names
	//-----------------------------
	char	*inB1	 	= argv[1]; //ETpotd
	char	*inB2	 	= argv[2]; //ETa
	char	*inB3	 	= argv[3]; //FC
	char	*taF	 	= argv[4]; //Ta Gap Outfile
	//Loading the input files
	//-----------------------
	GDALAllRegister();
	GDALDatasetH hD1 = GDALOpen(inB1,GA_ReadOnly);//ETpotd
	GDALDatasetH hD2 = GDALOpen(inB2,GA_ReadOnly);//ETa
	GDALDatasetH hD3 = GDALOpen(inB3,GA_ReadOnly);//FC
	if(hD1==NULL||hD2==NULL||hD3==NULL){
		printf("One or more input files ");
		printf("could not be loaded\n");
		exit(EXIT_FAILURE);
	}
	//Loading the file infos
	//----------------------
	GDALDriverH hDr1 = GDALGetDatasetDriver(hD1);
	GDALDatasetH hDOut = GDALCreateCopy(hDr1,taF,hD1,FALSE,NULL,NULL,NULL);
	GDALRasterBandH hBOut = GDALGetRasterBand(hDOut,1);
	GDALRasterBandH hB1 = GDALGetRasterBand(hD1,1);//ETpotd
	GDALRasterBandH hB2 = GDALGetRasterBand(hD2,1);//ETa
	GDALRasterBandH hB3 = GDALGetRasterBand(hD3,1);//FC
	int nX = GDALGetRasterBandXSize(hB1);
	int nY = GDALGetRasterBandYSize(hB1);
	int N = nX*nY;
	float *l1 = (float *) malloc(sizeof(float)*N);
	float *l2 = (float *) malloc(sizeof(float)*N);
	short int *l3 = (short int *) malloc(sizeof(short int)*N);
	float *lOut = (float *) malloc(sizeof(float)*N);
	int rowcol;
	GDALRasterIO(hB1,GF_Read,0,0,nX,nY,l1,nX,nY,GDT_Float32,0,0);
	GDALRasterIO(hB2,GF_Read,0,0,nX,nY,l2,nX,nY,GDT_Float32,0,0);
	GDALRasterIO(hB3,GF_Read,0,0,nX,nY,l3,nX,nY,GDT_Int16,0,0);
	#pragma omp parallel for default(none) \
	private (rowcol) shared (N, l1, l2, l3, lOut)
	for(rowcol=0;rowcol<N;rowcol++){
		if(l1[rowcol] < 0 || l2[rowcol] < 0
		|| l3[rowcol] < 0) lOut[rowcol] = -28768;
		else
		//FC is in percentage
		lOut[rowcol] = (l1[rowcol] - l2[rowcol]) * l3[rowcol] / 100.0;
	}
	#pragma omp barrier
	GDALRasterIO(hBOut,GF_Write,0,0,nX,nY,lOut,nX,nY,GDT_Float32,0,0);
	if( l1 != NULL ) free( l1 );
	if( l2 != NULL ) free( l2 );
	if( l3 != NULL ) free( l3 );
	GDALClose(hD1);
	GDALClose(hD2);
	GDALClose(hD3);
	GDALClose(hDOut);
	return(EXIT_SUCCESS);
}
示例#14
0
int main( int argc, char *argv[] )
{
      	if( argc < 9 ) {
		usage();
		return 1;
	}
	char	*inB1 		= argv[1]; //Albedo
	char	*inB2	 	= argv[2]; //Sunza
	char	*inB3		= argv[3]; //e0-1-b31
	char	*inB4		= argv[4]; //e0-2-b32
	char	*inB5		= argv[5]; //LST
	char	*inB6		= argv[6]; //DEM
	char	*rnetF	 	= argv[7];
	float	doy		= atof( argv[8] );
	float	tmax	 	= atof( argv[9] );

	//MDB Farm A
// 	double phase_max=sin(2*3.1415927*(doy+365/3.3)/365);
// 	tmax=31.17+(36.9-24.1)/2*((1+1/3+1/5+1/7)*phase_max);
// // 	double phase_min=sin(2*PI*(doy+365/3.5)/365);
// // 	double tmin=31.17+(36.9-24.1)/2*((1+1/3+1/5+1/7)*phase_min);

	//Convert Tmax from C to K
// 	if(tmax<100.0) tmax+=273.15;

// 	printf("\ndoy\t= %7.2f\ntmax\t= %7.2f\n\n",doy, tmax);
	GDALAllRegister();

	GDALDatasetH hD1 = GDALOpen(inB1,GA_ReadOnly);//Albedo
	GDALDatasetH hD2 = GDALOpen(inB2,GA_ReadOnly);//Sunza
	GDALDatasetH hD3 = GDALOpen(inB3,GA_ReadOnly);//e31
	GDALDatasetH hD4 = GDALOpen(inB4,GA_ReadOnly);//e32
	GDALDatasetH hD5 = GDALOpen(inB5,GA_ReadOnly);//LST
	GDALDatasetH hD6 = GDALOpen(inB6,GA_ReadOnly);//DEM

	if(hD1==NULL||hD2==NULL||hD3==NULL||
	hD4==NULL||hD5==NULL||hD6==NULL){
		printf("One or more input files ");
		printf("could not be loaded\n");
		exit(1);
	}

	GDALDriverH hDr6 = GDALGetDatasetDriver(hD6);
	GDALDatasetH hDOut = GDALCreateCopy(hDr6,rnetF,hD6,FALSE,NULL,NULL,NULL);
	GDALRasterBandH hBOut = GDALGetRasterBand(hDOut,1);

	GDALRasterBandH hB1 = GDALGetRasterBand(hD1,1);//Albedo
	GDALRasterBandH hB2 = GDALGetRasterBand(hD2,1);//Sunza
	GDALRasterBandH hB3 = GDALGetRasterBand(hD3,1);//e31
	GDALRasterBandH hB4 = GDALGetRasterBand(hD4,1);//e32
	GDALRasterBandH hB5 = GDALGetRasterBand(hD5,1);//LST
	GDALRasterBandH hB6 = GDALGetRasterBand(hD6,1);//DEM

	int nX = GDALGetRasterBandXSize(hB1);
	int nY = GDALGetRasterBandYSize(hB1);
	int N=nX*nY;

	float *mat1 = (float *) malloc(sizeof(float)*N);
	float *mat2 = (float *) malloc(sizeof(float)*N);
	float *mat3 = (float *) malloc(sizeof(float)*N);
	float *mat4 = (float *) malloc(sizeof(float)*N);
	float *mat5 = (float *) malloc(sizeof(float)*N);
	float *mat6 = (float *) malloc(sizeof(float)*N);
	float *matOut = (float *) malloc(sizeof(float)*N);

	float e0, rnet;
	int rowcol;
	GDALRasterIO(hB1,GF_Read,0,0,nX,nY,mat1,nX,nY,GDT_Float32,0,0);
	GDALRasterIO(hB2,GF_Read,0,0,nX,nY,mat2,nX,nY,GDT_Float32,0,0);
	GDALRasterIO(hB3,GF_Read,0,0,nX,nY,mat3,nX,nY,GDT_Float32,0,0);
	GDALRasterIO(hB4,GF_Read,0,0,nX,nY,mat4,nX,nY,GDT_Float32,0,0);
	GDALRasterIO(hB5,GF_Read,0,0,nX,nY,mat5,nX,nY,GDT_Float32,0,0);
	GDALRasterIO(hB6,GF_Read,0,0,nX,nY,mat6,nX,nY,GDT_Float32,0,0);
	#pragma omp parallel for default(none) \
		private(rowcol, e0, rnet)\
		shared(N, tmax, doy,\
			mat1,mat2,mat3,mat4,mat5,mat6, \
			matOut )
	for(rowcol=0;rowcol<N;rowcol++){
		if(mat1[rowcol]==-28768||mat5[rowcol]==-28768||mat5[rowcol]==0) matOut[rowcol] = -28768;
		else {
			e0 = 0.5*((mat3[rowcol]*0.002+0.49)+(mat4[rowcol]*0.002+0.49));
			rnet = r_net(mat1[rowcol]*0.001,mat2[rowcol]*0.01,e0,mat5[rowcol]*0.02,mat6[rowcol],doy,tmax);
			matOut[rowcol]=rnet;
		}
	}
	#pragma omp barrier
	GDALRasterIO(hBOut,GF_Write,0,0,nX,nY,matOut,nX,nY,GDT_Float32,0,0);
	GDALClose(hDOut);
	//free memory close unused files
	if(mat1 != NULL) free(mat1);
	if(mat2 != NULL) free(mat2);
	if(mat3 != NULL) free(mat3);
	if(mat4 != NULL) free(mat4);
	if(mat5 != NULL) free(mat5);
	if(mat6 != NULL) free(mat6);
	if(matOut != NULL) free(matOut);

	GDALClose(hD1);
	GDALClose(hD2);
	GDALClose(hD3);
	GDALClose(hD4);
	GDALClose(hD5);
	GDALClose(hD6);
	return(EXIT_SUCCESS);
}
示例#15
0
int main( int argc, char *argv[] )
{
      	if( argc < 7 ) {
		usage();
		return 1;
	}
	int 	row, col;
	double 	geomx[6]={0.0};

	char *inB1 	= argv[1]; //Albedo
	char *inB2 	= argv[2]; //DEM
	char *inB3	= argv[3]; //e0 31
	char *inB4	= argv[4]; //e0 32
	char *inB5	= argv[5]; //LST
	char *rnetdF 	= argv[6];
	float doy	= atof( argv[7] );

// 	printf("\ndoy\t= %7.2f\n\n",doy);
// 	printf("%s %s %s %s %s\n",inB1, inB2, inB3, inB4, inB5);
	GDALAllRegister();
	GDALDatasetH hD1 = GDALOpen(inB1,GA_ReadOnly);//Albedo
	GDALDatasetH hD2 = GDALOpen(inB2,GA_ReadOnly);//DEM
	GDALDatasetH hD3 = GDALOpen(inB3,GA_ReadOnly);//E 31
	GDALDatasetH hD4 = GDALOpen(inB4,GA_ReadOnly);//E 32
	GDALDatasetH hD5 = GDALOpen(inB5,GA_ReadOnly);//LST

	if(hD1==NULL||hD2==NULL||hD3==NULL||hD4==NULL||hD5==NULL){
		printf("One or more input files ");
		printf("could not be loaded\n");
		exit(1);
	}

	if(GDALGetGeoTransform(hD1,geomx)==CE_None){
	/* Do Nothing */
// 		printf( "Origin (ULx,ULy) = (%.6f,%.6f)\n", geomx[0], geomx[3] );
// 		printf( "Pixel Size = (%.6f,%.6f)\n", geomx[1], geomx[5] );
// 		printf( "Rot0 = (%.6f,%.6f)\n", geomx[2], geomx[4] );
	} else {
		printf("ERROR: Projection acquisition problem from Band1\n");
		exit(1);
	}

	GDALDriverH hDr2 = GDALGetDatasetDriver(hD2);
	//RNETD out
	GDALDatasetH hDOut = GDALCreateCopy( hDr2, rnetdF,hD2,FALSE,NULL,NULL,NULL);
	GDALRasterBandH hBOut = GDALGetRasterBand(hDOut,1);
	GDALRasterBandH hB1 = GDALGetRasterBand(hD1,1);//Albedo
	GDALRasterBandH hB2 = GDALGetRasterBand(hD2,1);//DEM
	GDALRasterBandH hB3 = GDALGetRasterBand(hD3,1);//E 31
	GDALRasterBandH hB4 = GDALGetRasterBand(hD4,1);//E 32
	GDALRasterBandH hB5 = GDALGetRasterBand(hD5,1);//LST

	int nX = GDALGetRasterBandXSize(hB1);
	int nY = GDALGetRasterBandYSize(hB1);

	float *mat1 = (float *) malloc(sizeof(float)*nX);
	float *mat2 = (float *) malloc(sizeof(float)*nX);
	float *mat3 = (float *) malloc(sizeof(float)*nX);
	float *mat4 = (float *) malloc(sizeof(float)*nX);
	float *mat5 = (float *) malloc(sizeof(float)*nX);
	float *matOut = (float *) malloc(sizeof(float)*nX);
/*	int i,temp,histogramT[512];
	for (i=0;i<512;i++){
		histogramT[i]=0;
	}*/
	float solar, rnetd, e0;
	for(row=0;row<nY;row++){
		GDALRasterIO(hB1,GF_Read,0,row,nX,1,mat1,nX,1,GDT_Float32,0,0);
		GDALRasterIO(hB2,GF_Read,0,row,nX,1,mat2,nX,1,GDT_Float32,0,0);
		GDALRasterIO(hB3,GF_Read,0,row,nX,1,mat3,nX,1,GDT_Float32,0,0);
		GDALRasterIO(hB4,GF_Read,0,row,nX,1,mat4,nX,1,GDT_Float32,0,0);
		GDALRasterIO(hB5,GF_Read,0,row,nX,1,mat5,nX,1,GDT_Float32,0,0);
		#pragma omp parallel for default(none) \
			private(col, solar, rnetd, e0)\
			shared( row, doy, geomx,nX, \
				mat1, mat2, mat3, mat4, mat5, matOut )
		for(col=0;col<nX;col++){
			if(mat1[col]==-28768||mat5[col]==-28768||mat5[col]==0){
				matOut[col] = -28768;
			}else {
				/*temp = (int) (mat1[col]);
				if(temp>0) histogramT[temp]=histogramT[temp]+1.0;*/
// 				printf("lat=%f\n", geomx[3]+geomx[4]*col+geomx[5]*row);
// 				printf("%f \n",e0);
				e0 = 0.5*((mat3[col]*0.002+0.49)+(mat4[col]*0.002+0.49));
				solar = solar_day(geomx[3]+geomx[4]*col+geomx[5]*row, doy, mat2[col] );
				//rnetd = r_net_d( mat1[col]*0.001, solar, e0, mat5[col]*0.02, mat2[col]);
				rnetd = r_net_day( mat1[col]*0.001, solar, mat2[col]);
				matOut[col]=rnetd;
			}
		}
		#pragma omp barrier
	GDALRasterIO(hBOut,GF_Write,0,row,nX,1,matOut,nX,1,GDT_Float32,0,0);
	}
	GDALClose(hDOut);
/*	for (i=0;i<512;i++){
		printf("%i\t%i\n",i,histogramT[i]);
	}*/
	//free memory close unused files
	if(mat1 != NULL) free(mat1);
	if(mat2 != NULL) free(mat2);
	if(mat3 != NULL) free(mat3);
	if(mat4 != NULL) free(mat4);
	if(mat5 != NULL) free(mat5);
	if(matOut != NULL) free(matOut);

	GDALClose(hD1);
	GDALClose(hD2);
	GDALClose(hD3);
	GDALClose(hD4);
	GDALClose(hD5);
	return(EXIT_SUCCESS);
}
示例#16
0
int main(int /* argc*/ , char* /* argv */[])
{
    int nOvrLevel;
    int nBandNum;
    GDALDatasetH hDS;
    GDALDatasetH hSrcDS;
    FILE* f;

    const char* pszGDAL_SKIP = CPLGetConfigOption("GDAL_SKIP", NULL);
    if( pszGDAL_SKIP == NULL )
        CPLSetConfigOption("GDAL_SKIP", "GIF");
    else
        CPLSetConfigOption("GDAL_SKIP", CPLSPrintf("%s GIF", pszGDAL_SKIP));

    GDALAllRegister();

    hDS = GDALOpen("../gcore/data/byte.tif", GA_ReadOnly);
    if (hDS)
        GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));

    hDS = GDALOpen("../gcore/data/byte.vrt", GA_ReadOnly);
    if (hDS)
        GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));

    hDS = GDALOpen("../gdrivers/data/rgb_warp.vrt", GA_ReadOnly);
    if (hDS)
        GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));

    hDS = GDALOpen("../gdrivers/data/A.TOC", GA_ReadOnly);

    hDS = GDALOpen("NITF_TOC_ENTRY:CADRG_ONC_1,000,000_2_0:../gdrivers/data/A.TOC", GA_ReadOnly);
    if (hDS)
        GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));

    hDS = GDALOpen("../gdrivers/data/testtil.til", GA_ReadOnly);
    if (hDS)
        GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));

    hDS = GDALOpen("../gdrivers/data/product.xml", GA_ReadOnly);
    if (hDS)
        GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));

    hDS = GDALOpen("../gdrivers/data/METADATA.DIM", GA_ReadOnly);
    if (hDS)
        GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));

    hDS = GDALOpen("../gdrivers/tmp/cache/file9_j2c.ntf", GA_ReadOnly);
    if (hDS)
        GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));

    hDS = GDALOpen("../gdrivers/data/bug407.gif", GA_ReadOnly);
    if (hDS)
    {
        GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));
        GDALSetCacheMax(0);
        GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));
    }

    /* Create external overviews */
    hSrcDS = GDALOpen("../gcore/data/byte.tif", GA_ReadOnly);
    hDS = GDALCreateCopy(GDALGetDriverByName("GTiff"), "byte.tif", hSrcDS, 0, NULL, NULL, NULL);
    GDALClose(hSrcDS);
    hSrcDS = NULL;
    hDS = GDALOpen("byte.tif", GA_ReadOnly);
    nOvrLevel = 2;
    nBandNum = 1;
    GDALBuildOverviews( hDS, "NEAR", 1, &nOvrLevel, 1, &nBandNum, NULL, NULL);
    GDALClose(hDS);

    hDS = GDALOpen("byte.tif", GA_ReadOnly);
    GDALGetOverviewCount(GDALGetRasterBand(hDS, 1));

    /* Create internal overviews */
    hSrcDS = GDALOpen("../gcore/data/byte.tif", GA_ReadOnly);
    hDS = GDALCreateCopy(GDALGetDriverByName("GTiff"), "byte2.tif", hSrcDS, 0, NULL, NULL, NULL);
    GDALClose(hSrcDS);
    hSrcDS = NULL;
    hDS = GDALOpen("byte2.tif", GA_Update);
    nOvrLevel = 2;
    nBandNum = 1;
    GDALBuildOverviews( hDS, "NEAR", 1, &nOvrLevel, 1, &nBandNum, NULL, NULL);
    GDALClose(hDS);

    hDS = GDALOpen("byte2.tif", GA_ReadOnly);
    GDALGetOverviewCount(GDALGetRasterBand(hDS, 1));

    /* Create external mask */
    hSrcDS = GDALOpen("../gcore/data/byte.tif", GA_ReadOnly);
    hDS = GDALCreateCopy(GDALGetDriverByName("GTiff"), "byte3.tif", hSrcDS, 0, NULL, NULL, NULL);
    GDALClose(hSrcDS);
    hSrcDS = NULL;
    hDS = GDALOpen("byte3.tif", GA_ReadOnly);
    GDALCreateDatasetMaskBand(hDS, GMF_PER_DATASET);
    GDALClose(hDS);

    hDS = GDALOpen("byte3.tif", GA_ReadOnly);
    GDALGetMaskFlags(GDALGetRasterBand(hDS, 1));

    f = fopen("byte.vrt", "wb");
    fprintf(f, "%s", "<VRTDataset rasterXSize=\"20\" rasterYSize=\"20\">"
  "<VRTRasterBand dataType=\"Byte\" band=\"1\">"
    "<SimpleSource>"
      "<SourceFilename relativeToVRT=\"1\">../gcore/data/byte.tif</SourceFilename>"
      "<SourceBand>1</SourceBand>"
      "<SourceProperties RasterXSize=\"20\" RasterYSize=\"20\" DataType=\"Byte\" BlockXSize=\"20\" BlockYSize=\"20\" />"
      "<SrcRect xOff=\"0\" yOff=\"0\" xSize=\"20\" ySize=\"20\"/>"
      "<DstRect xOff=\"0\" yOff=\"0\" xSize=\"20\" ySize=\"20\"/>"
    "</SimpleSource>"
  "</VRTRasterBand>"
"</VRTDataset>");
    fclose(f);

    hDS = GDALOpen("byte.vrt", GA_ReadOnly);
    nOvrLevel = 2;
    nBandNum = 1;
    GDALBuildOverviews( hDS, "NEAR", 1, &nOvrLevel, 1, &nBandNum, NULL, NULL);
    GDALClose(hDS);

    hDS = GDALOpen("byte.vrt", GA_ReadOnly);
    GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));
    GDALGetOverviewCount(GDALGetRasterBand(hDS, 1));

    hDS = GDALOpen("<VRTDataset rasterXSize=\"20\" rasterYSize=\"20\">"
  "<VRTRasterBand dataType=\"Byte\" band=\"1\">"
    "<SimpleSource>"
      "<SourceFilename relativeToVRT=\"1\">byte.vrt</SourceFilename>"
      "<SourceBand>1</SourceBand>"
      "<SourceProperties RasterXSize=\"20\" RasterYSize=\"20\" DataType=\"Byte\" BlockXSize=\"20\" BlockYSize=\"20\" />"
      "<SrcRect xOff=\"0\" yOff=\"0\" xSize=\"20\" ySize=\"20\"/>"
      "<DstRect xOff=\"0\" yOff=\"0\" xSize=\"20\" ySize=\"20\"/>"
    "</SimpleSource>"
  "</VRTRasterBand>"
"</VRTDataset>", GA_ReadOnly);
    GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));

    hDS = GDALOpenShared("../gcore/data/byte.tif", GA_ReadOnly);
    hDS = GDALOpenShared("../gcore/data/byte.tif", GA_ReadOnly);

    hDS = GDALOpenShared("../gdrivers/data/mercator.sid", GA_ReadOnly);

    hDS = GDALOpen("RASTERLITE:../gdrivers/data/rasterlite_pyramids.sqlite,table=test", GA_ReadOnly);
    hDS = GDALOpen("RASTERLITE:../gdrivers/data/rasterlite_pyramids.sqlite,table=test,level=1", GA_ReadOnly);

    OpenJPEG2000("../gdrivers/data/rgbwcmyk01_YeGeo_kakadu.jp2");
    
    hDS = GDALOpen("../gdrivers/tmp/cache/Europe 2001_OZF.map", GA_ReadOnly);

    CPLDebug("TEST","Call GDALDestroyDriverManager()");
    GDALDestroyDriverManager();

    unlink("byte.tif");
    unlink("byte.tif.ovr");
    unlink("byte2.tif");
    unlink("byte3.tif");
    unlink("byte3.tif.msk");
    unlink("byte.vrt");

    return 0;
}