CLI Raster Viewer

Occasionally, you just want to view a raster, locally or remote. Possibly, just a bounding box of a large or virtual raster set. Here's a simple function placed in your .bashrc to do just that. All the heavy lifting is done by GDAL, version >= 3.12.0.

# You will need a default viewer. You can set it with the environment variable:
export DEFAULT_VIEWER=/path/to/myViewer

#...or specify it with viewRaster:
--viewer=/path/to/myViewer

# Let's start with a few usage examples, most simply:
viewRaster source.tif

# that will create an image using all the defaults in the current directory and displayed with the provided image viewer. If image exists, it will be overwritten. Default output image:
viewRaster_tmp.png

# You can be more specific. Output will be overwritten:
viewRaster --input="source.tif" --output="out.png" --viewer=myViewer

Let's try something more complex. Say we want to view a bounding box of a very large virtual DEM on AWS S3. For instance, a collection of 10 meter DEMs of the U.S. and we want to clip it, reproject it and colorize it. Try this:

viewRaster \
   --input="/vsis3/prd-tnm/StagedProducts/Elevation/13/TIFF/USGS_Seamless_DEM_13.vrt" \
   --output="color.png" \
   --bbox=-123,45,-120.8,46 \
   --epsg=EPSG:3857 \
   --height=800 \
   --color-map=color-map.txt

# Note, color-map.txt contains:

0 0 0 0
192 0 128 220
255 220 220 255

The result should look like Mt. Hood and the Columbia River:

The important part of viewRaster is just a splash of GDAL, v3.12.0:

   gdal raster pipeline \
      ! read -i $input \
      ! select --band $band \
      $bbox \
      ! resize --size=$width,$height \
      ! scale --dst-min 0 --dst-max 255 --ot Byte \
      ! reproject --dst-crs $epsg \
      $colorMap \
      ! write -o $output --progress

The complete BASH function looks like this. Just toss it into your .bashrc and it will be there when you need it:

viewRaster () {
   local input="$1"
   local output="viewRaster_tmp.png"
   local band=1
   local width=0
   local height=0
   local epsg="EPSG:4326"
   local bbox=""
   local colorMap=""
   local viewer=$IMAGE_VIEWER
   local help=0
   while [ "$#" -gt 0 ]; do
      case "$1" in
         --width=*) width="$(echo -n ${1#*=} |sed 's/[^-0-9]//g')"; shift 1;;
         --height=*) height="$(echo -n ${1#*=} |sed 's/[^-0-9]//g')"; shift 1;;
         --input=*) input="$(echo -n ${1#*=} |sed "s/[^0-9a-z\_\.\ \"-\/]//gi")"; shift 1;;
         --output=*) output="$(echo -n ${1#*=} |sed "s/[^0-9a-z\_\.\ \"-\/]//gi")"; shift 1;;
         --band=*) band="$(echo -n ${1#*=} |sed 's/[^0-9]//g')"; shift 1;;
         --epsg=*) epsg="$(echo -n ${1#*=} |sed 's/[^0-9a-z\:]//gi')"; shift 1;;
         --bbox=*) bbox="$(echo -n ${1#*=} |sed 's/[^0-9,-\.]//gi')"; shift 1;;
         --viewer=*) viewer="$(echo -n ${1#*=} |sed 's/[^0-9a-z\_\.\-\ \"]//gi')"; shift 1;;
         --color-map=*) colorMap="$(echo -n ${1#*=} |sed "s/[^0-9a-z\_\.\ \"-\/]//gi")"; shift 1;;
         --help=*) help="$(echo -n ${1#*=} |sed 's/[^0-9]//g')"; shift 1;;
         --help) help=1; shift 1;;
         *) shift 1;;
      esac
   done

   local isVsi="$(echo "${input}" | /bin/grep -E "^/vsi")"
   [[ -z "${input}" ]] || [[ -z "${output}" ]] && help=1
   [[ ! -f "${input}" ]] && [[ ${#isVsi} -lt 1 ]] && help=1
   [[ ${#output} == 0 ]] && echo "No --output file specified" && help=1
   if [ ${#viewer} == 0 ] || [ ! -f $viewer ] ; then
      echo "No image viewer found. Set environment variable IMAGE_VIEWER or specify viewer with --viewer" && help=1
   fi

if [ $help -gt 0 ] ; then
cat<<EOF
viewRaster requires GDAL v3.12.0 or greater

Required:
   --input     : input raster
Optional:
   --output    : output image your viewer will open, png suggested
                 output will overwritten. Default is ./$output
   --width     : default 800. If no width or height or both '0'. If height omitted or '0', it will be calculated.
   --height    : default 0. If width omitted or '0', it will be calculated.
   --band      : default 1.
   --epsg      : output projection, ie, EPSG:5070
   --bbox      : clip to bbox, ie, xmin,ymin,xmax,ymax . Must be deciaml degrees lng/lat.
   --viewer    : image viewer to use, default is environment variable $IMAGE_VIEWER'
   --color-map : color-map.txt used to style output raster.
   --help

Examples:
   viewRaster dem.tif
   viewRaster dem.tif --output="dem.png"
   viewRaster --input="dem.tif" --output="dem.png"
   viewRaster --input="dem.tif" --output="dem.png" --width=1024 --epsg=EPSG:5070 --bbox=-125,22,-66,50

EOF
   return
fi

   #[[ -f "$output" ]] && echo "file exists: $output" && return
   [[ $width -lt 1 ]] && [[ $height -lt 1 ]] && width=800
   [[ ${#bbox} -gt 6 ]] && bbox="! clip --bbox=${bbox} --bbox-crs=EPSG:4326 --allow-bbox-outside-source" || bbox=""
   [[ ${#colorMap} -gt 0 ]] && colorMap="! color-map --color-selection interpolate --color-map ${colorMap}" || colorMap=""

   gdal raster pipeline \
      ! read -i $input \
      ! select --band $band \
      $bbox \
      ! resize --size=$width,$height \
      ! scale --dst-min 0 --dst-max 255 --ot Byte \
      ! reproject --dst-crs $epsg \
      $colorMap \
      ! write -o $output --overwrite --progress

   [[ -f $output ]] && $viewer $output
   return 0
}