3

I'm trying to come up with a way to patch over raster A with data from raster B. Extent of raster A can be smaller than raster B.

More specifically, I'd like to patch over nodata values from raster A with raster B values as well as create pixels in raster A where they exist in raster B.

Simple gdal_merge doesn't work for me as this doesn't work:

gdal_merge -o out.tif rasterA.tif rasterB.tif

as it is replacing values in raster A with values of raster B and would like values in raster A to be kept where they are not nodata.

and this won't work

gdal_merge -o out.tif rasterB.tif rasterA.tif

as it will replace values in raster B with nodata from raster A.

gdal_calc won't work, as rasters have different dimesions.

I'm aware that this such conditional logic can be implemented in Arc, but I'm looking for a solution using GDAL. Any suggestions?

4

Formulating the question helped me answer it myself. To solve this, 3 steps are required:

Step 1: create a nodata mask equal in size to raster B (255 is the nodata value)

gdal_calc -A rasterB.tif --outfile=mask.tif --calc="255"

Step 2: merge over raster A over this mask

gdal_merge -o rasterA_extended.tif mask.tif rasterA.tif

Step 3: conditional gdal_calc, update only where nodata

gdal_calc -A rasterA_extended.tif -B rasterB.tif --outfile=result.tif --calc="A*(A<255) + B*(A==255)"

Additionally, if don't want to copy over value, but you need to set all pixels to be patched to a specific value (0 in my case), you can use this logic:

gdal_calc -A rasterA_extended.tif -B rasterB.tif --outfile=!res.tif --calc="A*(A<255) + 0*(logical_and(A==255,B<>255)) + A*(logical_and(B==255,A<>255))" Note that B is never assigned.

2

You can do this with VRTs. From the gdalbuildvrt documentation:

If there is some amount of spatial overlapping between files, the order of files appearing in the list of source matter: files that are listed at the end are the ones from which the content will be fetched. Note that nodata will be taken into account to potentially fetch data from less prioritary datasets, but currently, alpha channel is not taken into account to do alpha compositing (so a source with alpha=0 appearing on top of another source will override is content). This might be changed in later versions.

So for your example, your command would be something like:

gdalbuildvrt output.vrt rasterA.tif rasterB.tif

You may need to do some pre-processing to deal with the nodata.

Once you get the desired result, you can gdal_translate the VRT as necessary.

If needed, you can even control the handling of multiple input resolutions using the -resolution switch (average is the default) in gdalbuildvrt.

1

Actually this can be done with gdal_merge by telling it to ignore the nodata values with the -n flag:

gdal_merge -n -32768 -o out.tif rasterB.tif rasterA.tif

This will merge rasterA on top of rasterB but not in places where rasterA has nodata pixels (of the value -32768 in this case).

From the gdal_merge documentation:

-n nodata_value: Ignore pixels from files being merged in with this pixel value

2
  • I've tried that, this unfortunately doesn't work if your rasters don't fit in memory. Jan 8 '16 at 17:06
  • Ah, the old memory problem. If you are not afraid of Python you could copy the logic from gdal_merge.py and use it for a windowed/striped approach - which would solve the issue of fitting the whole dataset into memory.
    – Kersten
    Jan 9 '16 at 18:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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