Opened 15 years ago

Closed 15 years ago

Last modified 15 years ago

#2889 closed defect (invalid)

gdalwarp interpolates on nodata for all methods but near

Reported by: ocarre Owned by: warmerdam
Priority: high Milestone:
Component: Utilities Version: 1.6.0
Severity: major Keywords:
Cc:

Description

Hello there, i came across a problem in gdalwarp, when doing a reprojection with gdalwarp using something like gdalwarp -r cubic -srcnodata "65531 65532 65533 65534" myfile.tif myfile_proj.tif

the resampling algorithm souldn't use the nodatavlue specified to resample, but actually it does. you can swap cubic for all others except near the problem is the same. The result file comes with "nice" boundaries around valid data areas containing values from interpolation between nodata and valid data

this is less visible on data with small range between data and nodata, that is why i missed it at first.

i noticed that on a file with 0 < data < 10 000 and a nodata value around 65000

Keep up the good work

gdal is a wonderfull tool

Change History (7)

comment:1 by ocarre, 15 years ago

Version: unspecified1.6.0

comment:2 by Even Rouault, 15 years ago

I've used the below program to generate a 100x100 4 band GeoTIFF whose first band value is 1000 except one point of 9 whose value is 65531 (2000 for uniform value - 65532 for nodata value of second band, etc...)

Then I do 'gdalwarp -r cubic -srcnodata "65531 65532 65533 65534" -ts 80 80 test_warp.tif test_warp2.tif' and the result I got looks ok. Nodata pixels are not taken into account as expected.

Perhaps you could attach your file (possibly a small one or an extract of a larger) and the exact command you use, so that we can reproduce the issue.

#include <gdal.h>

int main(int argc, char* argv[])
{
  GDALAllRegister();
  GDALDriverH hDriver = GDALGetDriverByName("GTiff");
  GDALDatasetH hDS = GDALCreate(hDriver, "test_warp.tif", 100 ,100, 4,GDT_UInt16,NULL);
  double adfGeoTransform[] = { 20, .1, 0, 40, 0, -.1 };
  GDALSetGeoTransform(hDS, adfGeoTransform);
  int i, j;
  unsigned short val1 = 65531;
  unsigned short val2 = 65532;
  unsigned short val3 = 65533;
  unsigned short val4 = 65534;
  GDALFillRaster(GDALGetRasterBand(hDS, 1), 1000, 0);
  GDALFillRaster(GDALGetRasterBand(hDS, 2), 2000, 0);
  GDALFillRaster(GDALGetRasterBand(hDS, 3), 3000, 0);
  GDALFillRaster(GDALGetRasterBand(hDS, 4), 4000, 0);
  for(i=0;i<100;i+=3)
  {
      for(j=0;j<100;j+=3)
      {
          GDALRasterIO(GDALGetRasterBand(hDS, 1), GF_Write, i,j,1,1,&val1,1,1,GDT_UInt16,0,0);
          GDALRasterIO(GDALGetRasterBand(hDS, 2), GF_Write, i,j,1,1,&val2,1,1,GDT_UInt16,0,0);
          GDALRasterIO(GDALGetRasterBand(hDS, 3), GF_Write, i,j,1,1,&val3,1,1,GDT_UInt16,0,0);
          GDALRasterIO(GDALGetRasterBand(hDS, 4), GF_Write, i,j,1,1,&val4,1,1,GDT_UInt16,0,0);
      }
  }
  GDALClose(hDS);
  return 0;
}

comment:3 by ocarre, 15 years ago

Hello, thanks for the quick reply, i have looked into you code sniplet and modified it to reproduce the problem i have. The trouble comes from having more than one no data value in one band. here is your code modified to show this.

#include <gdal.h>

 int main(int argc, char* argv[])
 {
   GDALAllRegister();
   GDALDriverH hDriver = GDALGetDriverByName("GTiff");
   GDALDatasetH hDS = GDALCreate(hDriver, "test_warp.tif", 100 ,100,  1,GDT_UInt16,NULL);
   double adfGeoTransform[] = { 20, .1, 0, 40, 0, -.1 };
   GDALSetGeoTransform(hDS, adfGeoTransform);
   int i, j;
   unsigned short val1 = 65531;
   unsigned short val2 = 65532;
   unsigned short val3 = 65533;
   unsigned short val4 = 65534;
   GDALFillRaster(GDALGetRasterBand(hDS, 1), 1000, 0);

   for(i=0;i<100;i++)
   {
       for(j=45;j<55;j++)
       {
	 
	 if ( j < 50 )
	   {
	     GDALRasterIO(GDALGetRasterBand(hDS, 1), GF_Write,  i,j,1,1,&val1,1,1,GDT_UInt16,0,0);
	   }
	 else
	   {
	     GDALRasterIO(GDALGetRasterBand(hDS, 1), GF_Write,  i,j,1,1,&val2,1,1,GDT_UInt16,0,0);  
	   }
	   
       }
   }
   GDALClose(hDS);
   return 0;
 }

thanks again

comment:4 by ocarre, 15 years ago

I'v taken a quick look into gdal source and it seems to me that GDALWarpNoDataMasker can only take one no data value to create some nodata mask (i haven't had time to figure out exactly how that works) which is used later. As of now it looks like it is not a "bug", it is just the way gdal works.

comment:5 by ocarre, 15 years ago

Also i said there was no problem with the nearest neighbour algorithm but as nodata is handled no doferently from the other algorithms there must be the same result, maybe it is not so obvious because of the way the algorithm itself works.

comment:6 by Even Rouault, 15 years ago

Resolution: invalid
Status: newclosed

Yes, definitely, GDAL only supports 1 nodata value per band. The multiple values you can pass with the -srcnodata flag are one for each band... So, the behaviour you get is a feature not a bug...

If you want to have the effect of several nodata values per band, you'd need to add something like an alpha band to your dataset. This could be done by creating a GeoTIFF of the dimension of your raster file with values of 0 for transparent region, and 255 for opaque ones. Then you can combine your original file and this mask dataset into a VRT file, and use it as the input of gdalwarp...

Or if you want a quick&very dirty hack to achieve your result and provided that you are in a position to build GDAL yourself, it should be easy to hack GDALWarpNoDataMasker so that it can recognize the different values you are interested in as nodata values... Quick&dirty, yeah...

comment:7 by ocarre, 15 years ago

All right thanks for the support, i guess i ll use one or the other of your solutions, i definitely can hack gdal but i m not sure yet if i want to custmize it without making a nice change that can be commited. (by the way it seems quite hard at first glance because it involes modifying several interfaces)

anyway keep up the good work.

Note: See TracTickets for help on using tickets.