abox.tools

語言: 繁體中文

怎麼把 GIF 拆成一幀一幀

把幀取出來,只要一次拖放加一個按鈕。真正值得弄明白的,是 GIF 裡的一「幀」到底是什麼,因為這個格式存下來的東西和你看見的相當不一樣——你的第十四幀之所以是一個裝著誰的嘴的長方形,就差在這裡。

開啟GIF 拆幀 每一幀都單獨存成一張 PNG。

以 Markdown 檢視

簡短的回答

開啟 GIF 拆幀,把 GIF 拖進去,每一幀都會變成一張可以下載的 PNG——一張一張下,或者打成一個 ZIP 一起下。設定不用動,你拿到的正是大多數人想要的那個:每一幀都是完整的畫面,就是它在動畫那一刻的樣子。

這一頁剩下的部分,講的是隨後最讓人意外的三件事:某一幀只是一小塊、透明換個地方就變黑,還有時間——幀一旦成了各自獨立的檔案,它就不存在了。

GIF 的一幀到底是什麼

GIF 不是一疊畫。它是一張畫,後面跟著一串補丁。

第一幀之後的每一幀,只存那塊變過的長方形,外加一條規矩,說明畫布接下來該怎麼處理。螢幕上其餘的一切,不過是前面幾幀留在那裡的東西。一個人站在不動的牆前說話,每幀的代價就是一塊臉那麼大的長方形,而不是一整張畫;一個既沒有運動補償、也沒有有損環節的格式還不至於完全沒法用,全靠這個。

所以「把第 14 幀給我」有兩個不同、卻同樣誠實的答案,這個工具兩個都給:

它看上去的樣子。那一刻的完整畫面:第 14 幀畫在它之前的一切之上。這是預設,做聯絡表、縮圖、要發出去的靜幀,或者要送進剪輯軟體的幀,要的都是這個。

只有這一幀自己存著的畫素。補丁本身,按它自己的大小、自己的位置出來,它沒帶的地方一律留成透明。第 14 幀可能就是 ⁦60 × 40⁩ 畫素的一張嘴。這個檢視解釋了一個 GIF 的位元組都花到哪裡去了;你要是在改這段動畫、而不是從裡面收割圖片,要的就是它。

存下來的幀看起來像個碎片,並不說明你的檔案有毛病。那就是這個檔案。

一段動畫的十二個編號幀,每一幀都是完整畫面,並標著停留時間。
每一幀都是完整畫面,而檔案裡裝的並不是這樣:這一節講的正是這個差別。

處置規則,以及為什麼有些幀會留下窟窿

每一幀還帶著四條指令中的一條,說明在下一幀畫上去之前,它那塊長方形該怎麼辦。在「存著什麼」這個檢視裡,工具會把它寫在每一幀下面:

留在螢幕上。最常見的一種。補丁待在落下的地方,下一幀蓋上去。

之後清掉自己那塊。下一幀落下之前,那塊長方形先被擦乾淨。帶著移動的透明物體的動畫就是這麼做的,而這也是 GIF 閃爍的經典原因。

還原它底下原來的東西。畫布回到這一幀畫上去之前的樣子——蓋一個章,再撤銷。少見,也是自制的 GIF 讀取程式最常做錯的一條。

要是你打算比較幾個工具,有個細節值得知道:規範說「清掉自己那塊」應當還原成背景色,但 1990 年代以來的每一個瀏覽器都改成清成透明,因為那個年代的動畫就是這麼設想的。這裡的工具是有意跟著瀏覽器走的,好讓你拿到的幀就是你看見過的幀。

設定卡片:在看到的那一幀與檔案裡存著的原始補片之間做選擇,另有一個給透明部分墊底的背景色。
看到的那一幀這一檔,會把處置規則重放一遍,交給你的是畫面。另一檔交給你的是檔案裡真正存著的東西,連窟窿一起。

透明會怎麼樣

GIF 的透明只有一位。一個畫素要麼塗了,要麼看不見,中間什麼都沒有——沒有柔和的邊,也沒有半透的影子。背景透明的 GIF 邊緣總是硬硬的、還有點毛刺,就是這個道理。

PNG 能把這一點原樣、無損地存下來,所以幀出來時透明是完整的,也不會憑空多出什麼。要是這些幀接下來去的地方懂透明,那就留著。

要是不懂,就拿一個顏色填上。忽略 alpha 通道的軟體通常會把那裡畫成黑的,於是在瀏覽器裡好端端的一幀,到了那邊就帶著黑底——而一塊幾乎處處透明的儲存補丁,到那邊就成了一個裝著嘴的黑長方形。事先選好顏色就是解法。它會寫進 PNG,之後撤不回來,這也是它沒被設成預設的唯一理由。

幀帶不走的那些時間

PNG 裡沒有地方記它在螢幕上待了多久。把動畫拆成 PNG,時間就沒了,而你一想把它拼回去,這件事立刻就要緊起來。

ZIP 裡的 frames.txt 就是為此而在。它列出每一幀的延時、位置和大小,所以這段動畫可以在 GIF 製作裡、或者別的地方重新搭起來。它只花幾 KB,而且事後沒有任何辦法把它推算回來。

關於 GIF 的延時,有兩件事人人都會栽進去:

單位是百分之一秒,所以這個格式能有的最細的一檔是 0.01 秒。世上沒有正好 30 fps 的 GIF:每幀 0.03 秒是 33.3 fps,0.04 秒是 25。

低於 0.02 秒的一律按 0.10 秒播。瀏覽器從 1990 年代起就這麼封著——一條為那個年代的旋轉地球儀寫下、之後再沒刪掉的規矩。檔案裡寫著每幀 0.01 秒的 GIF,聲稱自己是 100 fps,實際按 10 播。這裡的工具顯示的是真正播出來的延時,兩者對不上時,還會把檔案裡存的值寫在旁邊,因為正是這個落差,讓一個拆開又拼回去的 GIF 可能比原來慢。

幀的編號,以及為什麼要補零

幀出來的名字是 name-001.png、name-002.png,從一開始數,並補零補到最後那個數字的寬度。這不是裝飾:在任何檔案管理器裡,在大多數匯入序列的軟體裡,frame9.png 都排在 frame10.png 後面,因為它們排的是文字,不是數。補過零的名字到哪裡都排得對,而每一個能匯入圖片序列的剪輯軟體也都指望它是這樣。

用「每兩幀留一幀」把長動畫抽稀,不會重新編號。第 42 幀還叫第 42 幀,所以這些檔案既對得上原片,也對得上那份時間清單。

為什麼這件事不需要伺服器

讀一個 GIF 是兩件事:走一遍檔案裡的那些塊,再把包著它畫素的 LZW 壓縮解開。兩件加起來幾百行,在儲存庫裡原樣寫著,而且跑在你自己的機器上——網線拔了這一頁照樣能用,原因就在這裡。

你的瀏覽器早就會放 GIF,只是它不肯把零件交出來:<img> 給你一段動畫,把它畫到畫布上永遠只給你第一幀,而唯一能多做一點的那個介面,Safari 沒有。所以這裡乾脆自己把這個格式讀一遍,在每個瀏覽器裡都是同一套做法——而正因為是自己讀的,才談得上把補丁和處置規則擺給你看。

把檔案傳給線上轉換器安全嗎?那一頁列了四條檢查,它們會告訴你關於任何工具的同一件事,也包括這一個。