Пример #1
0
int CPL_STDCALL
GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
                     int nBandCount, int *panBandList,
                     GDALTransformerFunc pfnTransform, void *pTransformArg,
                     GDALProgressFunc pfnProgress, void *pProgressArg,
                     char **papszWarpOptions )

{
    VALIDATE_POINTER1( hSrcDS, "GDALSimpleImageWarp", 0 );
    VALIDATE_POINTER1( hDstDS, "GDALSimpleImageWarp", 0 );

    bool bError = false;

/* -------------------------------------------------------------------- */
/*      If no bands provided assume we should process all bands.        */
/* -------------------------------------------------------------------- */
    if( nBandCount == 0 )
    {
        nBandCount = GDALGetRasterCount( hSrcDS );
        if (nBandCount == 0)
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "No raster band in source dataset");
            return FALSE;
        }

        panBandList = (int *) CPLCalloc(sizeof(int),nBandCount);

        for( int iBand = 0; iBand < nBandCount; iBand++ )
            panBandList[iBand] = iBand+1;

        const int nResult =
            GDALSimpleImageWarp( hSrcDS, hDstDS, nBandCount, panBandList,
                                 pfnTransform, pTransformArg,
                                 pfnProgress, pProgressArg,
                                 papszWarpOptions );
        CPLFree( panBandList );
        return nResult;
    }

/* -------------------------------------------------------------------- */
/*      Post initial progress.                                          */
/* -------------------------------------------------------------------- */
    if( pfnProgress )
    {
        if( !pfnProgress( 0.0, "", pProgressArg ) )
            return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Load the source image band(s).                                  */
/* -------------------------------------------------------------------- */
    const int nSrcXSize = GDALGetRasterXSize(hSrcDS);
    const int nSrcYSize = GDALGetRasterYSize(hSrcDS);
    GByte **papabySrcData = static_cast<GByte **>(
        CPLCalloc(nBandCount, sizeof(GByte*)) );

    bool ok = true;
    for( int iBand = 0; iBand < nBandCount; iBand++ )
    {
        papabySrcData[iBand] = static_cast<GByte *>(
            VSI_MALLOC2_VERBOSE(nSrcXSize, nSrcYSize) );
        if( papabySrcData[iBand] == NULL )
        {
            CPLError( CE_Failure, CPLE_OutOfMemory,
                      "GDALSimpleImageWarp out of memory.\n" );
            ok = false;
            break;
        }

        if( GDALRasterIO( GDALGetRasterBand(hSrcDS,panBandList[iBand]), GF_Read,
                      0, 0, nSrcXSize, nSrcYSize,
                      papabySrcData[iBand], nSrcXSize, nSrcYSize, GDT_Byte,
                      0, 0 ) != CE_None )
        {
            CPLError( CE_Failure, CPLE_FileIO, "GDALSimpleImageWarp "
                      "GDALRasterIO failure %s ",
                      CPLGetLastErrorMsg() );
            ok = false;
            break;
        }
    }
    if( !ok ) {
        for( int i=0; i <= nBandCount; i++ )
        {
            VSIFree(papabySrcData[i]);
        }
        CPLFree(papabySrcData);
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Check for remap request(s).                                     */
/* -------------------------------------------------------------------- */
    GDALSimpleWarpRemapping( nBandCount, papabySrcData, nSrcXSize, nSrcYSize,
                             papszWarpOptions );

/* -------------------------------------------------------------------- */
/*      Allocate scanline buffers for output image.                     */
/* -------------------------------------------------------------------- */
    const int nDstXSize = GDALGetRasterXSize( hDstDS );
    const int nDstYSize = GDALGetRasterYSize( hDstDS );
    GByte **papabyDstLine = static_cast<GByte **>(
        CPLCalloc(nBandCount, sizeof(GByte*)) );

    for( int iBand = 0; iBand < nBandCount; iBand++ )
        papabyDstLine[iBand] = static_cast<GByte *>(CPLMalloc( nDstXSize ));

/* -------------------------------------------------------------------- */
/*      Allocate x,y,z coordinate arrays for transformation ... one     */
/*      scanlines worth of positions.                                   */
/* -------------------------------------------------------------------- */
    double *padfX = static_cast<double *>(
        CPLMalloc(sizeof(double) * nDstXSize) );
    double *padfY = static_cast<double *>(
        CPLMalloc(sizeof(double) * nDstXSize) );
    double *padfZ = static_cast<double *>(
        CPLMalloc(sizeof(double) * nDstXSize) );
    int *pabSuccess = static_cast<int *>( CPLMalloc(sizeof(int) * nDstXSize) );

/* -------------------------------------------------------------------- */
/*      Establish the value we will use to initialize the bands.  We    */
/*      default to -1 indicating the initial value should be read       */
/*      and preserved from the source file, but allow this to be        */
/*      overridden by passed                                            */
/*      option(s).                                                      */
/* -------------------------------------------------------------------- */
    int * const panBandInit =
        static_cast<int *>( CPLCalloc(sizeof(int), nBandCount) );
    if( CSLFetchNameValue( papszWarpOptions, "INIT" ) )
    {
        char **papszTokens =
            CSLTokenizeStringComplex( CSLFetchNameValue( papszWarpOptions,
                                                         "INIT" ),
                                      " ,", FALSE, FALSE );

        const int nTokenCount = CSLCount(papszTokens);

        for( int iBand = 0; iBand < nBandCount; iBand++ )
        {
            if( nTokenCount == 0 )
                panBandInit[iBand] = 0;
            else
                panBandInit[iBand] =
                    atoi(papszTokens[MIN(iBand,nTokenCount-1)]);
        }

        CSLDestroy(papszTokens);
    }

/* -------------------------------------------------------------------- */
/*      Loop over all the scanlines in the output image.                */
/* -------------------------------------------------------------------- */
    for( int iDstY = 0; iDstY < nDstYSize; iDstY++ )
    {
        // Clear output buffer to "transparent" value.  Should not we
        // really be reading from the destination file to support overlay?
        for( int iBand = 0; iBand < nBandCount; iBand++ )
        {
            if( panBandInit[iBand] == -1 )
            {
                if( GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Read,
                              0, iDstY, nDstXSize, 1,
                              papabyDstLine[iBand], nDstXSize, 1, GDT_Byte,
                              0, 0 ) != CE_None )
                {
                    bError = TRUE;
                    break;
                }
            }
            else
                memset( papabyDstLine[iBand], panBandInit[iBand], nDstXSize );
        }

        // Set point to transform.
        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
        {
            padfX[iDstX] = iDstX + 0.5;
            padfY[iDstX] = iDstY + 0.5;
            padfZ[iDstX] = 0.0;
        }

        // Transform the points from destination pixel/line coordinates
        // to source pixel/line coordinates.
        pfnTransform( pTransformArg, TRUE, nDstXSize,
                      padfX, padfY, padfZ, pabSuccess );

        // Loop over the output scanline.
        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
        {
            if( !pabSuccess[iDstX] )
                continue;

            // We test against the value before casting to avoid the
            // problem of asymmetric truncation effects around zero.  That is
            // -0.5 will be 0 when cast to an int.
            if( padfX[iDstX] < 0.0 || padfY[iDstX] < 0.0 )
                continue;

            const int iSrcX = static_cast<int>( padfX[iDstX] );
            const int iSrcY = static_cast<int>( padfY[iDstX] );

            if( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize )
                continue;

            const int iSrcOffset = iSrcX + iSrcY * nSrcXSize;

            for( int iBand = 0; iBand < nBandCount; iBand++ )
                papabyDstLine[iBand][iDstX] = papabySrcData[iBand][iSrcOffset];
        }

        // Write scanline to disk.
        for( int iBand = 0; iBand < nBandCount; iBand++ )
        {
            if( GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Write,
                          0, iDstY, nDstXSize, 1,
                          papabyDstLine[iBand], nDstXSize, 1, GDT_Byte, 0, 0 ) != CE_None )
            {
                bError = TRUE;
                break;
            }
        }

        if( pfnProgress != NULL )
        {
            if( !pfnProgress( (iDstY+1) / (double) nDstYSize,
                              "", pProgressArg ) )
            {
                CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
                bError = TRUE;
                break;
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Cleanup working buffers.                                        */
/* -------------------------------------------------------------------- */
    for( int iBand = 0; iBand < nBandCount; iBand++ )
    {
        CPLFree( papabyDstLine[iBand] );
        CPLFree( papabySrcData[iBand] );
    }

    CPLFree( panBandInit );
    CPLFree( papabyDstLine );
    CPLFree( papabySrcData );
    CPLFree( padfX );
    CPLFree( padfY );
    CPLFree( padfZ );
    CPLFree( pabSuccess );

    return !bError;
}
Пример #2
0
/**
 * \private \memberof mapcache_source_gdal
 * \sa mapcache_source::render_metatile()
 */
void _mapcache_source_gdal_render_metatile(mapcache_context *ctx, mapcache_metatile *tile)
{
  mapcache_source_gdal *gdal = (mapcache_source_gdal*)tile->tile.tileset->source;
  char *srcSRS = "", *dstSRS;
  mapcache_buffer *data = mapcache_buffer_create(0,ctx->pool);
  GC_CHECK_ERROR(ctx);
  GDALDatasetH  hDataset;

  GDALAllRegister();
  OGRSpatialReferenceH hSRS;
  CPLErrorReset();

  hSRS = OSRNewSpatialReference( NULL );
  if( OSRSetFromUserInput( hSRS, tile->tile.grid->srs ) == OGRERR_NONE )
    OSRExportToWkt( hSRS, &dstSRS );
  else {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"failed to parse gdal srs %s",tile->tile.grid->srs);
    return;
  }

  OSRDestroySpatialReference( hSRS );

  hDataset = GDALOpen( gdal->datastr, GA_ReadOnly );
  if( hDataset == NULL ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"GDAL failed to open %s",gdal->datastr);
    return;
  }

  /* -------------------------------------------------------------------- */
  /*      Check that there's at least one raster band                     */
  /* -------------------------------------------------------------------- */
  if ( GDALGetRasterCount(hDataset) == 0 ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"raster %s has no bands",gdal->datastr);
    return;
  }

  if( GDALGetProjectionRef( hDataset ) != NULL
      && strlen(GDALGetProjectionRef( hDataset )) > 0 )
    srcSRS = apr_pstrdup(ctx->pool,GDALGetProjectionRef( hDataset ));

  else if( GDALGetGCPProjection( hDataset ) != NULL
           && strlen(GDALGetGCPProjection(hDataset)) > 0
           && GDALGetGCPCount( hDataset ) > 1 )
    srcSRS = apr_pstrdup(ctx->pool,GDALGetGCPProjection( hDataset ));

  GDALDriverH hDriver = GDALGetDriverByName( "MEM" );
  GDALDatasetH hDstDS;
  /* -------------------------------------------------------------------- */
  /*      Create a transformation object from the source to               */
  /*      destination coordinate system.                                  */
  /* -------------------------------------------------------------------- */
  void *hTransformArg =
    GDALCreateGenImgProjTransformer( hDataset, srcSRS,
                                     NULL, dstSRS,
                                     TRUE, 1000.0, 0 );

  if( hTransformArg == NULL ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"gdal failed to create SRS transformation object");
    return;
  }

  /* -------------------------------------------------------------------- */
  /*      Get approximate output definition.                              */
  /* -------------------------------------------------------------------- */
  int nPixels, nLines;
  double adfDstGeoTransform[6];
  if( GDALSuggestedWarpOutput( hDataset,
                               GDALGenImgProjTransform, hTransformArg,
                               adfDstGeoTransform, &nPixels, &nLines )
      != CE_None ) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"gdal failed to create suggested warp output");
    return;
  }

  GDALDestroyGenImgProjTransformer( hTransformArg );
  double dfXRes = (tile->bbox[2] - tile->bbox[0]) / tile->sx;
  double dfYRes = (tile->bbox[3] - tile->bbox[1]) / tile->sy;

  adfDstGeoTransform[0] = tile->bbox[0];
  adfDstGeoTransform[3] = tile->bbox[3];
  adfDstGeoTransform[1] = dfXRes;
  adfDstGeoTransform[5] = -dfYRes;
  hDstDS = GDALCreate( hDriver, "tempd_gdal_image", tile->sx, tile->sy, 4, GDT_Byte, NULL );

  /* -------------------------------------------------------------------- */
  /*      Write out the projection definition.                            */
  /* -------------------------------------------------------------------- */
  GDALSetProjection( hDstDS, dstSRS );
  GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
  char               **papszWarpOptions = NULL;
  papszWarpOptions = CSLSetNameValue( papszWarpOptions, "INIT", "0" );



  /* -------------------------------------------------------------------- */
  /*      Create a transformation object from the source to               */
  /*      destination coordinate system.                                  */
  /* -------------------------------------------------------------------- */
  GDALTransformerFunc pfnTransformer = NULL;
  void               *hGenImgProjArg=NULL, *hApproxArg=NULL;
  hTransformArg = hGenImgProjArg =
                    GDALCreateGenImgProjTransformer( hDataset, srcSRS,
                        hDstDS, dstSRS,
                        TRUE, 1000.0, 0 );

  if( hTransformArg == NULL )
    exit( 1 );

  pfnTransformer = GDALGenImgProjTransform;

  hTransformArg = hApproxArg =
                    GDALCreateApproxTransformer( GDALGenImgProjTransform,
                        hGenImgProjArg, 0.125 );
  pfnTransformer = GDALApproxTransform;

  /* -------------------------------------------------------------------- */
  /*      Now actually invoke the warper to do the work.                  */
  /* -------------------------------------------------------------------- */
  GDALSimpleImageWarp( hDataset, hDstDS, 0, NULL,
                       pfnTransformer, hTransformArg,
                       GDALDummyProgress, NULL, papszWarpOptions );

  CSLDestroy( papszWarpOptions );

  if( hApproxArg != NULL )
    GDALDestroyApproxTransformer( hApproxArg );

  if( hGenImgProjArg != NULL )
    GDALDestroyGenImgProjTransformer( hGenImgProjArg );

  if(GDALGetRasterCount(hDstDS) != 4) {
    ctx->set_error(ctx,MAPCACHE_SOURCE_GDAL_ERROR,"gdal did not create a 4 band image");
    return;
  }

  GDALRasterBandH *redband, *greenband, *blueband, *alphaband;

  redband = GDALGetRasterBand(hDstDS,1);
  greenband = GDALGetRasterBand(hDstDS,2);
  blueband = GDALGetRasterBand(hDstDS,3);
  alphaband = GDALGetRasterBand(hDstDS,4);

  unsigned char *rasterdata = apr_palloc(ctx->pool,tile->sx*tile->sy*4);
  data->buf = rasterdata;
  data->avail = tile->sx*tile->sy*4;
  data->size = tile->sx*tile->sy*4;

  GDALRasterIO(redband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  GDALRasterIO(greenband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata+1),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  GDALRasterIO(blueband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata+2),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  if(GDALGetRasterCount(hDataset)==4)
    GDALRasterIO(alphaband,GF_Read,0,0,tile->sx,tile->sy,(void*)(rasterdata+3),tile->sx,tile->sy,GDT_Byte,4,4*tile->sx);
  else {
    unsigned char *alphaptr;
    int i;
    for(alphaptr = rasterdata+3, i=0; i<tile->sx*tile->sy; i++, alphaptr+=4) {
      *alphaptr = 255;
    }
  }

  tile->imdata = mapcache_image_create(ctx);
  tile->imdata->w = tile->sx;
  tile->imdata->h = tile->sy;
  tile->imdata->stride = tile->sx * 4;
  tile->imdata->data = rasterdata;


  GDALClose( hDstDS );
  GDALClose( hDataset);
}
Пример #3
0
int main( int argc, char ** argv )

{
    GDALDatasetH	hSrcDS, hDstDS;
    const char         *pszFormat = "GTiff";
    char               *pszTargetSRS = NULL;
    char               *pszSourceSRS = NULL;
    const char         *pszSrcFilename = NULL, *pszDstFilename = NULL;
    int                 bCreateOutput = FALSE, i, nOrder = 0;
    void               *hTransformArg, *hGenImgProjArg=NULL, *hApproxArg=NULL;
    char               **papszWarpOptions = NULL;
    double             dfErrorThreshold = 0.125;
    GDALTransformerFunc pfnTransformer = NULL;
    char                **papszCreateOptions = NULL;

    GDALAllRegister();

/* -------------------------------------------------------------------- */
/*      Parse arguments.                                                */
/* -------------------------------------------------------------------- */
    for( i = 1; i < argc; i++ )
    {
        if( EQUAL(argv[i],"--version") )
        {
            printf( "%s\n", GDALVersionInfo( "--version" ) );
            exit( 0 );
        }
        else if( EQUAL(argv[i],"--formats") )
        {
            int iDr;

            printf( "Supported Formats:\n" );
            for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
            {
                GDALDriverH hDriver = GDALGetDriver(iDr);
                
                printf( "  %s: %s\n",
                        GDALGetDriverShortName( hDriver ),
                        GDALGetDriverLongName( hDriver ) );
            }

            exit( 0 );
        }
        else if( EQUAL(argv[i],"-co") && i < argc-1 )
        {
            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
            bCreateOutput = TRUE;
        }   
        else if( EQUAL(argv[i],"-of") && i < argc-1 )
        {
            pszFormat = argv[++i];
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-t_srs") && i < argc-1 )
        {
            pszTargetSRS = SanitizeSRS(argv[++i]);
        }
        else if( EQUAL(argv[i],"-s_srs") && i < argc-1 )
        {
            pszSourceSRS = SanitizeSRS(argv[++i]);
        }
        else if( EQUAL(argv[i],"-order") && i < argc-1 )
        {
            nOrder = atoi(argv[++i]);
        }
        else if( EQUAL(argv[i],"-et") && i < argc-1 )
        {
            dfErrorThreshold = CPLAtof(argv[++i]);
        }
        else if( EQUAL(argv[i],"-tr") && i < argc-2 )
        {
            dfXRes = CPLAtof(argv[++i]);
            dfYRes = fabs(CPLAtof(argv[++i]));
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-ts") && i < argc-2 )
        {
            nForcePixels = atoi(argv[++i]);
            nForceLines = atoi(argv[++i]);
            bCreateOutput = TRUE;
        }
        else if( EQUAL(argv[i],"-te") && i < argc-4 )
        {
            dfMinX = CPLAtof(argv[++i]);
            dfMinY = CPLAtof(argv[++i]);
            dfMaxX = CPLAtof(argv[++i]);
            dfMaxY = CPLAtof(argv[++i]);
            bCreateOutput = TRUE;
        }
        else if( argv[i][0] == '-' )
            Usage();
        else if( pszSrcFilename == NULL )
            pszSrcFilename = argv[i];
        else if( pszDstFilename == NULL )
            pszDstFilename = argv[i];
        else
            Usage();
    }

    if( pszDstFilename == NULL )
        Usage();

/* -------------------------------------------------------------------- */
/*      Open source dataset.                                            */
/* -------------------------------------------------------------------- */
    hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
    
    if( hSrcDS == NULL )
        exit( 2 );

/* -------------------------------------------------------------------- */
/*      Check that there's at least one raster band                     */
/* -------------------------------------------------------------------- */
    if ( GDALGetRasterCount(hSrcDS) == 0 )
    {
        fprintf(stderr, "Input file %s has no raster bands.\n", pszSrcFilename );
        exit( 2 );
    }

    if( pszSourceSRS == NULL )
    {
        if( GDALGetProjectionRef( hSrcDS ) != NULL 
            && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
            pszSourceSRS = CPLStrdup(GDALGetProjectionRef( hSrcDS ));

        else if( GDALGetGCPProjection( hSrcDS ) != NULL
                 && strlen(GDALGetGCPProjection(hSrcDS)) > 0 
                 && GDALGetGCPCount( hSrcDS ) > 1 )
            pszSourceSRS = CPLStrdup(GDALGetGCPProjection( hSrcDS ));
        else
            pszSourceSRS = CPLStrdup("");
    }

    if( pszTargetSRS == NULL )
        pszTargetSRS = CPLStrdup(pszSourceSRS);

/* -------------------------------------------------------------------- */
/*      Does the output dataset already exist?                          */
/* -------------------------------------------------------------------- */
    CPLPushErrorHandler( CPLQuietErrorHandler );
    hDstDS = GDALOpen( pszDstFilename, GA_Update );
    CPLPopErrorHandler();

    if( hDstDS != NULL && bCreateOutput )
    {
        fprintf( stderr, 
                 "Output dataset %s exists,\n"
                 "but some commandline options were provided indicating a new dataset\n"
                 "should be created.  Please delete existing dataset and run again.",
                 pszDstFilename );
        exit( 1 );
    }

/* -------------------------------------------------------------------- */
/*      If not, we need to create it.                                   */
/* -------------------------------------------------------------------- */
    if( hDstDS == NULL )
    {
        hDstDS = GDALWarpCreateOutput( hSrcDS, pszDstFilename, pszFormat, 
                                       pszSourceSRS, pszTargetSRS, nOrder,
                                       papszCreateOptions );
        papszWarpOptions = CSLSetNameValue( papszWarpOptions, "INIT", "0" );
        CSLDestroy( papszCreateOptions );
        papszCreateOptions = NULL;
    }

    if( hDstDS == NULL )
        exit( 1 );

/* -------------------------------------------------------------------- */
/*      Create a transformation object from the source to               */
/*      destination coordinate system.                                  */
/* -------------------------------------------------------------------- */
    hTransformArg = hGenImgProjArg = 
        GDALCreateGenImgProjTransformer( hSrcDS, pszSourceSRS, 
                                         hDstDS, pszTargetSRS, 
                                         TRUE, 1000.0, nOrder );

    if( hTransformArg == NULL )
        exit( 1 );

    pfnTransformer = GDALGenImgProjTransform;

/* -------------------------------------------------------------------- */
/*      Warp the transformer with a linear approximator unless the      */
/*      acceptable error is zero.                                       */
/* -------------------------------------------------------------------- */
    if( dfErrorThreshold != 0.0 )
    {
        hTransformArg = hApproxArg = 
            GDALCreateApproxTransformer( GDALGenImgProjTransform, 
                                         hGenImgProjArg, dfErrorThreshold );
        pfnTransformer = GDALApproxTransform;
    }

/* -------------------------------------------------------------------- */
/*      Now actually invoke the warper to do the work.                  */
/* -------------------------------------------------------------------- */
    GDALSimpleImageWarp( hSrcDS, hDstDS, 0, NULL, 
                         pfnTransformer, hTransformArg,
                         GDALTermProgress, NULL, papszWarpOptions );

    CSLDestroy( papszWarpOptions );

    if( hApproxArg != NULL )
        GDALDestroyApproxTransformer( hApproxArg );

    if( hGenImgProjArg != NULL )
        GDALDestroyGenImgProjTransformer( hGenImgProjArg );

/* -------------------------------------------------------------------- */
/*      Cleanup.                                                        */
/* -------------------------------------------------------------------- */
    GDALClose( hDstDS );
    GDALClose( hSrcDS );

    GDALDumpOpenDatasets( stderr );

    GDALDestroyDriverManager();
    
    exit( 0 );
}