rmagick

Converting and saving grayscale image to e.g. viridis colour scheme


Let's say I have this image:

enter image description here

I want to convert the grayscale to a viridis colour schema and save it. I have got it to work using this chuck of code:

system('wget https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Von_einem_Schrecklichen_vnd_Wunderbarlichen_Cometen_so_sich_den_Dienstag_nach_Martini_dieses_lauffenden_M._D._Lxxvij._Jahrs_am_Himmel_erzeiget_hat_%28grayscale%29.png/320px-thumbnail.png')
library(png)
library(viridisLite)
x <- png::readPNG('320px-thumbnail.png')
x <- x[, ,1]
intmat <- x * 255
image(1:nrow(intmat), 1:ncol(intmat), intmat, col=viridis(256))

Which results in this:

enter image description here

I'm very happy with how the colour schema was applied. However, this is not the original image anymore, but just a plot. What I want is to exchange each pixel in the grayscale, and save the converted image as a png again, so without using image(). I had a look at the image_convert function in magick, but couldn't figure out how to get the desired behavior.


Solution

  • I'm sure there are ways to do this without reinventing the wheel, but using just the libraries you have loaded, it's fairly straightforward to manipulate the viridis colours to split them into 3 channels and save as png.

    Here's a function to do the job for any png:

    png_to_viridis <- function(in_file, out_file)
    {
      PNG_raw <- readBin(in_file, "raw", 10e6)
      x <- png::readPNG(PNG_raw)
      intmat <- 255 * x[, ,1] 
      virmat <- viridisLite::viridis(256)[intmat + 1]
      virmat <- c(substr(virmat, 2, 3), substr(virmat, 4, 5), 
                  substr(virmat, 6, 7), substr(virmat, 8, 9))
      virmat <- as.numeric(as.hexmode(virmat))/255
      dim(virmat) <- c(dim(intmat), 4)
      png::writePNG(virmat, out_file)
    }
    

    So now if I do:

    png_to_viridis("https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Von_einem_Schrecklichen_vnd_Wunderbarlichen_Cometen_so_sich_den_Dienstag_nach_Martini_dieses_lauffenden_M._D._Lxxvij._Jahrs_am_Himmel_erzeiget_hat_%28grayscale%29.png/320px-thumbnail.png",
                   "viridis.png")
    

    I get the following result saved as viridis.png:

    enter image description here