How to fill no data cells in a raster map in GRASS GIS

I need to fill onshore NULL (no data) cells in the DEM raster map shown below.

dem1km-rast.png

The first step is to fill no data cells by interpolation.

g.region rast=dem1km
r.fillnulls input=dem1km output=dem1km_nullfilled method=bilinear

However, r.fillnulls fills not only small islands of NULL cells, but also any NULL cells outside the valid raster boundaries. The output from r.fillnulls will be rectangular regardless of the original shape of the input raster map.

dem1km_nullfilled-rast.png

I need to create a mask that only covers the original data extent, but it should also include no data areas. First, create a mask using the original DEM raster map.

r.mapcalc expression='dem1km_mask=if(!isnull(dem1km),1,null())'

dem1km_mask-rast.png

Convert this raster mask to vector.

r.to.vect input=dem1km_mask output=dem1km_mask type=area

dem1km_mask-vect.png

There are island areas where no data cells are. These areas are not assigned a centroid, so let’s assign a centroid to them.

v.centroids input=dem1km_mask output=dem1km_mask_nullfilled

dem1km_mask_nullfilled-vect.png

Create a new column “dissolve” and assign the same value of 1 to this column for all areas. Then, dissolve all areas by this column.

v.db.addcolumn map=dem1km_mask_nullfilled column='dissolve int'
v.db.update map=dem1km_mask_nullfilled column=dissolve value=1
v.dissolve input=dem1km_mask_nullfilled output=dem1km_mask_dissolved column=dissolve

dem1km_mask_dissolved-vect.png

Convert the dissolved vector to raster.

v.to.rast input=dem1km_mask_dissolved output=dem1km_mask_dissolved use=val

The above steps failed once for me, but that’s OK. We can directly convert the undissolved vector mask to raster. This method can even be better and faster if we don’t need a dissolved vector mask.

v.to.rast input=dem1km_mask_nullfilled output=dem1km_mask_dissolved use=value
# optionally, you can create a vector mask if you need one
r.to.vect input=dem1km_mask_dissolved out=dem1km_mask_dissolved type=area

dem1km_mask_dissolved-rast.png

Extract the filled DEM by the final mask.

r.mapcalc expression='dem1km_clean=if(!isnull(dem1km_mask_dissolved),dem1km_nullfilled,null())'

dem1km_clean-rast.png