Basic manipulation of GIF frames with magick
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
The magick
package is a really powerful package for image processing in R. The official vignette is a great place to start learning how to use the package.
I’ve been playing around with using magick
for manipulating GIFs and found some tips and tricks that don’t seem to be documented anywhere. Since the NBA restart is upon us, I’ll illustrate these tips with a GIF featuring one of the greatest of all time:
library(magick) img_path <- paste0("https://media3.giphy.com/media/3o72F9VC4WjFDCPTag/", "giphy.gif?cid=ecf05e470ceb6cd8542e8c243d0e0a2282c3390e5c", "72fd17&rid=giphy.gif") img <- magick::image_read(img_path) img
If you print img
, you will see that the GIF is represented as a tibble, with each row representing a single frame in the GIF:
print(img) # # A tibble: 44 x 7 # format width height colorspace matte filesize density # <chr> <int> <int> <chr> <lgl> <int> <chr> # 1 GIF 480 266 sRGB TRUE 2617620 72x72 # 2 GIF 480 266 sRGB TRUE 2617620 72x72 # 3 GIF 480 266 sRGB TRUE 2617620 72x72 # 4 GIF 480 266 sRGB TRUE 2617620 72x72 # 5 GIF 480 266 sRGB TRUE 2617620 72x72 # 6 GIF 480 266 sRGB TRUE 2617620 72x72 # 7 GIF 480 266 sRGB TRUE 2617620 72x72 # 8 GIF 480 266 sRGB TRUE 2617620 72x72 # 9 GIF 480 266 sRGB TRUE 2617620 72x72 # 10 GIF 480 266 sRGB TRUE 2617620 72x72 # # … with 34 more rows
Use the length()
function to determine how many frames there are in the GIF:
length(img) # [1] 44
You can index GIFs as you would with a vector. For example, img[12]
returns the 12th frame of the GIF:
You can, of course, put more than one frame index in the square brackets. For example, img[44:1]
will run the GIF in reverse (this can also be achieved with rev(img)
):
This is a little more elaborate:
img[c(1:44, rep(c(rep(44, times = 5), 43:30, rep(30, times = 5), 31:43), times = 2))]
Slowing down the dunk action:
img[c(1:30, rep(31:44, each = 3))]
We can replace a single frame with a different image too:
logo <- image_read("https://jeroen.github.io/images/Rlogo.png") %>% image_resize("480x266!") img[25] <- logo img
I don’t know if there is a clean way to insert the R logo as the 25th frame and push the original 25-44th frames down one frame (that would be a neat functionality to have). The below is a workaround but it feels inelegant:
img <- img[c(1:25, 25:44)] img[25] <- logo
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.