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

Uniform vs Positional Transforms on a Stitched Strip

Whether a transform can run on a whole libvips page-strip comes down to one question: does it look at coordinates? Uniform ops are safe, positional ops go frame by frame.

A GIF in libvips is one tall stacked strip (a page-strip): 5 frames of 100px make one 500px image. Whether a transform can run on that strip comes down to one question: does it care where a pixel is?

  • Uniform means the same rule for every pixel, position independent, like resize/scale. Shrink the whole strip and every frame shrinks equally, boundaries stay aligned, and the animation survives. It never has to know frames exist.
  • Positional means it acts on a specific coordinate or region, like crop and fill/pad. On a strip, that coordinate points into the pile of frames, not “the same spot in each frame.” So a naive box slices across frame boundaries and produces garbage.
UNIFORM · resize — safe f0 f1 f2 f3 f4 every frame scales together → animation survives POSITIONAL · crop — broken f0 crop box crosses a boundary → frames 1–4 vanish = garbage
Does it look at coordinates? No → uniform, run on the whole strip. Yes → positional, go frame by frame.

Fix for positional ops: load with [n=-1], split the strip by page-height, apply the operation identically to each frame, vips_arrayjoin(across=1), then reset page-height, n-pages, and delay.

Rule of thumb: scales or recolors everything the same → uniform → safe on the whole strip. Targets a coordinate or region → positional → go frame by frame. The service I worked on splits exactly this way: a bare resize runs on the whole strip, while crop and fill run per frame.

Not language-specific: the vips_* names are the libvips C API, but the geometry rule holds in any binding (govips, pyvips, sharp). It survives a rewrite off the host language.

Whether it looks at coordinates decides if you can run on the whole strip or must go frame by frame.


References:

Related: This closes the loop from how libvips stores an animation as one tall stacked strip and one load path for stills and animation, or go back to the crop, resize, fill overview.

↑↓ navigate ↵ open esc close