简介
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)
包含以下信息:
- 整个文件的尺寸
- 是否有全局色表
- 全局色表的颜色分辨率
- 色表是否经过了排序
- 全局色表中颜色的数量
- 哪种颜色被视为背景色
- 像素的长宽比
色表
很多古老的显示设备并不能直接展示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
- 初始字典:#1->a,#2->b,#3->c
- 见到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里面封装了新的动图格式,但这离成为行业标准还有一定距离。
本文作者:
李霄,陈敏