Engineering · 1 min read
均勻變換 vs 定位變換:在拼接長條上的差別
一個變換能不能直接對整條 libvips page-strip 做,只看一個問題:它在乎座標嗎?均勻變換整條做安全,定位變換必須逐格處理。
一張 GIF 在 libvips 裡是一條「上下疊起來的長條」(page-strip):5 格 × 100px = 一張 500px 的圖。一個變換能不能直接對這條長條做,取決於一個問題:它在乎像素在哪裡嗎?
- 均勻(uniform) = 每個像素同一套規則、跟位置無關 → resize/scale。縮整條,每格一起縮、邊界對齊,還是一段合法動畫,它根本不用知道有影格這回事。
- 定位(positional) = 針對特定座標或區域下手 → crop、fill/pad。在長條上那個座標指到的是「一疊影格」,不是「每格的同一個位置」,一個天真的框切下去就跨過影格邊界,變成垃圾。
定位操作的修法: 用 [n=-1] 載入、依 page-height 把長條拆成每一格、每格套一模一樣的操作、vips_arrayjoin(across=1) 接回去,最後把 page-height、n-pages、delay 補回去。
判斷口訣: 對整張一視同仁地縮放、改色 → 均勻 → 整條做沒問題;針對座標或區域 → 定位 → 乖乖逐格處理。我手上的服務就是這樣分:純 resize 對整條長條跑,crop 跟 fill 逐格跑。
跟語言無關: vips_* 是 libvips 的 C API 名字,但這條幾何規則在任何 binding(govips、pyvips、sharp)都成立,換語言也不會變。
會不會看座標,決定了你能整條做、還是得逐格做。
參考來源:
- https://www.libvips.org/API/current/multipage-and-animated-images.html
- https://github.com/libvips/libvips/issues/2668
Related: 這一篇收束了libvips 把動圖存成一條上下疊起來的長條與一條載入路徑,同時吃靜圖與動圖,或回到裁切、縮放、填滿的四堂課總覽。