Skip to content
All writing Part 06 of 07 · 裁切、縮放、填滿:圖片處理
Engineering · 1 min read

一條載入路徑,同時吃靜圖與動圖

給 libvips loader 一個 n=-1,一條無條件路徑就能同時吃靜圖與動圖——因為預設的 n=1 只會默默解出第一格,把動畫悄悄丟掉。

載入時給 libvips 的 loader 一個 n=-1,一條無條件的路徑就能吃下所有輸入,不用嗅格式,也不用分幾頁的分支。

importParams := vips.NewImportParams()
importParams.NumPages.Set(-1) // -1 = load ALL pages/frames
image, err := vips.LoadImageFromBuffer(imageBytes, importParams)

NumPages 對到 loader 的 n-1 的意思是「有幾頁就讀幾頁」:

  • 動圖 GIF(5 格) → 疊成 5 頁 → Pages() == 5
  • 單張圖(JPEG/PNG/靜態 GIF) → 剛好 1 頁 → Pages() == 1PageHeight() == Height()。這裡的 -1 是不折不扣的 no-op,不會回「0 格」、也不會出錯。

所以「單張還是多張」是載入之後Pages()PageHeight() 判斷的,不在載入那一行決定。-1 也跟格式無關,animated WebP/AVIF、multi-page TIFF/PDF 全走同一條路,就算註解寫「for GIFs」也一樣。

那個坑:預設 n=1 會默默丟掉動畫

loader 的 n 預設是 1,所以一張 GIF 只會載第 0 頁。其餘影格連解碼都沒有,動畫被安靜地丟掉,你拿到的是第一格的靜圖:

5 格的 GIF 5 格疊起來 載入 n = 1 frame 0 — 保留 frame 1–4 被丟掉 沒有例外 · 沒有警告 Pages() = 1 → 被當成一張靜圖 · 動畫掉了
預設 n = 1 只解第 0 頁——解法是用 n = -1 載入。

沒有例外、沒有警告,失敗方式就是「動畫悄悄不見」,這正是為什麼那個 -1 要緊。

預設值不是中性的:沒讀到的影格,它不會吭一聲就丟掉。


參考來源:

Related: 這一步接續libvips 把動圖存成一條上下疊起來的長條,也接到均勻變換 vs 定位變換:在拼接長條上的差別,或回到裁切、縮放、填滿的四堂課總覽

Tags #image-processing #libvips #go
// connect

Be brave | Be wise | Be grateful

21 BreakinCode

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