/** * GDALReprojectImage() method with a ChunkAndWarpImage replaced with ChunkAndWarpMulti */ CPLErr GDALReprojectImageMulti( GDALDatasetH hSrcDS, const char *pszSrcWKT, GDALDatasetH hDstDS, const char *pszDstWKT, GDALResampleAlg eResampleAlg, double dfWarpMemoryLimit, double dfMaxError, GDALProgressFunc pfnProgress, void *pProgressArg, GDALWarpOptions *psOptions ) { GDALWarpOptions *psWOptions; /* -------------------------------------------------------------------- */ /* Setup a reprojection based transformer. */ /* -------------------------------------------------------------------- */ void *hTransformArg; hTransformArg = GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT, TRUE, 1000.0, 0 ); if( hTransformArg == NULL ) return CE_Failure; /* -------------------------------------------------------------------- */ /* Create a copy of the user provided options, or a defaulted */ /* options structure. */ /* -------------------------------------------------------------------- */ if( psOptions == NULL ) psWOptions = GDALCreateWarpOptions(); else psWOptions = GDALCloneWarpOptions( psOptions ); psWOptions->eResampleAlg = eResampleAlg; /* -------------------------------------------------------------------- */ /* Set transform. */ /* -------------------------------------------------------------------- */ if( dfMaxError > 0.0 ) { psWOptions->pTransformerArg = GDALCreateApproxTransformer( GDALGenImgProjTransform, hTransformArg, dfMaxError ); psWOptions->pfnTransformer = GDALApproxTransform; } else { psWOptions->pfnTransformer = GDALGenImgProjTransform; psWOptions->pTransformerArg = hTransformArg; } /* -------------------------------------------------------------------- */ /* Set file and band mapping. */ /* -------------------------------------------------------------------- */ int iBand; psWOptions->hSrcDS = hSrcDS; psWOptions->hDstDS = hDstDS; if( psWOptions->nBandCount == 0 ) { psWOptions->nBandCount = MIN(GDALGetRasterCount(hSrcDS), GDALGetRasterCount(hDstDS)); psWOptions->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWOptions->nBandCount); psWOptions->panDstBands = (int *) CPLMalloc(sizeof(int) * psWOptions->nBandCount); for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ ) { psWOptions->panSrcBands[iBand] = iBand+1; psWOptions->panDstBands[iBand] = iBand+1; } } /* -------------------------------------------------------------------- */ /* Set source nodata values if the source dataset seems to have */ /* any. Same for target nodata values */ /* -------------------------------------------------------------------- */ for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ ) { GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, iBand+1 ); int bGotNoData = FALSE; double dfNoDataValue; if (GDALGetRasterColorInterpretation(hBand) == GCI_AlphaBand) { psWOptions->nSrcAlphaBand = iBand + 1; } dfNoDataValue = GDALGetRasterNoDataValue( hBand, &bGotNoData ); if( bGotNoData ) { if( psWOptions->padfSrcNoDataReal == NULL ) { int ii; psWOptions->padfSrcNoDataReal = (double *) CPLMalloc(sizeof(double) * psWOptions->nBandCount); psWOptions->padfSrcNoDataImag = (double *) CPLMalloc(sizeof(double) * psWOptions->nBandCount); for( ii = 0; ii < psWOptions->nBandCount; ii++ ) { psWOptions->padfSrcNoDataReal[ii] = -1.1e20; psWOptions->padfSrcNoDataImag[ii] = 0.0; } } psWOptions->padfSrcNoDataReal[iBand] = dfNoDataValue; } // Deal with target band hBand = GDALGetRasterBand( hDstDS, iBand+1 ); if (hBand && GDALGetRasterColorInterpretation(hBand) == GCI_AlphaBand) { psWOptions->nDstAlphaBand = iBand + 1; } dfNoDataValue = GDALGetRasterNoDataValue( hBand, &bGotNoData ); if( bGotNoData ) { if( psWOptions->padfDstNoDataReal == NULL ) { int ii; psWOptions->padfDstNoDataReal = (double *) CPLMalloc(sizeof(double) * psWOptions->nBandCount); psWOptions->padfDstNoDataImag = (double *) CPLMalloc(sizeof(double) * psWOptions->nBandCount); for( ii = 0; ii < psWOptions->nBandCount; ii++ ) { psWOptions->padfDstNoDataReal[ii] = -1.1e20; psWOptions->padfDstNoDataImag[ii] = 0.0; } } psWOptions->padfDstNoDataReal[iBand] = dfNoDataValue; } } /* -------------------------------------------------------------------- */ /* Set the progress function. */ /* -------------------------------------------------------------------- */ if( pfnProgress != NULL ) { psWOptions->pfnProgress = pfnProgress; psWOptions->pProgressArg = pProgressArg; } /* -------------------------------------------------------------------- */ /* Create a warp options based on the options. */ /* -------------------------------------------------------------------- */ GDALWarpOperation oWarper; CPLErr eErr; eErr = oWarper.Initialize( psWOptions ); if( eErr == CE_None ) eErr = oWarper.ChunkAndWarpMulti( 0, 0, GDALGetRasterXSize(hDstDS), GDALGetRasterYSize(hDstDS) ); /* -------------------------------------------------------------------- */ /* Cleanup. */ /* -------------------------------------------------------------------- */ GDALDestroyGenImgProjTransformer( hTransformArg ); if( dfMaxError > 0.0 ) GDALDestroyApproxTransformer( psWOptions->pTransformerArg ); GDALDestroyWarpOptions( psWOptions ); return eErr; }
int main( int nArgc, char ** papszArgv ) { // register drivers GDALAllRegister(); if( nArgc < 2 ) return EXIT_FAILURE; double dfaCornersX[5] = {0}; double dfaCornersY[5] = {0}; CPLString sFileName; // parse input values for( int iArg = 1; iArg < nArgc; iArg++ ) { if( EQUAL(papszArgv[iArg],"-nw")) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2); const char* pszCoord = papszArgv[++iArg]; dfaCornersY[1] = CPLAtofM(pszCoord); pszCoord = papszArgv[++iArg]; dfaCornersX[1] = CPLAtofM(pszCoord); } else if( EQUAL(papszArgv[iArg],"-ne")) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2); const char* pszCoord = papszArgv[++iArg]; dfaCornersY[2] = CPLAtofM(pszCoord); pszCoord = papszArgv[++iArg]; dfaCornersX[2] = CPLAtofM(pszCoord); } else if( EQUAL(papszArgv[iArg],"-se")) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2); const char* pszCoord = papszArgv[++iArg]; dfaCornersY[3] = CPLAtofM(pszCoord); pszCoord = papszArgv[++iArg]; dfaCornersX[3] = CPLAtofM(pszCoord); } else if( EQUAL(papszArgv[iArg],"-sw")) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2); const char* pszCoord = papszArgv[++iArg]; dfaCornersY[4] = CPLAtofM(pszCoord); pszCoord = papszArgv[++iArg]; dfaCornersX[4] = CPLAtofM(pszCoord); } else if( EQUAL(papszArgv[iArg],"-c")) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(2); const char* pszCoord = papszArgv[++iArg]; dfaCornersY[0] = CPLAtofM(pszCoord); pszCoord = papszArgv[++iArg]; dfaCornersX[0] = CPLAtofM(pszCoord); } else if(sFileName.empty()) sFileName = papszArgv[iArg]; } OGRSpatialReference oOGRSpatialReference(SRS_WKT_WGS84); int nZoneNo = ceil( (180.0 + dfaCornersX[0]) / 6.0 ); OGRSpatialReference oDstSpatialReference(SRS_WKT_WGS84); oDstSpatialReference.SetUTM(nZoneNo, dfaCornersY[0] > 0); // transform coordinates from WGS84 to UTM OGRCoordinateTransformation *poCT = OGRCreateCoordinateTransformation( &oOGRSpatialReference, &oDstSpatialReference); if(!poCT) { Usage("get coordinate transformation failed"); return EXIT_FAILURE; } int nResult = poCT->Transform(5, dfaCornersX, dfaCornersY, NULL); if(!nResult) { Usage("transformation failed"); return EXIT_FAILURE; } // open input dataset GDALDataset *poSrcDataset = (GDALDataset *) GDALOpen( sFileName, GA_ReadOnly ); // GA_Update char* pszSpaRefDef = NULL; if( oDstSpatialReference.exportToWkt(&pszSpaRefDef) != OGRERR_NONE) { CPLFree( pszSpaRefDef ); GDALClose( (GDALDatasetH) poSrcDataset ); return EXIT_FAILURE; } // search point along image // add GCP to opened raster OGRPoint ptCenter(dfaCornersX[0], dfaCornersY[0]); OGRPoint pt1(dfaCornersX[1], dfaCornersY[1]); // NW Cormer OGRPoint pt2(dfaCornersX[2], dfaCornersY[2]); // NE Corner OGRPoint pt3(dfaCornersX[3], dfaCornersY[3]); // SE Corner OGRPoint pt4(dfaCornersX[4], dfaCornersY[4]); // SW Corner int nGCPCount = 0; OGREnvelope DstEnv; GDAL_GCP *paGSPs = PrepareGCP(sFileName, &pt1, &pt2, &pt3, &pt4, &ptCenter, oDstSpatialReference, poSrcDataset->GetRasterXSize(), poSrcDataset->GetRasterYSize(), nGCPCount, DstEnv); if(poSrcDataset->SetGCPs(nGCPCount, paGSPs, pszSpaRefDef) != CE_None) { Usage( "Set GCPs failed" ); return EXIT_FAILURE; } // create warper char **papszTO = NULL; papszTO = CSLSetNameValue( papszTO, "METHOD", "GCP_TPS" ); papszTO = CSLSetNameValue( papszTO, "NUM_THREADS", "4" ); papszTO = CSLSetNameValue( papszTO, "DST_SRS", pszSpaRefDef ); papszTO = CSLSetNameValue( papszTO, "SRC_SRS", pszSpaRefDef ); papszTO = CSLSetNameValue( papszTO, "INSERT_CENTER_LONG", "FALSE" ); GDALDriver *poOutputDriver = (GDALDriver *) GDALGetDriverByName( "GTiff" ); CPLSetConfigOption( "CHECK_WITH_INVERT_PROJ", "TRUE" ); void* hTransformArg = GDALCreateGenImgProjTransformer2( poSrcDataset, NULL, papszTO ); GDALTransformerInfo* psInfo = (GDALTransformerInfo*)hTransformArg; double adfThisGeoTransform[6]; double adfExtent[4]; int nThisPixels, nThisLines; // suggest the raster output size if( GDALSuggestedWarpOutput2( poSrcDataset, psInfo->pfnTransform, hTransformArg, adfThisGeoTransform, &nThisPixels, &nThisLines, adfExtent, 0 ) != CE_None ) { Usage( "Suggest Output failed" ); return EXIT_FAILURE; } adfThisGeoTransform[0] = DstEnv.MinX; adfThisGeoTransform[3] = DstEnv.MaxY; int nPixels = (int) ((DstEnv.MaxX - DstEnv.MinX) / adfThisGeoTransform[1] + 0.5); int nLines = (int) ((DstEnv.MaxY - DstEnv.MinY) / -adfThisGeoTransform[5] + 0.5); GDALSetGenImgProjTransformerDstGeoTransform( hTransformArg, adfThisGeoTransform); // create new raster CPLString sOutputRasterPath = CPLResetExtension(sFileName, "tif"); GDALDataset *poDstDataset = poOutputDriver->Create(sOutputRasterPath, nPixels, nLines, poSrcDataset->GetRasterCount(), GDT_Byte, NULL ); if( NULL == poDstDataset ) { Usage( "Create Output failed" ); return EXIT_FAILURE; } poDstDataset->SetProjection( pszSpaRefDef ); poDstDataset->SetGeoTransform( adfThisGeoTransform ); #ifdef APRROX_MAXERROR hTransformArg = GDALCreateApproxTransformer( GDALGenImgProjTransform, hTransformArg, APRROX_MAXERROR); GDALTransformerFunc pfnTransformer = GDALApproxTransform; GDALApproxTransformerOwnsSubtransformer(hTransformArg, TRUE); #else GDALTransformerFunc pfnTransformer = GDALGenImgProjTransform; #endif // APRROX_MAXERROR // warp GDALWarpOptions *psWO = GDALCreateWarpOptions(); psWO->eWorkingDataType = GDT_Byte; psWO->eResampleAlg = GRA_NearestNeighbour; psWO->hSrcDS = poSrcDataset; psWO->hDstDS = poDstDataset; psWO->pfnTransformer = pfnTransformer; psWO->pTransformerArg = hTransformArg; psWO->pfnProgress = GDALTermProgress; psWO->nBandCount = poSrcDataset->GetRasterCount(); psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int)); psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int)); for(int i = 0; i < psWO->nBandCount; ++i ) { psWO->panSrcBands[i] = i+1; psWO->panDstBands[i] = i+1; } GDALWarpOperation oWO; if( oWO.Initialize( psWO ) == CE_None ) { #ifdef MULTI if( oWO.ChunkAndWarpMulti( 0, 0, poDstDataset->GetRasterXSize(), poDstDataset->GetRasterYSize() ) != CE_None) #else //MULTI if( oWO.ChunkAndWarpImage( 0, 0, poDstDataset->GetRasterXSize(), poDstDataset->GetRasterYSize() ) != CE_None) #endif //MULTI { const char* err = CPLGetLastErrorMsg(); Usage( CPLSPrintf("Warp failed.%s", err) ); return EXIT_FAILURE; } } // cleanup GDALDestroyWarpOptions( psWO ); CSLDestroy( papszTO ); CPLFree( pszSpaRefDef ); GDALClose( (GDALDatasetH) poSrcDataset ); GDALClose( (GDALDatasetH) poDstDataset ); GDALDestroyDriverManager(); return EXIT_SUCCESS; }
/** * \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); }
GDALDatasetH CPL_STDCALL GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS, const char *pszSrcWKT, const char *pszDstWKT, GDALResampleAlg eResampleAlg, double dfMaxError, const GDALWarpOptions *psOptionsIn ) { GDALWarpOptions *psWO; int i; VALIDATE_POINTER1( hSrcDS, "GDALAutoCreateWarpedVRT", NULL ); /* -------------------------------------------------------------------- */ /* Populate the warp options. */ /* -------------------------------------------------------------------- */ if( psOptionsIn != NULL ) psWO = GDALCloneWarpOptions( psOptionsIn ); else psWO = GDALCreateWarpOptions(); psWO->eResampleAlg = eResampleAlg; psWO->hSrcDS = hSrcDS; psWO->nBandCount = GDALGetRasterCount( hSrcDS ); psWO->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWO->nBandCount); psWO->panDstBands = (int *) CPLMalloc(sizeof(int) * psWO->nBandCount); for( i = 0; i < psWO->nBandCount; i++ ) { psWO->panSrcBands[i] = i+1; psWO->panDstBands[i] = i+1; } /* TODO: should fill in no data where available */ /* -------------------------------------------------------------------- */ /* Create the transformer. */ /* -------------------------------------------------------------------- */ psWO->pfnTransformer = GDALGenImgProjTransform; psWO->pTransformerArg = GDALCreateGenImgProjTransformer( psWO->hSrcDS, pszSrcWKT, NULL, pszDstWKT, TRUE, 1.0, 0 ); if( psWO->pTransformerArg == NULL ) { GDALDestroyWarpOptions( psWO ); return NULL; } /* -------------------------------------------------------------------- */ /* Figure out the desired output bounds and resolution. */ /* -------------------------------------------------------------------- */ double adfDstGeoTransform[6]; int nDstPixels, nDstLines; CPLErr eErr; eErr = GDALSuggestedWarpOutput( hSrcDS, psWO->pfnTransformer, psWO->pTransformerArg, adfDstGeoTransform, &nDstPixels, &nDstLines ); /* -------------------------------------------------------------------- */ /* Update the transformer to include an output geotransform */ /* back to pixel/line coordinates. */ /* */ /* -------------------------------------------------------------------- */ GDALSetGenImgProjTransformerDstGeoTransform( psWO->pTransformerArg, adfDstGeoTransform ); /* -------------------------------------------------------------------- */ /* Do we want to apply an approximating transformation? */ /* -------------------------------------------------------------------- */ if( dfMaxError > 0.0 ) { psWO->pTransformerArg = GDALCreateApproxTransformer( psWO->pfnTransformer, psWO->pTransformerArg, dfMaxError ); psWO->pfnTransformer = GDALApproxTransform; } /* -------------------------------------------------------------------- */ /* Create the VRT file. */ /* -------------------------------------------------------------------- */ GDALDatasetH hDstDS; hDstDS = GDALCreateWarpedVRT( hSrcDS, nDstPixels, nDstLines, adfDstGeoTransform, psWO ); GDALDestroyWarpOptions( psWO ); if( pszDstWKT != NULL ) GDALSetProjection( hDstDS, pszDstWKT ); else if( pszSrcWKT != NULL ) GDALSetProjection( hDstDS, pszDstWKT ); else if( GDALGetGCPCount( hSrcDS ) > 0 ) GDALSetProjection( hDstDS, GDALGetGCPProjection( hSrcDS ) ); else GDALSetProjection( hDstDS, GDALGetProjectionRef( hSrcDS ) ); return hDstDS; }
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 ); }
/** Apply a vertical shift grid to a source (DEM typically) dataset. * * hGridDataset will typically use WGS84 as horizontal datum (but this is * not a requirement) and its values are the values to add to go from geoid * elevations to WGS84 ellipsoidal heights. * * hGridDataset will be on-the-fly reprojected and resampled to the projection * and resolution of hSrcDataset, using bilinear resampling by default. * * Both hSrcDataset and hGridDataset must be single band datasets, and have * a valid geotransform and projection. * * On success, a reference will be taken on hSrcDataset and hGridDataset. * Reference counting semantics on the source and grid datasets should be * honoured. That is, don't just GDALClose() it, unless it was opened with * GDALOpenShared(), but rather use GDALReleaseDataset() if wanting to * immediately release the reference(s) and make the returned dataset the * owner of them. * * Valid use cases: * * \code * hSrcDataset = GDALOpen(...) * hGridDataset = GDALOpen(...) * hDstDataset = GDALApplyVerticalShiftGrid(hSrcDataset, hGridDataset, ...) * GDALReleaseDataset(hSrcDataset); * GDALReleaseDataset(hGridDataset); * if( hDstDataset ) * { * // Do things with hDstDataset * GDALClose(hDstDataset) // will close hSrcDataset and hGridDataset * } * \endcode * * @param hSrcDataset source (DEM) dataset. Must not be NULL. * @param hGridDataset vertical grid shift dataset. Must not be NULL. * @param bInverse if set to FALSE, hGridDataset values will be added to * hSrcDataset. If set to TRUE, they will be subtracted. * @param dfSrcUnitToMeter the factor to convert values from hSrcDataset to * meters (1.0 if source values are in meter). * @param dfDstUnitToMeter the factor to convert shifted values from meter * (1.0 if output values must be in meter). * @param papszOptions list of options, or NULL. Supported options are: * <ul> * <li>RESAMPLING=NEAREST/BILINEAR/CUBIC. Defaults to BILINEAR.</li> * <li>MAX_ERROR=val. Maximum error measured in input pixels that is allowed in * approximating the transformation (0.0 for exact calculations). Defaults * to 0.125</li> * <li>DATATYPE=Byte/UInt16/Int16/Float32/Float64. Output data type. If not * specified will be the same as the one of hSrcDataset. * <li>ERROR_ON_MISSING_VERT_SHIFT=YES/NO. Whether a missing/nodata value in * hGridDataset should cause I/O requests to fail. Default is NO (in which case * 0 will be used) * <li>SRC_SRS=srs_def. Override projection on hSrcDataset; * </ul> * * @return a new dataset corresponding to hSrcDataset adjusted with * hGridDataset, or NULL. If not NULL, it must be closed with GDALClose(). * * @since GDAL 2.2 */ GDALDatasetH GDALApplyVerticalShiftGrid( GDALDatasetH hSrcDataset, GDALDatasetH hGridDataset, int bInverse, double dfSrcUnitToMeter, double dfDstUnitToMeter, const char* const* papszOptions ) { VALIDATE_POINTER1( hSrcDataset, "GDALApplyVerticalShiftGrid", nullptr ); VALIDATE_POINTER1( hGridDataset, "GDALApplyVerticalShiftGrid", nullptr ); double adfSrcGT[6]; if( GDALGetGeoTransform(hSrcDataset, adfSrcGT) != CE_None ) { CPLError(CE_Failure, CPLE_NotSupported, "Source dataset has no geotransform."); return nullptr; } const char* pszSrcProjection = CSLFetchNameValueDef(papszOptions, "SRC_SRS", GDALGetProjectionRef(hSrcDataset)); if( pszSrcProjection == nullptr || pszSrcProjection[0] == '\0' ) { CPLError(CE_Failure, CPLE_NotSupported, "Source dataset has no projection."); return nullptr; } if( GDALGetRasterCount(hSrcDataset) != 1 ) { CPLError(CE_Failure, CPLE_NotSupported, "Only single band source dataset is supported."); return nullptr; } double adfGridGT[6]; if( GDALGetGeoTransform(hGridDataset, adfGridGT) != CE_None ) { CPLError(CE_Failure, CPLE_NotSupported, "Grid dataset has no geotransform."); return nullptr; } const char* pszGridProjection = GDALGetProjectionRef(hGridDataset); if( pszGridProjection == nullptr || pszGridProjection[0] == '\0' ) { CPLError(CE_Failure, CPLE_NotSupported, "Grid dataset has no projection."); return nullptr; } if( GDALGetRasterCount(hGridDataset) != 1 ) { CPLError(CE_Failure, CPLE_NotSupported, "Only single band grid dataset is supported."); return nullptr; } GDALDataType eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDataset,1)); const char* pszDataType = CSLFetchNameValue(papszOptions, "DATATYPE"); if( pszDataType ) eDT = GDALGetDataTypeByName(pszDataType); if( eDT == GDT_Unknown ) { CPLError(CE_Failure, CPLE_NotSupported, "Invalid DATATYPE=%s", pszDataType); return nullptr; } const int nSrcXSize = GDALGetRasterXSize(hSrcDataset); const int nSrcYSize = GDALGetRasterYSize(hSrcDataset); OGRSpatialReference oSRS; CPLString osSrcProjection(pszSrcProjection); oSRS.SetFromUserInput(osSrcProjection); if( oSRS.IsCompound() ) { OGR_SRSNode* poNode = oSRS.GetRoot()->GetChild(1); if( poNode != nullptr ) { char* pszWKT = nullptr; poNode->exportToWkt(&pszWKT); osSrcProjection = pszWKT; CPLFree(pszWKT); } } void* hTransform = GDALCreateGenImgProjTransformer3( pszGridProjection, adfGridGT, osSrcProjection, adfSrcGT ); if( hTransform == nullptr ) return nullptr; GDALWarpOptions* psWO = GDALCreateWarpOptions(); psWO->hSrcDS = hGridDataset; psWO->eResampleAlg = GRA_Bilinear; const char* pszResampling = CSLFetchNameValue(papszOptions, "RESAMPLING"); if( pszResampling ) { if( EQUAL(pszResampling, "NEAREST") ) psWO->eResampleAlg = GRA_NearestNeighbour; else if( EQUAL(pszResampling, "BILINEAR") ) psWO->eResampleAlg = GRA_Bilinear; else if( EQUAL(pszResampling, "CUBIC") ) psWO->eResampleAlg = GRA_Cubic; } psWO->eWorkingDataType = GDT_Float32; int bHasNoData = FALSE; const double dfSrcNoData = GDALGetRasterNoDataValue( GDALGetRasterBand(hGridDataset, 1), &bHasNoData ); if( bHasNoData ) { psWO->padfSrcNoDataReal = static_cast<double*>(CPLMalloc(sizeof(double))); psWO->padfSrcNoDataReal[0] = dfSrcNoData; } psWO->padfDstNoDataReal = static_cast<double*>(CPLMalloc(sizeof(double))); const bool bErrorOnMissingShift = CPLFetchBool( papszOptions, "ERROR_ON_MISSING_VERT_SHIFT", false ); psWO->padfDstNoDataReal[0] = (bErrorOnMissingShift) ? -std::numeric_limits<float>::infinity() : 0.0; psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions, "INIT_DEST", "NO_DATA"); psWO->pfnTransformer = GDALGenImgProjTransform; psWO->pTransformerArg = hTransform; const double dfMaxError = CPLAtof(CSLFetchNameValueDef(papszOptions, "MAX_ERROR", "0.125")); if( dfMaxError > 0.0 ) { psWO->pTransformerArg = GDALCreateApproxTransformer( psWO->pfnTransformer, psWO->pTransformerArg, dfMaxError ); psWO->pfnTransformer = GDALApproxTransform; GDALApproxTransformerOwnsSubtransformer(psWO->pTransformerArg, TRUE); } psWO->nBandCount = 1; psWO->panSrcBands = static_cast<int *>(CPLMalloc(sizeof(int))); psWO->panSrcBands[0] = 1; psWO->panDstBands = static_cast<int *>(CPLMalloc(sizeof(int))); psWO->panDstBands[0] = 1; VRTWarpedDataset* poReprojectedGrid = new VRTWarpedDataset(nSrcXSize, nSrcYSize); // This takes a reference on hGridDataset CPLErr eErr = poReprojectedGrid->Initialize(psWO); CPLAssert(eErr == CE_None); CPL_IGNORE_RET_VAL(eErr); GDALDestroyWarpOptions(psWO); poReprojectedGrid->SetGeoTransform(adfSrcGT); poReprojectedGrid->AddBand(GDT_Float32, nullptr); GDALApplyVSGDataset* poOutDS = new GDALApplyVSGDataset( reinterpret_cast<GDALDataset*>(hSrcDataset), poReprojectedGrid, eDT, CPL_TO_BOOL(bInverse), dfSrcUnitToMeter, dfDstUnitToMeter, // Undocumented option. For testing only atoi(CSLFetchNameValueDef(papszOptions, "BLOCKSIZE", "256")) ); poReprojectedGrid->ReleaseRef(); if( !poOutDS->IsInitOK() ) { delete poOutDS; return nullptr; } poOutDS->SetDescription( GDALGetDescription( hSrcDataset ) ); return reinterpret_cast<GDALDatasetH>(poOutDS); }