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:
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
the Jeroen Ooms
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:
Linking to ImageMagick 22.214.171.124 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
 "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)
 "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
imgs <- image_read(files)
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
open ~/Downloads/moon/favicon.ico confirms that indeed the “.ico”
file contains all the 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.
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.
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.↩
I am a lot more comfortable in R than I am on a ☆nix shell.↩