簡介
GIF的全稱是Graphics Interchange Format,可譯為圖形交換格式,用于以超文本标志語言(Hypertext Markup Language)方式顯示索引彩色圖像,在網際網路和其他線上服務系統上得到廣泛應用。GIF雖然是一個古老的檔案格式,但是随着移動網際網路的發展,在手機社交應用中因表情包和動圖的火爆而重新大範圍的進入公衆視野, 重新流行起來。
版本
GIF具有GIF87a和GIF89a兩個版本。
GIF87a版本是1987年推出的,一個檔案存儲一個圖像,嚴格不支援透明像素;GIF87a采用LZW壓縮算法,它能夠在保持圖像品質的前提下将圖像尺寸壓縮百分之二十到二十五。
GIF89a版本是1989年推出的很有特色的版本,該版本允許一個檔案存儲多個圖像,可實作動畫功能,允許某些像素透明。在這個版本中,為GIF文檔擴充了圖形控制區塊、備注、說明、應用程式程式設計接口4個區塊,并提供了對透明色和多幀動畫的支援。
檔案格式詳解
一個典型的GIF檔案,由以下内容構成:
- Q:這是什麼檔案?A:GIF (Header)
- Q:顯示它需要多大的區域?A:寬xxx,高xxx(LSD)
- Q:顯示它需要準備哪些色彩?A:色表(LSD、GCT、ID、LCT)
- Q:某一幀的内容是什麼樣的?A:LZW壓縮後的像素清單
- Q:如何繪制?A:位置、尺寸、透明色、隔行掃描(GCE、ID)
- Q:繪制完一幀後還要做什麼?A:Disposal Method(GCE)
- Q:開始繪制下一幀前等待多久?A:0.01秒的倍數(GCE)
- Q:循環播放幾次?A:無限,或者1~65535次(NETSCAPE2.0)

Header
前三個位元組叫做“檔案簽名”,固定為'G' 'I' 'F'
後三個位元組标記GIF規範的版本,有"89a"和"87a"兩種
Logical Screen Descriptor(LSD)
包含以下資訊:
- 整個檔案的尺寸
- 是否有全局色表
- 全局色表的顔色分辨率
- 色表是否經過了排序
- 全局色表中顔色的數量
- 哪種顔色被視為背景色
- 像素的長寬比
淺談動圖檔案格式 - GIF
色表
很多古老的顯示裝置并不能直接展示RGB資料, 由于硬體的限制,裝置會預先将一些顔色加載到内部寄存器中, 每種顔色對應一個編号,傳輸圖像時,不必傳輸每一個像素的顔色,而隻需要傳輸每一個像素的顔色編号。
假定色表中最多含有256項
我們需要利用一些算法,提取出最能代表一張圖檔的256種顔色,配合抖動算法,讓色表繪制出的圖檔盡量接近原圖
原圖色彩資訊太豐富,會導緻難以還原,這就是為什麼我們很多時候看到的GIF圖檔,看起來像是資訊缺失或失真的原因。
色表資訊 - 顔色分辨率
顔色分辨率表示原圖中一個色彩通道的位數,例如,對于RGB444格式的原圖,顔色分辨率為4,RGB888格式的原圖,顔色分辨率為8。
LSD中,顔色分辨率用3位表示,将這個值+1可以得到實際的顔色分辨率數值, 例如,011代表顔色分辨率為4,111代表顔色分辨率為8
色表資訊 - 色表大小
色表大小表示色表中含有的項目數量,用3位表示,記為n,則實際的項目數量為2(n+1),例如,010代表8,100代表32, 111代表色表大小的上限,即256
色表的格式
每一項含有RGB三個通道的值, 按照編号順序排列
全局色表與本地色表
除了GCT之外,每一幀還可以有自己的色表, 本地色表存在時,忽略全局色表
Image Descriptor
描述如何繪制一幀圖檔, 一幀不需要占滿整張圖檔, 圖檔可能是隔行掃描的
Graphics Control Extension(GCE)
Graphics Control Extension(GCE)是在GIF89a中加入的,屬于可選内容,它含有一些動畫相關的屬性(包括透明色)
LZW(Lempel–Ziv–Welch)編碼
LZW(Lempel–Ziv–Welch)編碼由Abraham Lempel、Jacob Ziv和Terry Welch發明, 用于資訊的無損壓縮,它于1984年被提出,用固定長度的碼,表示不同長度的字元串。
GIF中的壓縮算法采用的是該LZW的一個變體。
LZW中,字典是不固定的,開始編解碼前,會有一個初始字典,編解碼時,随着資料的增多,字典也在不斷擴充,讀入的每一個此前未見過的新字元串,都會被加入到字典中
如編碼過程:
- 字元串:aabcaac
- 初始字典:#1->a,#2->b,#3->c
- 見到aa,是我們沒見過的字元串,在字典中增加#4->aa,輸出1
- 見到ab,在字典中增加#5->ab,輸出1
- 見到bc,增加#6->bc,輸出2
- 見到ca,增加#7->ca,輸出3;見到aac,增加#8->aac,輸出4
- 最後見到c,輸出3
- 得到112343
- 它對應的解碼過程如下:
- LZW串:112343
- 見到11,輸出aa,并在字典中增加#4->aa
- 見到23,輸出bc,增加#5->ab和#6->bc
- 見到43,輸出aac,增加#7->ca和#8->aac
- 得到aabcaac
在GIF中,圖像資料的内容是每個像素的顔色編号串,初始字典就是顔色編号對應同值的字典編号,另外加入兩個碼:Clear Code和End Of Information Code
以4色圖檔為例,初始字典為:#1->1,#2->2,#3->3,#4->4,#5->Clear Code(遇到此Code時,清空字典重新開始
),#6->EOI code(圖檔結束)
圖像資料如下圖所示,開頭是初始字典(除去特殊Code)的位數,接着是資料塊的位元組數,接着是LZW資料塊,以00結尾:
Disposal method
繪制完一幀之後,如何處理
0:未定義(可以清空)
1:不處理
2:在本幀繪制的區域填上背景色
3:将本幀繪制的區域還原到繪制之前的狀态
GIF檔案格式的優劣
GIF是一個古老但流行的檔案格式,這就概況了GIF這個檔案格式的優劣,其優勢在于推出時間早,廣泛流行,幾乎所有的作業系統和浏覽器都有對GIF的很好的支援,基于浏覽器對于該檔案格式的解釋,GIF具備加載即播放,同屏多點傳播放等特性,這些都是與同類動态畫面的檔案(如短視訊)所不一緻的。而其缺陷在于它的資訊承載比很低,同等檔案尺寸下分辨率低,畫面品質差,還原度差。
現在有很多網際網路公司都在推出新的動圖格式如GIFV等,但一個新的格式需要将編解碼工作都完成,這就需要既提供檔案格式,又需要提供解碼環境,雖然已經有一些公司在自己的SDK裡面封裝了新的動圖格式,但這離成為行業标準還有一定距離。
本文作者:
李霄,陳敏