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; }
/** * \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); }
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 ); }