I'm trying to stack two images with gdal_merge.py -separate so that I can use the NoData values in the second band to mask the first band (was going to use gdal_translate -b 1 -mask 2). The first image (or band 1 after the merge) has no NoData values, while in the second image NoData = 0. However when I use gdal_merge to stack the two images, the NoData for the second image/band is removed and set back to 0.

There is a "-a_nodata output_nodata_value" option in gdal_merge, but I don't want to set the first band's NoData values, just the second. Is this possible?

Or is there another way I can use the second image's NoData values to mask out values in the first without stacking the images via merge? That is my ultimate goal. Maybe I can achieve this via gdal_calc?

1 Answer 1


As I understand, here is your setup:

  • A: raster
  • B: raster, same size as A
  • nodata_b: nodata value for B; 0 in this instance

Your goal is to create raster C, which is A masked by valid B.

C = A where (B != nodata_b) else nodata_a

The question now concerns what are valid possibilities for nodata_a. This is something that you don't give, so there are a few options. Remember that rasters are required to have a value for each pixel. The nodata tag is just there to help interpret such values within the raster array as having a special property (nodata). You need to determine what nodata_a should be.

If nodata_a is allowed to be 0, this is pretty trivial.

gdal_calc.py -A rasterA.tif -B rasterB.tif --outfile=rasterC.tif \
--calc ="A*(B!=0)" --NoDataValue=0

Here, B!=0 is translated into 0 for False and 1 for True on a pixel-by-pixel basis. So 1*value = value and 0*value = 0.

If nodata_a needs to be a specific value, things become a little more tricky. Let's say 0 is a meaningful value in raster A. Setting nodata_a to 0 would mean that meaningful data is absent in raster C. Maybe there are no meaningful negative values in A (and the datatype of the raster permits negative values). So if nodata_a==-999.

gdal_calc.py -A rasterA.tif -B rasterB.tif --outfile=rasterC.tif \
--calc ="A*(B!=0) + ((B==0)*-999)" --NoDataValue=-999

Here, there are two parts to the calculation. On the left is the same calculation as above -- A where B!=0 else 0. On the right, the result is either 0 for valid pixels or -999 for invalid. Summing the left and right values will result in the correct values of A where valid and -999 where invalid.

You could of course substitute any value you want for -999, as long as that value is guaranteed to not be present in the valid portion of A.

  • Thanks Logan! I actually managed to get what I wanted with this: "gdal_calc.py --calc="200*(B==0)+A" --type=Byte --NoDataValue=200 --co COMPRESS=LZW --outfile=%s -A %s -B %s' % (output, input, mask)" but your answer works too
    – user20408
    Oct 3, 2016 at 14:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.