Favicons From the Comfort of Your R Session

Call Me Selectively Paranoid

I don’t know about you, but I get skeeved out at the thought of submitting my photos to random websites hawking favicons. Worse, I’m supposed to download the converted image onto my computer. Yuck. I’ll admit, I’m not exactly consistent about my web hygiene, but as I sat there with my finger hovering over the submit button to just get the bloody favicon done with, I couldn’t do it.

Surely it can’t be that difficult to make a favicon. Besides, figuring out how to do this felt like a great way to procrastinate from wrestling with the intransigent CSS in my website.

What is a Favicon Anyway?

Favicons are thumbnail images that show up on web browser tabs:

favicon location on webpage

Generating them is surprisingly complicated. There are many formats you can use, but I settled on “.ico” as it has the benefit of being a single file and appears to be the most backward compatible1. Unfortunately “.ico” is a Windows icon file format of all things, and there is no out-of-the-box way to generate them on OS X. Even Photoshop requires a plug-in to generate them.

The best way I found to do this on OS X is described in a post by Michael Argentini. This requires installing imagemagick via Brew or otherwise, which felt like too much work to make a silly thumbnail.

R to the Rescue

It turns out that R makes it really easy to install and use imagemagick via the Jeroen Ooms magick package:

install.packages(magick)

This is particularly straightforward for OS X and Windows as CRAN provides pre-compiled binaries with everything packaged up. On Linux you’ll need to do some extra work to compile with the imagemagick libraries, or find a repository of pre-compiled R packages.

First we start with a square image larger than 64 x 64 and resize it to 64, 48, 32, 24, and 16 pixels to the side. I have no idea if this is best practice, but it is what the aforementioned post used. Unfortunately I don’t know how to vectorize the resize operation directly, so I’m resorting to hackily writing to disk:

library(magick)
Linking to ImageMagick 6.9.9.39
Enabled features: cairo, fontconfig, freetype, lcms, pango, rsvg, webp
Disabled features: fftw, ghostscript, x11
img.orig <- image_read(rep('~/Downloads/moon/moon-small.png', 5))
sizes <- 8 * c(2, 3, 4, 6, 8)
img.sizes <- sprintf("%dx%d", sizes, sizes)
img.sizes
[1] "16x16" "24x24" "32x32" "48x48" "64x64"
dir <- tempfile()
dir.create(dir)
files <- file.path(dir, sprintf("moon-%s.png", sizes))

img.resize <- lapply(img.sizes, image_resize, image=img.orig)
invisible(Map(image_write, img.resize, files))
list.files(dir)
[1] "moon-16.png" "moon-24.png" "moon-32.png" "moon-48.png" "moon-64.png"

To confirm this did what we thought:

par(mai=numeric(4))
plot(img.orig)
for(img in rev(img.resize)) plot(img, add=TRUE)

We can re-read the pngs into our session as a single magick object:

imgs <- image_read(files)
imgs
  format width height colorspace matte filesize density
1    PNG    16     16       sRGB  TRUE     1410   28x28
2    PNG    24     24       sRGB  TRUE     1587   28x28
3    PNG    32     32       sRGB  TRUE     2298   28x28
4    PNG    48     48       sRGB  TRUE     4086   28x28
5    PNG    64     64       sRGB  TRUE     6152   28x28

Conversion to “.ico” is trivial:

ico <- image_convert(imgs, 'ico')
image_write(ico, '~/Downloads/moon/favicon.ico')
unlink(dir, recursive=TRUE)

That’s it! It turns out that on OS X, preview can read “.ico” files, so at the shell open ~/Downloads/moon/favicon.ico confirms that indeed the “.ico” file contains all the thumbnails:

Proof that favicon file actually has all thumbnails

In theory if you put this at the top level of your website browsers will find it and use the “.ico” file as favicons. My website places them in a subfolder and provides <link> directives in the <head> of each page, although that’s just because the theme I use set it up that way2.

Conclusions

This is not the first time that I’ve tackled what was shaping up to be an annoying system problem only to realize R provides a great solution. Batch processing text files is another thing I’ve done, where at first I struggled with a bash/shell solution before implementing an R solution in minutes3. I’m always amazed at just how much you can do with R.


  1. There seems to be some debate about whether “.ico” is actually the right format to use for favicons nowadays. It worked for me and I don’t care enough to get to the bottom of it, so there you go.

  2. The canonical source supports using <link>.

  3. I am a lot more comfortable in R than I am on a ☆nix shell.

Brodie Gaslam Written by:

Brodie Gaslam is a hobbyist programmer based on the US East Coast.