The following demonstrates how to create a single image from various raster/vector data sources. No clunky Python/R, etc or their endless dependencies.
A single dependency on GDAL, which most GIS software/libraries/packages rely on anyway, without numerous layers of abstraction. Your maintenance just became far less painless. Take the evening off.
Data: ETOPO_2022 1KM resolution bathymetry/elevation, NaturalEarth and various trail vector data sets.
bbox="-126.5,31,-104,49.5"
crs="EPSG:4269"
height="800"
gdal pipeline
! mosaic --resolution highest
[
! read ETOPO_2022_v1_30s_N90W180_bed.tif
! reproject --bbox $bbox --bbox-crs $crs --output-crs $crs --size 0,${height}
! hillshade --variant multidirectional --altitude 20 -z 6
! color-map --color-map bathy-color-map.txt --add-alpha
]
[
! read ETOPO_2022_v1_30s_N90W180_bed.tif
! reproject --bbox $bbox --bbox-crs $crs --output-crs $crs --size 0,${height}
! clip --like natural_earth_vector.gpkg --like-layer ne_50m_admin_0_countries --allow-bbox-outside-source
! hillshade --variant multidirectional --altitude 20 -z 6
! reproject --bbox $bbox --bbox-crs $crs --output-crs $crs --size 0,${height}
! color-map --color-map basemap-color-map.txt --add-alpha
]
[
! concat -i natural_earth_vector.gpkg -l ne_10m_lakes -l ne_50m_lakes -l ne_110m_lakes --mode single
! clip --bbox $bbox --bbox-crs $crs
! rasterize --nodata -9999 --burn 127 --size 0,${height}
! reproject --dst-crs $crs --size 0,${height} --bbox $bbox --bbox-crs $crs
! color-map --color-map lakes-color-map.txt --add-alpha
]
[
! read trails.gpkg
! rasterize --dialect sqlite --ot Byte --init 0 --burn 127 --size 0,${height} --sql 'select st_simplifypreservetopology(st_buffer(makeline(wkb_geometry), .03), .001) from milemarkers where trail_id in (1,2,9,27) group by trail_id order by trail_id, mile asc'
! color-map --color-map trails-color-map.txt --add-alpha
! reproject --dst-crs $crs --size 0,${height} --bbox $bbox --bbox-crs $crs
]
! write -o result.png --overwrite
Color maps in standard GRASS/QGIS, etc format:
bathy-color-map.txt: 0% 0 4 8 255 100% 16 24 64 255 basemap-color-map.txt: nv 0 0 0 0 0% 0 0 0 255 100% 32 32 32 255 lakes-color-map.txt: nv 0 0 0 0 0% 32 36 96 255 100% 48 56 128 255 trails-color-map.txt: nv 0 0 0 0 127 127 32 32 255
That's it!