Border of zeroes when exporting image in Earth Engine

exportgoogle-earth-enginegoogle-earth-engine-javascript-apinodata

Problem description

When exporting any clipped image in Earth Engine using Export.image.toDrive function; it always converts masked pixels (nodata) to zeroes (0). The only exception from this malfunction is Float type images. This problem can be clearly shown when the exported image is displayed in a desktop software (e.g. ArcGIS).

Temporary Solution

As a temporary solution, one must convert any raster pixel depth to float before exporting. The downside of this solution is that the exported image will be larger in size.

Reproducible example

var dem = ee.Image("NASA/NASADEM_HGT/001");
var aoi = ee.FeatureCollection("FAO/GAUL/2015/level0").filter(ee.Filter.eq('ADM0_NAME', 'Iraq'));
var elevationVis = {
  min: -15.0,
  max: 5000.0,
  palette: [
    '0602ff', '235cb1', '307ef3', '269db1', '30c8e2', '32d3ef', '3ae237',
    'b5e22e', 'd6e21f', 'fff705', 'ffd611', 'ffb613', 'ff8b13', 'ff6e08',
    'ff500d', 'ff0000', 'de0101', 'c21301'
  ]}
  
Map.addLayer(dem.select('elevation').clip(aoi), elevationVis, 'Elevation')
Map.centerObject(aoi)

// Export image normally which converts nodata to 0.
Export.image.toDrive({
  image: dem.select('elevation').clip(aoi), //16 bit signed integer raster
  fileNamePrefix: 'Problem Image',
  description: 'Problem_Image',
  region: aoi,
  maxPixels: 1e10,
  crs: 'EPSG:4326',
  crsTransform: [0.0002777777777777778,0,0.0001388888888888889,0,-0.0002777777777777778,-0.0001388888888888889],
  folder: "Image Production"
})

// Export image after converting to float which keeps nodata as nodata.
Export.image.toDrive({
  image: dem.select('elevation').clip(aoi).toFloat(), //32 bit float raster
  fileNamePrefix: 'Solution Image',
  description: 'Solution_Image',
  region: aoi,
  maxPixels: 1e10,
  crs: 'EPSG:4326',
  crsTransform: [0.0002777777777777778,0,0.0001388888888888889,0,-0.0002777777777777778,-0.0001388888888888889],
  folder: "Image Production"
})

What is required?

To mask images as expected where areas out of clipped geometry marked as nodata not zeroes, without the need to convert integer images to float.

Best Answer

Matt Hancher answered a similar question in the Google Earth Engine Developers group:

In Earth Engine all data carries a mask, but GeoTIFFs don't work in quite the same way.

The most common practice in the world of GeoTIFFs is indeed just to use a nodata value. By default Earth Engine will represent masked pixels the value zero. If your data uses zero as a meaningful data value, just call image.unmask(42) before you export and the masked pixels will have the value 42 instead (or whatever value you prefer).

If instead you want to export the mask as a separate band, you can get the mask using image.mask() and then add that as an extra band before you export. (By default it will be a floating point number in the range 0-1, but if you're exporting integer data then you can do something like image.mask().multiply(255).round().uint8() to generate an 8-bit mask, for example.)

https://groups.google.com/g/google-earth-engine-developers/c/REn7f6w-Jqo/m/y7AxzMu2BAAJ

Related Question