Dear GDAL community

I'm currently working with gdal api C/C++ and I'm facing an issue with gdal 
warp region to buffer functionality (WarpRegionToBuffer).

When my destination dataset is not strictly contained in the frame of my source 
dataset, the area where there should be no data values is filled with random 
data (see out_code.tif enclosed). However gdalwarp command line functionality, 
which also uses WarpRegionToBuffer function, does not seem to have this problem.

I enclose to my email warp_tiling.cpp a sample of our code

Can you please help us find what is wrong with our use of GDAL C/C++ API  in 
order to have a similar behaviour as gdalwarp command line? There is probably 
an algorithm in gdalwarp that computes a mask of useful pixels in destination 
frame before calling WarpRegionToBuffer, but we didn't find it.
I would really appreciate help on this problem!

Best regards,
Maud FERRATO

#include <iostream>
#include <string>
#include <vector>

#include "gdal.h"
#include "gdalwarper.h"
#include "cpl_conv.h"


int main(void)
{
	std::string pathSrc = "in.dt1";
	//these datas will be provide by command line 
    std::string pathDst = "out_code.tif";
    
    double resolutionx = 0.000833333;
	double resolutiony = 0.000833333;
	
	float_t xtl = -1;
	float_t ytl = 45;
	float_t xbr = 2;
	float_t ybr = 41;    
    
	//tile size defined by user
	int tilesizex = 256;
	int tilesizey = 256;
    
    float width = std::ceil((xbr - xtl)/resolutionx);
	float height = std::ceil((ytl - ybr)/resolutiony);

    double adfDstGeoTransform[6] = {xtl, resolutionx, 0, ytl, 0, -resolutiony};

    GDALDatasetH  hSrcDS, hDstDS;

    // Open input file
    GDALAllRegister();
    hSrcDS = GDALOpen(pathSrc.c_str(), GA_ReadOnly);
    GDALDataType  eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1));
    
    // Create output file, using same spatial reference as input image, but new geotransform
    GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
    hDstDS = GDALCreate( hDriver, pathDst.c_str(), width, height, GDALGetRasterCount(hSrcDS), eDT, NULL );

    OGRSpatialReference oSRS;
	char *pszWKT = NULL;

	//force geo projection
	oSRS.SetWellKnownGeogCS( "WGS84" );
	oSRS.exportToWkt( &pszWKT );
	GDALSetProjection( hDstDS, pszWKT );
	//Fetches the coefficients for transforming between pixel/line (P,L) raster space,
	//and projection coordinates (Xp,Yp) space.
	GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
	    
    // Setup warp options
    GDALWarpOptions *psWarpOptions = GDALCreateWarpOptions();
    psWarpOptions->hSrcDS = hSrcDS;
    psWarpOptions->hDstDS = hDstDS;
    psWarpOptions->nBandCount = 1;
    psWarpOptions->panSrcBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount );
    psWarpOptions->panSrcBands[0] = 1;
    psWarpOptions->panDstBands = (int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount );
    psWarpOptions->panDstBands[0] = 1;
    psWarpOptions->pfnProgress = GDALTermProgress;
    
    //these datas will be calculated in order to warp tile by tile
	//current tile size
	int cursizex = 0;
	int cursizey = 0;

	double nbtilex = std::ceil(width/tilesizex);
	double nbtiley = std::ceil(height/tilesizey);

	int starttilex = 0;
	int starttiley = 0;
				
    // Establish reprojection transformer
    psWarpOptions->pTransformerArg =
        GDALCreateGenImgProjTransformer(hSrcDS,
                                        GDALGetProjectionRef(hSrcDS),
                                        hDstDS,
                                        GDALGetProjectionRef(hDstDS),
                                        FALSE, 0.0, 1);
    psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
    
    // Initialize and execute the warp operation on region
    GDALWarpOperation oOperation;
    oOperation.Initialize(psWarpOptions);
    
	for (int ty = 0; ty < nbtiley; ty++) {
		//handle last tile size
		//if it last tile change size otherwise keep tilesize
		for (int tx = 0; tx < nbtilex; tx++) {
			//if it last tile change size otherwise keep tilesize
			starttiley = ty * tilesizey;
			starttilex = tx * tilesizex;
			
			cursizex = std::min(starttilex + tilesizex, (int)width) - starttilex;
			cursizey = std::min(starttiley + tilesizey, (int)height) - starttiley;

			float * buffer = new float[cursizex*cursizey];
			memset(buffer, 0, cursizex*cursizey);

			//warp source
			CPLErr ret = oOperation.WarpRegionToBuffer(
				starttilex, starttiley, cursizex, cursizey,
				buffer,
				eDT);
			if (ret != 0) {
				CEA_SIMONE_ERROR(CPLGetLastErrorMsg());
				throw std::runtime_error("warp error");
			}
			
			//write the fuzed tile in dest
			ret = GDALRasterIO(GDALGetRasterBand(hDstDS,1),
				GF_Write,
				starttilex, starttiley, cursizex, cursizey,
				buffer, cursizex, cursizey,
				eDT,
				0, 0);
			if (ret != 0) {
				CEA_SIMONE_ERROR("raster io write error");
				throw std::runtime_error("raster io write error");
			}
			delete(buffer);
		}
	}
    
    // Clean memory
    GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );
    GDALDestroyWarpOptions( psWarpOptions );
    GDALClose( hDstDS );
    GDALClose( hSrcDS );
    
    return 0;
}
_______________________________________________
gdal-dev mailing list
[email protected]
https://lists.osgeo.org/mailman/listinfo/gdal-dev

Reply via email to