<- function(png_dir, gif_path, ...) {
make_gif
<- inherits(png_dir, "character")
png_dir_is_char <- inherits(gif_path, "character")
gif_path_is_char
if (!png_dir_is_char | !gif_dir_exists) {
stop("png_dir and gif_path must be character class.", call. = FALSE)
}
<- dir.exists(png_dir)
png_dir_exists <- dir.exists(dirname(gif_path))
gif_dir_exists
if (!png_dir_exists | !gif_path_is_char) {
stop("png_dir and gif_path directories must exist.", call. = FALSE)
}
<- tools::file_ext(gif_path) == "gif"
path_is_gif
if (!path_is_gif) {
stop("gif_path must be a file path ending with .gif.", call. = FALSE)
}
<- list.files(
files path = png_folder,
pattern = ".png$|.PNG$",
full.names = TRUE
)
if (length(files) < 2) {
stop("You need two or more PNGs to make a gif.", call. = FALSE)
}
png("frame%03d.png")
par(ask = FALSE)
dev.off()
::gifski(png_files = files, gif_file = gif_path)
gifski
}
tl;dr
Use {gifski} to make gifs—real quickly!—using R.
Intergalactic pizza sloths
You and I both know that the world needs more gifs of sloths riding through space on a slice of pizza, for example.
Great news: ‘the fastest gif encoder in the universe’ has come to R via the {gifski} package built by Jeroen Ooms for rOpenSci. It’s built on Gifski package for Rust, hence the speed.
The obvious analytical application is for creating gifs from plots, as in the following example from the rOpenSci announcement, which shows life expectancy by GDP per capita with a different year for each frame of the gif.
But no-one can stop us having fun with it too.
Engifification proclamation
So I’ve made a quick function that takes a folder of PNGs and stitches them into a gif using the gifski::gifski()
function. I’ve called it make_gif()
because it… makes gifs. It’s not optimised because it’s just for fun, okay?
Basically, you must supply two things:
- A path to a folder containing the images (.png or .PNG only).
- A path for where the gif should be written (including the ‘.gif’ extension).
Optionally you can provide a third: use the dots (...
) to pass further arguments to gifski::gifski()
(see ?gifski
for details).
Note that you should make sure your PNGs are ordered alphabetically or numerically in the named directory so that they’re engiffed1 in the desired sequence. Don’t worry if your folder has other filetypes; make_gif()
only extracts PNGs.
Hexapod lilypad-frog evolution
I used the make_gif()
function to create the important gif at the top of this post, featuring the evolution chain of Lotad, the best and most special Pokémon.
make_gif(
png_folder = "~/Documents/pokemon/lotad/images", # folder of images
gif_path = "~/Desktop/lotad.gif" # path to save gif
)
Maybe you’ll find the function useful too. So get out there and get engiffing!2
Environment
Session info
Last rendered: 2023-08-08 22:14:03 BST
R version 4.3.1 (2023-06-16)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.2.1
Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
time zone: Europe/London
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] htmlwidgets_1.6.2 compiler_4.3.1 fastmap_1.1.1 cli_3.6.1
[5] tools_4.3.1 htmltools_0.5.5 rstudioapi_0.15.0 yaml_2.3.7
[9] rmarkdown_2.23 knitr_1.43.1 jsonlite_1.8.7 xfun_0.39
[13] digest_0.6.33 rlang_1.1.1 evaluate_0.21