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.

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