Using {leaflet} with a GeoTIFF background layer and resolving difficulties with RGB colormaps
R
Data visualization
Published
February 21, 2025
Documenting how to generate a colormap for a geo-encoded TIFF layer into a leaflet map.
TL;DR
colorvec <- terra::coltab(terra::rast(geotiff_file))[[1]] |>mutate(rgb =rgb(red, green, blue, alpha, maxColorValue =255)) |>pull(rgb)# And within the `leafem::addGeotiff()` function, add the argument:leafem::addGeotiff(colorOptions =colorOptions(palette = colorvec,domain =c(0, 255) )
Background
I’ve seen some advertisements for nice framed or shadowboxed aviation VFR sectional charts with RGB LED’s set in them to display flight categories (VFR / MVFR / IFR / LIFR), including this one on Etsy (a bargain at $500, compared to another one at $2,050).
For a little while, I thought I’d make one myself, probably driven by a Raspberry Pi or Arduino, but… code is faster and more flexible.
VFR sectional map in geoTIFF format source
The FAA provides VFR raster charts that are in geo-encoded TIFF format. The one for the entire conterminous United States is under the Planning tab as the U.S. VFR Wall Planning Geo-Tiff (Zip). It’s rather large at~60 MB.
It comes with a metadata file with a lot of data source information but is sparse on the TIFF encoding details:
The file is 300 dots per inch and 8-bit color. The data is provided as a GeoTIFF.
It does also give the latitude / longitude bounds, which I use to filter the METAR data in the next step.
…I found that the TIFF file had only 1 band (nlyr = 1).
In retrospect, it makes sense. The TIFF metadata said it was only 8-bit (256 distinct colors). If you look closely, you’ll see the color table : 1 – that’s another hint that instead of encoding a full (R, G, B) (and maybe even alpha), there’s a color lookup table someplace.
Looks a lot like a dataframe for a color lookup table
value ranges from 0 to 255
three more columns of red, green, and blue, all with values from 0 to 255
alpha is always 255 (makes sense for normal RGB files)
So somehow, the leafem::addGeotiff() function will need to get this color lookup incorporated.
Looks like there’s an argument called colorOptions, which sounds promising, but all it says is list defining the palette, breaks and na.color to be used. Not very helpful documentation.
More Google-fu, showed that there’s also a function called colorOptions. Let’s get help on that function.
So…
everything defaults to NULL
the palette argument is the palette
the breaks argument is the breaks
the domain is the domain (min/max)
That’s… not at all helpful.
I don’t even remember what bizarre guesswork and trial-and-error eventually led me to the solution.
I figured out that palette had to encode a function that would convert the index of the lookup table into some sort of color representation, which I guessed might be a hex code color representation.
The “function” ended up working fine as simply a vector of color values, since indexing into that vector looks like passing an argument into a function which yields the color value output. I worried that R uses 1-based indexing but the values in the lookup table started at 0, but it ended up being fine, presumably because of the domain argument of min/max.
It really didn’t take much code to get it to work, but for someone with zero background in colorspaces and how they’re described, it wasn’t really easy finding explanations what to do. Worked out in the end though!