NoData-value not fully preserved when exporting GeoTIFF

I have a bunch of dim-files, all containing several different bands, and I want to export them to single band GeoTIFF-files, readable in ArcMap 9.3, ArcMap 10, Erdas Imagine and QGIS.

In order to find a good approach I’ve created some BEAM-DIMAP testdata (attached) containing:

  1. Unsigned 8 bit (uint8) with NoData as 255
  2. Signed 8 bit (int8) with NoData as -128
  3. Unsigned 16 bit (uint16) with NoData as 65535
  4. Signed 16 bit (int16) with NoData as -32768
  5. Unsigned 32 bit (uint32) with NoData as 2147483647
  6. Signed 32 bit (int32) with NoData as -2147483648
  7. Floating-point 32 bit (float32) with NoData as NaN (-3.402823466e+38)

The next step was to create a python script exporting GeoTIFF-files (also attached).

testdata.zip (95.8 KB)

When looking at the exported GeoTIFF-files in SNAP 4 (or in BEAM 5) the NoData value is preserved. When looking at the exported GeoTIFF-files in ArcMap 9.3, ArcMap 10, Erdas Imagine or QGIS the NoData value is NOT preserved. The reason for this seems to be that the NoData-information is stored in the “BEAM-DIMAP”-header of the GeoTIFF-files, according to http://www.brockmann-consult.de/beam/doc/help/geotiff/ExportGeoTIFF.html

Question 1:
It seems to be two ways storing the NoData-value inside a GeoTIFF-file, the SNAP-way and the “all other software”-way. The first question is quite obvious. Can you update the SNAP GeoTIFF-export function in order to store the NoData-value inside a GeoTIFF-file the “all other software”-way?

Question 2:
For various reasons my plan B is to use ArcMap 9.3 (Python 2.5, 32-bit). I would like to use Python (if possible without snappy) in order to extract the NoData-information from the BEAM-DIMAP header in the GeoTIFF-file. Do you know if this is possible? Do you have any experience or recommendations?

2 Likes

Hi Niklas,

Regarding Question 1:
What is the “all other software”-way of storing no-data in GeoTIFF?
Actually GeoTIFF has no means to indicate a certain value to be used as no-data.
That’s why we add the DIMAP header as additional metadata.
We could convert int8 bands to float and set all -128 to NaN. But I think you don’t want to have the data changed in this way.
If you have a good idea how we an tell other software which value is the no-data value, please tell us. We would be happy to consider this for the further development.

Regarding Question 2:
You need a library in python which can read GeoTIFF and gives you access to the metadata and then parse the store DIMAP xml.
Maybe the user @hollstein has found a way to do so in this thread.

cheers

Hi @marpet

I just want to give some feedback.

Regarding Question 1:
After looking into this I’m pretty sure it’s not obvious how to make SNAP tell all other software which value is the no-data value. There is no “all other software”-way for instance.

Regarding Question 2:
Thank you for the tip!
I’ve succeeded extracting the DIMAP-xml from the header of the tif-file using ArcMap 9.3 (Python 2.5, 32-bit). I did this with the single band GeoTIFF-files (exported from SNAP):

...
pilImage = Image.open(inputFullFilename, "r") # Python Imaging Library 1.1.7 for Python 2.5
dimapXmlString = pilImage.tag[65000] # Extract the DIMAP-xml from the header of the tif-file
dimapXmlRoot = xml.etree.ElementTree.fromstring(dimapXmlString) # New in Python 2.5
dimapXmlElement = dimapXmlRoot.find('Image_Interpretation')
dimapXmlElement = dimapXmlElement.find('Spectral_Band_Info') # Assuming 1 band only
dimapDataType = dimapXmlElement.find('DATA_TYPE').text
dimapNoDataValueUsed = dimapXmlElement.find('NO_DATA_VALUE_USED').text
dimapNoDataValue = dimapXmlElement.find('NO_DATA_VALUE').text
...

Then, to set the NoData-value in ArcMap 9.3 a straight forward way is to use CopyRaster-tool (example below when dimapDataType == “int32”):

gp = arcgisscripting.create(9.3)
gp.CopyRaster_management(inputFullFilename, outputFullFilename, "DEFAULTS", dimapNoDataValue, dimapNoDataValue, "NONE", "NONE", "32_BIT_SIGNED")

But when (dimapDataType == “float32”) and (dimapNoDataValue == “NaN”) the CopyRaster-tool will not work. As a workaround you can then use Con-tool (requires Spatial Analyst extension)

gp.Con_sa(inputFullFilename, inputFullFilename, outputFullFilename, None, "VALUE > -3,4028235e+038")

//Niklas

Hi Marpet and Niklas,

How about treating GDAL-way as the “all other software”-way since it is very commonly used [1]. In the GDAL GeoTIFF specifications [2] it says:
“GDAL stores band nodata value in the non standard TIFFTAG_GDAL_NODATA ASCII tag (code 42113) for files created with the default profile GDALGeoTIFF. Note that all bands must use the same nodata value. When BASELINE or GeoTIFF profile are used, the nodata value is stored into a PAM .aux.xml file.”

Would it be possible to add TIFFTAG_GDAL_NODATA to the GeoTIFFs created by SNAP?

Thanks

[1] https://en.wikipedia.org/wiki/GDAL#Software_using_GDAL.2FOGR
[2] http://www.gdal.org/frmt_gtiff.html

1 Like