Days 20-21: Cat GIFs. Irises. Magick
by Danielle Navarro, 17 May 2018
Right. So I was working on a post talking about my efforts to learn more about non-standard evaluations, expressions, scoping rules and other scary things about R that I don’t really understand as well as I should (I’ve been reading this for some reason) but then the awesome Lisa Williams tweeted this:
@williamslisaphd) May 16, 2018
@jinxgoh) May 12, 2018
… so naturally now I MUST LEARN THIS SORCERY.
Clicking through the links leads me to this post from Daniel Hadley. I’ve never used the
magick package before, but I think I’ve incidentally interacted with it while trying to work out animations and some other image processing things? Anyway, I set myself a simple task.
In real life cats and irises don’t get along but I don’t care. I want to add a cat gif to a plot of the famous
iris data, so that’s my task. Turns out to be surprisingly painless!
First, I load packages, draw a simple ggplot image, and save it as
library(ggplot2) library(magick) ggplot(iris, aes(x=Petal.Width, y=Sepal.Width, colour = Species)) + geom_point() + theme_bw() + ggsave(filename ="iris.png", width = 5, height = 4, dpi = 300)
Next, I find a cat gif. Looking at the Daniel Hadley post suggests what I need to do next is read the iris pic in along with the cat gif…
irispic <- image_read("iris.png") catgif <- image_read("1V7a.gif")
From what I understand from skimming the vignette, we aren’t literally loading anything into R here. The
magick package is just a wrapper to the Magick++ library, and all the processing is being done outside of R
Anyway from here it’s surprisingly straightforward. The
image_composite function allows you to compose two images together in a variety of different ways. What’s nice is that it operates on vectorised input. The
irispic image is just one image but
catgif is an animated gif with 58 frames…
format width height colorspace matte filesize density 1 GIF 500 282 sRGB TRUE 565642 72x72 2 GIF 500 282 sRGB TRUE 565642 72x72 3 GIF 500 282 sRGB TRUE 565642 72x72 4 GIF 500 282 sRGB TRUE 565642 72x72 5 GIF 500 282 sRGB TRUE 565642 72x72 6 GIF 500 282 sRGB TRUE 565642 72x72
… so if I feed in
irispic as the background image and
catgif as the composite image, and it will overlay each frame of the cat gif onto the iris picture background.
Because the irispic image is bigger I specify an
offset to move the cat where we want it:
frames <- image_composite(irispic, catgif, offset = "+70+800")
Finally, stitch the frames together as an animation, and write it to a new gif…
animation <- image_animate(frames, fps = 10) image_write(animation, "iriscat.gif")
The last step takes ages, which I think is happening because magick is lazy? If I’ve understood this right, it doesn’t actually do anything until it really needs to, so it’s only at the time I tell it to write something that it starts processing?? I should probably read the docs.