Skip to content
All writing Part 05 of 07 · Crop, Resize, Fill: Image Processing
Engineering · 2 min read

libvips Stores an Animation as One Tall Stacked Strip

libvips stores a multi-frame image not as N frames but as one tall page-strip — every frame stacked vertically, with page-height, n-pages, and delay in metadata.

When libvips handles any multi-frame image (animated GIF or WebP, multi-page TIFF or PDF), it doesn’t store N separate frames. It stacks every frame vertically into one tall image, officially a page-strip. I picture an unrolled toilet roll.

  • The structure lives in metadata: page-height (one frame’s height), n-pages (frame count), delay (ms per frame). The invariant is n-pages × page-height = total height.
  • So imageRef.Height() returns the strip height (every frame combined), and Pages() > 1 is the flag that you’re holding a strip, not a still.

I originally guessed these frames were different sizes. The opposite is true: every frame is identical in size, which is exactly why libvips can stack them neatly. To detect an animation, I just check Pages() > 1.

Frame order in the strip

Frames stack top-down in playback order: frame 0 at the top (y = 0), each next frame directly below. Unrolling the toilet roll top to bottom gives you frames 0 through 4, not the reverse.

one *vips.ImageRef — Height() = 5 × page-height (ph) frame 0 frame 1 frame 2 frame 3 frame 4 top ← playback starts bottom ← last frame y = 0 y = 5·ph = Height() Pages() = 5 · PageHeight() = ph · Pages() > 1 ⇒ a strip, not a still
frame i lives at top = i × page-height — that's how you crop one out.

To extract frame i, crop at y = i × page-height: frame 0 at y=0, frame 4 at y=4·ph. That also proves it’s top-down, not bottom-up.

To libvips, an animation is one tall image, not a pile of frames.


References:

Related: This is what makes one load path for stills and animation and uniform vs positional transforms on a stitched strip work — or go back to the crop, resize, fill overview.

Tags #image-processing #libvips
// connect

Be brave | Be wise | Be grateful

21 BreakinCode

// elsewhere
LinkedInMedium (lang: en)Life RecordYoutube
wh:~$William Hung· © 2026 Taipei · GMT+8 · Available for collaboration