Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gdal_translate: scale ignores nodata values #2105

Closed
aloboa opened this issue Dec 13, 2019 · 3 comments
Closed

gdal_translate: scale ignores nodata values #2105

aloboa opened this issue Dec 13, 2019 · 3 comments

Comments

@aloboa
Copy link

aloboa commented Dec 13, 2019

Expected behavior and actual behavior.

Values that are nodata in the original image should become nodata in the result

Steps to reproduce the problem.

Artificial small test image: https://www.dropbox.com/s/0vstg5cexlxodl7/imatest.tif
Result: https://www.dropbox.com/s/51uidcqz90clhnw/imateststretchgdal2.tif

$ gdalinfo -nomd imatest.tif
.../...
Band 1 Block=100x6 Type=Float32, ColorInterp=Gray
Min=-8.689 Max=7.383
Minimum=-8.689, Maximum=7.383, Mean=-0.049, StdDev=1.985
NoData Value=-3.39999999999999996e+38
Band 2 Block=100x6 Type=Float32, ColorInterp=Undefined
Min=-17.378 Max=14.766
Minimum=-17.378, Maximum=14.766, Mean=-0.098, StdDev=3.970
NoData Value=-3.39999999999999996e+38
Band 3 Block=100x6 Type=Float32, ColorInterp=Undefined
Min=1.311 Max=17.383
Minimum=1.311, Maximum=17.383, Mean=9.951, StdDev=1.985
NoData Value=-3.39999999999999996e+38

$ gdal_translate imatest.tif imateststretchgdal2.tif -ot Byte -scale -4.06862497329712 4.16076647758484 1 255 -scale -8.13724994659424 8.32153295516968 1 255 -scale 5.93137502670288 14.1607660102844 1 255

$ gdalinfo imateststretchgdal2.tif
.../...
Band 1 Block=100x27 Type=Byte, ColorInterp=Gray
NoData Value=-3.39999999999999996e+38
Band 2 Block=100x27 Type=Byte, ColorInterp=Undefined
NoData Value=-3.39999999999999996e+38
Band 3 Block=100x27 Type=Byte, ColorInterp=Undefined
NoData Value=-3.39999999999999996e+38

while NoData value is set, pixels that where NoData in the original
become 0 in the stretched image

Operating system

Debian Buster

GDAL version and provenance

$ gdalinfo --version
GDAL 2.4.3, released 2019/10/28

@jratike80
Copy link
Collaborator

There are at least two ways to handle the case.

  1. Assign a nodata value to output

gdal_translate imatest.tif imateststretchgdal_nodata.tif -ot Byte -scale -4.06862497329712 4.16076647758484 1 255 -scale -8.13724994659424 8.32153295516968 1 255 -scale 5.93137502670288 14.1607660102844 1 255 -a_nodata 0

  1. Don't use nodata but use alpha instead.
gdalwarp -dstalpha imatest.tif imatest_alpha.tif
gdal_translate imatest_alpha.tif imateststretchgdal2_alpha.tif -ot Byte -scale -4.06862497329712 4.16076647758484 1 255 -scale -8.13724994659424 8.32153295516968 1 255 -scale 5.93137502670288 14.1607660102844 1 255

I find some issues:

  • If output is 8 bit is does not make sense to copy NoData Value=-3.39999999999999996e+38 into it
  • It is not documented that scaling with nodata value needs some consideration
  • There is a missing fearure in GDAL that would do something for the nodata when image is scaled or the data type is changed so that the nodata value can't be kept.

I am not sure how the automatic conversion should work. Turnign nodata into alpha/mask band feels best in theory but users might be surprised by the extra band.

@rouault
Copy link
Member

rouault commented Dec 13, 2019

pixels that where NoData in the original become 0 in the stretched image

Yes, -3.39999999999999996e+38 is not a valid value for Byte datatype. In #2106 , I'm changing the behaviour to issue a warning and clamp to a valid value.

rouault added a commit that referenced this issue Dec 13, 2019
gdal_translate: clamp/round source nodata value when not compatible of the target data type. Was already done when using -a_nodata, but not with implicit copy (fixes #2105)
@aloboa
Copy link
Author

aloboa commented Dec 17, 2019

I confirm that nodata values are respected if the output is a float image:
$ gdal_translate imatest.tif imateststretchgdal.tif -scale -4.06862497329712 4.16076647758484 1 255 -scale -8.13724994659424 8.32153295516968 1 255 -scale 5.93137502670288 14.1607660102844 1 255

The problem is that such an image cannot be converted to Byte with nodata set as 0 because 0 is within the valid range of values (despite the scale had been defined in gdal_translate with 1:255 range in the output). The goal is stretching the float image to the interval 1:255 and write the result as Byte with nodata set as 0. Note that, in the example, nodata values occur in all bands of a limited region, but in genereal, nodata values can occur for a pixel in some bands only, thus a mask is not a general solution.

I understand the correct result can be obtained by using gdal_calc.py after gdal_translate, but a clamp option in gdal_translate would be convenient.
#1825

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants