# 一個 GIF 裡到底裝著什麼

GIF 是一疊長方形，每個都帶著一隻計時器和一張調色盤，而人們對這個格式的抱怨，幾乎都出自這三樣裡的某一樣。下面講每個部分各做什麼，以及怎麼弄清楚你的檔案把體積花在了哪一樣上。

[開啟GIF 分析](https://abox.tools/zh-TW/gif-analyzer/): 幀、延時、調色盤，以及每個位元組的去向。

最後更新 2026年8月26日

## 簡短的回答

一個 GIF 是一塊畫布、一串往上畫的長方形，外加一張調色盤，說明那些長方形裡的數字各代表什麼顏色。每個長方形帶著三樣東西：它該停留多久、之後該拿它怎麼辦，以及可有可無的一張自己的調色盤。

人們覺得這個格式奇怪的地方，幾乎都出自那串長方形。你的 GIF 大得離譜，要麼是那些長方形每次都是整塊畫布，要麼是裡面塞了三百張調色盤。它播得太慢，是因為延時低到了任何瀏覽器都不肯往下走的那條地板以下。它拖出尾巴，那是那個叫*處置*的欄位。

想知道某個具體檔案屬於哪一種，開啟 [GIF 分析](https://abox.tools/zh-TW/gif-analyzer/)把它拖進去。這一頁剩下的部分，講的是那些數字都是什麼意思。

![一個 GIF 的摘要卡片：版本、畫布尺寸、檔案大小、幀數、循環次數和用了多少種顏色。](https://abox.tools/screens/whats-inside-a-gif/facts.webp)

播放器從不告訴你的一切，全從一個檔案裡讀出來。

## 幀是長方形，不是畫

只見過 GIF 播出來的人，在這裡最容易吃驚。一幀並不是那一刻動畫的畫面。它是一個長方形，有自己的位置和自己的大小，畫在前面幾幀留下的東西之上。

那個長方形可以是整塊畫布，而在做得糟的檔案裡它每次都是。但 GIF 是允許只存下自上一幀起變過的那部分的——而在畫面大半不動的地方，這就是一個 12 MB 的檔案和一個 900 KB 的檔案之間的差別。一段幾乎靜止的視窗錄屏能做得很小，而同一段錄屏從一個馬虎的轉換器裡出來就不小，原因也在這裡。

光看動畫，你分不出自己手上是哪一種，兩者看起來一模一樣。唯一的辦法是看每一幀存了什麼，而分析器專為此備了一個檢視：把它切到*每幀實際存的東西*，你要麼看到透明底上一排小形狀，說明編碼器做了它該做的事；要麼一遍又一遍看到整張畫面，說明它沒做。

這個格式裡任何地方都沒有運動補償。不會有東西被存成「和上次一樣，只是往左挪了四個畫素」，影片編碼器才那麼做。變化區域這個招數是 GIF 僅有的一點省法，而它非常值錢。

## 延時，以及每個瀏覽器都強推的那條地板

每一幀都存著自己要停多久，單位是百分之一秒。這個格式只有這一種單位，所以一個檔案能要的最快是 0.01 秒——每秒一百幀——最長約 655 秒。

它不會得到每秒一百幀。**每個瀏覽器都把低於 0.02 秒的延時抬到 0.10。**這條規矩 1996 年寫進了 Netscape Navigator，為的是那個年代旋轉的地球儀和會動的「施工中」牌子，之後每個瀏覽器都照抄了下來。從來沒人刪掉它，也不會有人刪。

所以一個每幀都寫著 0.01 秒的 GIF，播出來是每秒十幀，不是一百幀。它比造它的那個程式打算的慢十倍，而檔案對此毫無提示：裡面的延時正是當初要求的值。這是這個格式裡最常見的意外，也是分析器要報兩個時長的原因——檔案說的那個，和瀏覽器真正會照辦的那個。

無論檔案是在哪裡造的，解法都是寫 0.02 而不是 0.01。那是每秒 50 幀，也是真正的上限，比任何用途需要的都快。實際上 0.05 秒——每秒二十幀——差不多就是值得去要的最快了。

延時還能告訴你另一件事。要是它們全都一樣，這個檔案是由一組固定幀率的幀做出來的。要是它們參差不齊——這裡 0.04，那裡 0.11——那是某個東西轉了一段影片、丟掉了一些幀，再把鄰居拉長去補上窟窿。而要是最後一幀比其餘的長得多，那是有意為之：讓動畫在循環回去之前停一下，就是這麼做的。

## 處置：決定它會不會拖尾巴的欄位

每一幀都寫明自己的時間到了之後，螢幕上該留下什麼。可能的答案有四個，值得知道，因為動畫看起來不對的四種方式裡，有三種就是這個欄位填錯了。

- **留在原地。**下一幀直接蓋上去。當各幀不透明且彼此完全遮住時，這是對的，而且最省，因為什麼都不用清。
- **清回背景。**這一幀的長方形在下一幀落下前被擦掉。透明就需要這個：沒有它，下一幀透出來的地方會露出前一幀，一組各自獨立的畫面就變成了一疊疊影。
- **還原下面原有的東西。**這一幀畫上去之前畫布上的樣子被放回來。一個小東西在靜止背景上移動，就是這麼存的——每一幀畫那個東西，然後背景回來，而寫進檔案的自始至終只有那個東西的長方形。
- **未指定。**檔案沒說。所有看圖程式都當成「留在原地」，通常沒錯，偶爾就是透明 GIF 拖出尾巴的原因。

有一處規範和現實分了家。「清回背景」指的是檔案頭裡寫著的那個背景色，而每個瀏覽器都無視它，改成清成透明。這樣已經二十五年了。一個指望那個背景色會出現的檔案，在做它的人、用做它的那個軟體看來是對的，在別處一律是錯的。

## 調色盤，以及它們要的 768 位元組

GIF 的一個畫素不是顏色。它是一個數字，指向一張最多 256 色的表，每種顏色佔三個位元組。所以一張滿的表是 768 位元組，而一個檔案可以讓所有幀共用一張，也可以一幀一張，或者兩者都有。

兩種安排都合法，只是換來的東西不同：

- **共用一張表**，整個檔案只花 768 位元組，而且顏色在幀與幀之間是穩的。GIF 的閃爍——從影片做出來的檔案上那種討厭的抖動——很多時候不過是調色盤在一幀一幀地跳。
- **每幀一張表**，讓每一幀都能用上共用表裡沒有的顏色，畫面整個換掉的時候這很要緊。代價是每次 768 位元組。一段 300 幀的動畫，那就是在存下第一個畫素之前，先花掉 230 KB 的調色盤。

還有一筆更安靜的開銷。調色盤的長度必須是 2 的冪，所以用九種顏色的幀照樣拿到十六格的表，用 130 種的照樣拿到 256 格。一定程度的往上湊是躲不掉的。但要是一個檔案的表裡宣告瞭五千種它的畫素從沒引用過的顏色，那就是另一回事了：那是為另一張畫配的調色盤，而最終進到幀裡的並不是那張畫。分析器會把沒用上的格子標出來，讓這個形狀一眼可見。

## 位元組實際去了哪裡

GIF 的每個位元組都落在為數不多的幾個地方，在斷定一個檔案太大之前，值得知道這幾個地方是什麼。

- **壓縮過的畫素。**健康的檔案裡，幾乎全是它。畫面本身，過了一遍 LZW——1984 年的一種壓縮方案，當初是為電子表格的截圖設計的，所以它在大片純色上表現好，在照片上表現差。
- **調色盤。**如上，一張滿表 768 位元組。
- **每幀的頭。**每一幀八個位元組的時間資訊加十一個位元組的描述符。正常檔案裡不算什麼；兩千個極小幀的動畫裡，是 38 KB。
- **分塊的外殼。**壓縮資料被切成最多 255 位元組一段，每段前面放一個長度位元組。大約每 256 個位元組裡有一個，躲不掉，值得看一眼，因為除此之外它完全看不見。
- **後設資料。**註釋、色彩配置檔案和 XMP 包。真正荒唐的結果就出在這一項：一個影像編輯器可能留下 40 KB 的 XML，描述的是幾年前做過的一次修改，而在一個小 GIF 上那就是檔案的大半。沒有任何看圖程式會把它畫出來。

要看這張表而不是猜，是因為答案因檔案而異，而解法直接從答案裡長出來。一個 95 % 都是壓縮畫素的檔案，就是畫面本身多，只有減幀、縮小尺寸或者減顏色才有用。一個 30 % 是調色盤、或者 40 % 是 XMP 的檔案，問題便宜得多。

![一條按位元組去向拆解 GIF 的條形圖，每一幀一行，給出各自的大小和在檔案中的佔比。](https://abox.tools/screens/whats-inside-a-gif/budget.webp)

位元組到底去了哪裡，一幀一幀地看。太大的 GIF 幾乎總是因為一個看了這張圖就明白的原因才大的。

## 循環並不屬於這個格式

GIF 規範裡沒有任何欄位說動畫會重複。循環來自 Netscape 在 1995 年發明的一個塊——一個裡面寫著 `NETSCAPE2.0` 的「應用程式擴充區塊」——所有人還是都實現了它，如今網際網路上每一個動圖 GIF 裡都有它。

這也意味著，沒有這個塊的檔案在每個瀏覽器裡都是恰好播一遍就停，在做它的人看來像是壞了。要是一段動畫只走一遍，就是這個塊不見了；這是最值得先查的幾件事之一，而且在任何看圖程式裡都看不見。

這個塊也能寫一個次數——播五遍然後停。零表示永遠，而幾乎所有檔案寫的都是零。

## GIF 還能捎帶的別的東西

有三種塊不裝畫面，而且所有看圖程式都跳過：

- **註釋。**自由文字，通常是寫這個檔案的軟體的名字，偶爾是作者本來不會選擇公開的東西。沒有東西會顯示它，而這個檔案的每一份複製都帶著它。
- **XMP。**Adobe 的 XML 後設資料：什麼改過這個檔案、什麼時候改的，有時還有誰改的。它末尾拖著 258 位元組的魔法尾巴，那是為了讓塊長度算得過去的把戲，也是為什麼老老實實去讀會讀出滿屏二進位。
- **純文字。**1989 年規範裡的一個塊，要求看圖程式按格子在畫面上寫字。從來沒有任何東西實現過它。檔案裡要是有一個，它寫的內容不會出現。

這三樣在把檔案發出去之前都值得知道：它們是一個 GIF 裡可能透露你的部分，而且除非有東西專門把它們剝掉，否則每一次複製、每一次重新上傳，它們都活著。

## 讀一個損壞的檔案

GIF 會被截斷——中途停掉的下載、從快壞的硬碟上救回來的檔案、某個程式只寫了一半的東西。因為這個格式是一串塊，而不是一整個帶索引的結構，被截斷的 GIF 通常仍然能讀到它斷掉的那一點為止：斷口之前的每一幀都是完整無損的。

這值得知道，因為大多數軟體會乾脆拒收這個檔案。一個儘量往下讀、並且告訴你在哪裡停住的分析器，至少能讓你知道有多少活了下來，以及丟掉的是一幀還是最後兩百幀。

反過來的毛病也存在：坐在檔案結束標記*之後*的那些位元組。每個解碼器都在那個標記處停下，所以它們從不會被讀到、也不會被畫出來，而它們通常是某次出錯時被接在第一個檔案後面的第二個檔案。它們是純粹的重量，切掉不損失任何東西。

## 這些都不需要上傳

讀一個 GIF 的結構不是什麼費勁的工作——走一遍塊的清單，再加一個小小的解壓器——而且從來沒有任何技術上的理由，非要把檔案送到伺服器上去做它。這裡的 [GIF 分析](https://abox.tools/zh-TW/gif-analyzer/)把整件事都放在頁面裡做完：走塊、LZW、畫到螢幕上的幀，還有那份位元組帳。

這件事在這裡比在多數工作上更要緊，因為人們最想拆開看的檔案，往往正是他們最拿不準要不要拿出去的那些——救回來的東西、別人發來的東西、裡面有一段自己還沒讀過的註釋的東西。[關於上傳檔案的那篇更長的說理](https://abox.tools/zh-TW/guides/is-it-safe-to-upload-files/)，在這裡和在本站任何地方一樣成立。
