GIF 格式
Graphics Interchange Format
块结构
GIF 属于那种活得远远超出预期的格式。它由 CompuServe 在 1987 年推出, 今天依然随处可见,主要靠的就是对动画的支持。
和现代格式相比,它基于块的结构简单得让人舒服:一个文件头、几个描述符、 一张色表、你的图像数据,最后一个单字节的结束符说一句“完”。
GIF 文件结构
GIF 文件头
| Offset | Hex | ASCII | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 | 4749463839618002E001F70000 | GIF89a....... | ||||||||||||
两个版本的差别
最初的规范,没有扩展块。
加入了扩展块、动画和透明度。
扩展块
GIF89a(1989 年的修订版)加入了扩展块,GIF 也正是靠它才有了动画。 所有扩展块都以 0x21 开头,后面跟一个类型字节, 扫文件的时候很好认。其中有些我们要留(动画时序),有些要删(注释)。
图形控制扩展(0xF9)
控制动画时序、透明度和处置方式,在动画 GIF 里位于每个图像描述符之前。 永远保留。
注释扩展(0xFE)
纯文本注释,里面什么都可能有:作者、创建日期、软件,或者私人备注。 会被 PicScrub 清除。
应用扩展(0xFF)
应用自定义的数据。最重要的是控制动画循环的 NETSCAPE2.0, 这里也可能藏着 XMP 元数据。
纯文本扩展(0x01)
几乎没人用。它会用 GIF 的色表来渲染文字,现代软件基本都直接忽略。
应用扩展详解
NETSCAPE2.0:动画循环
控制动画 GIF 循环播放多少次,取值为 0 表示无限循环。
| Offset | Hex | ASCII | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0000 | 21FF0B4E45545343415045322E300301000000 | !..NETSCAPE2.0..... | ||||||||||||||||||
PicScrub 会保留 NETSCAPE2.0,好让动画照常播放。
XMP Data:Extensible Metadata Platform
应用标识符:XMP DataXMP。里面是完整的 XMP/RDF 元数据,XML 格式。
PicScrub 会清除 XMP 应用扩展。
保住动画
GIF 麻烦的地方在于要分清动画数据(必须留)和元数据(想删掉), 而它们都住在扩展块里,所以不能一刀切地把扩展块全删了。
为动画保留
- • NETSCAPE2.0 循环次数
- • 图形控制扩展
- • 每帧的延迟
- • 处置方式
- • 透明色索引
- • 局部色表
会清除
- • 注释扩展
- • XMP 应用块
- • 无法识别的应用块
- • 纯文本扩展
PicScrub 如何处理 GIF
校验文件头
确认签名是 GIF87a 或 GIF89a
复制头部数据
原样保留 LSD 和全局色表
过滤扩展块
保留 NETSCAPE2.0 和图形控制扩展,清除注释和 XMP
保住图像数据
原样复制所有图像描述符、局部色表和 LZW 数据
写入结束符
用 0x3B 结束符收尾
LZW 压缩
顺便说说 GIF 的图像数据:它用的是 LZW 压缩,这项技术直到 2004 年才专利到期 (90 年代为此闹出过不少风波)。PicScrub 完全不碰压缩数据, 而是逐字节原样复制,所以画质零损失。
这为什么重要
原样保留 LZW 数据,可以让 PicScrub 做到:
- • 画质零损失(图像逐比特一致)
- • 处理速度快(没有解码/编码的过程)
- • 图像数据部分的体积完全不变
GIF 元数据的局限
GIF 的好消息是它比 EXIF 标准出现得还早,所以不用担心 GPS 坐标或相机信息。 它的元数据问题要平淡得多。
可能泄露什么
和 JPEG 相比,GIF 的隐私隐患算是比较小的:
- • 注释扩展(有时带着作者的备注)
- • XMP 元数据(少见,但确实可能有)
- • 应用块里的软件标识