R: image_read(gif) from magick produces a different number of frames to original gif created with gganimate

29 Views Asked by At

I've created maps of observations of several species over time and I want to place them side-by-side for comparison. I created the gifs using gganimate and wanted to use image_append() from magick to combine them. The problem arises when using image_read(): even though the gifs created by gganimate are 100 frames each and transition at the same frames, image_read() creates gifs with varying lengths. This means that when combined, the years aren't aligned. How can I standardize the output of image_read()?

This same question was asked in 2021 but was never answered. Hopefully including reprex will help potential answerers.

Sample code:

library(sf)
library(ggplot2)
library(gganimate)
library(transformr)
library(magick)

r <- data.frame(YEAR = c(1995:2022), 
                 TOTAL = c(runif(28, 0, 15)),
                 LONG = c(runif(28, -80, -78)),
                 LAT = c(runif(28, 38, 40)))

t <- data.frame(YEAR = c(1995:2022), 
                TOTAL = c(runif(28, 0, 20)),
                LONG = c(runif(28, -80, -78)),
                LAT = c(runif(28, 38, 40)))

r.map <- st_as_sf(r, coords = c("LONG", "LAT"), crs = 4326)
t.map <- st_as_sf(t, coords = c("LONG", "LAT"), crs = 4326)

r.map2 <- ggplot() +
  geom_sf(data = r.map, aes(size = TOTAL, alpha = ifelse(TOTAL == 0, 0, 1))) +
  guides(alpha = "none") +
  scale_alpha(range = c(0,1)) +
  transition_states(YEAR, transition_length = 0, state_length = 1) +
  ggtitle("{closest_state}") +
  shadow_mark(alpha = ifelse(r.map$TOTAL == 0, 0, 0.25))

t.map2 <- ggplot() +
  geom_sf(data = t.map, aes(size = TOTAL, alpha = ifelse(TOTAL == 0, 0, 1))) +
  guides(alpha = "none") +
  scale_alpha(range = c(0,1)) +
  transition_states(YEAR, transition_length = 0, state_length = 1) +
  ggtitle("{closest_state}") +
  shadow_mark(alpha = ifelse(t.map$TOTAL == 0, 0, 0.25))

r_gif <- animate(r.map2)
t_gif <- animate(t.map2)

Check the length of the gifs created by gganimate (this is an inelegant solution, there may be another way to do this):

length(frame_vars(r_gif)$frame)
> 100
length(frame_vars(t_gif)$frame)
> 100

Read into magick and check the lengths again:

r_mgif <- image_read(r_gif)
t_mgif <- image_read(t_gif)

length(r_mgif)
> 75
length(t_mgif)
> 66

This is my first time posting here so please let me know if my post is missing anything! Thank you for your help.

0

There are 0 best solutions below