Search code examples
rimagergbraster

How to convert categorial raster to mapped RGB values in R?


How do we convert a single band categorial raster to a three-dimensional RGB array?

Lets say we want to define the color per value(category) and get an RGB array with corresponding decimal RGB values.

E.g. in the example below how would I get rgb_array given r and myCol?

library(raster)
# sample raster
r <- raster(ncol=4, nrow=4)
r[] <- c(rep(1, 8), rep(2, 8))

# plot 1=red, 2=blue
myCol = c("red", "blue")
plot(r, col=myCol)

# rgb_array is the desired output, but how to get it programatically from r?
red_band <- c(rep(255, 8), rep(0, 8))
green_band <- c(rep(0, 8), rep(0, 8))
blue_band <- c(rep(0, 8), rep(255, 8))
rgb_array <- array(c(red_band, green_band, blue_band), dim= c(4, 4, 3))

Solution

  • You can do this with terra::subst.

    Example data

    library(terra)
    #terra 1.6.21
    x <- rast(ncol=4, nrow=4, vals=c(rep(1, 8), rep(2, 8)))
    

    Solution

    from <- 1:2
    to <-  t(col2rgb(c("red", "blue")))
    r <- subst(x, from, to, names=c("red", "green", "blue"))
    plotRGB(r)
    

    And to a three-dimensional array from r, you can do

    ar <- as.array(r)
    

    You can also use terra::colorize for that. But thanks to your question I found a bug in that method so you need to use "terra" version 1.6-21 or higher. That is currently the development version that you can install like this: install.packages('terra', repos='https://rspatial.r-universe.dev')

    Set the color table that matches the values with a color, and use colorize.

    coltab(x) <- data.frame(value=1:2, col=c("red", "blue"))
     
    rgb <- colorize(x, "rgb")
    rgb
    #class       : SpatRaster 
    #dimensions  : 4, 4, 3  (nrow, ncol, nlyr)
    #resolution  : 90, 45  (x, y)
    #extent      : -180, 180, -90, 90  (xmin, xmax, ymin, ymax)
    #coord. ref. : +proj=longlat +datum=WGS84 +no_defs 
    #source      : memory 
    #colors RGB  : 1, 2, 3 
    #names       : red, green, blue 
    #min values  :   0,     0,    0 
    #max values  : 255,     0,  255 
    

    And now you can do

    plot(rgb)
    ar2 <- as.array(rgb)
    

    To get the equivalent to plot(x) (because x has a color-table)