HTML5技术

浓缩的才是精华:浅析GIF格式图片的存储和压缩 - 腾讯云技术社区(2)

字号+ 作者:H5之家 来源:H5之家 2017-04-07 15:08 我要评论( )

我们得到下面的文本 5 .gif 19 images logical screen 200 x196 global color table [128] background 93 loop forever extensions 1+ image #0 200 x196 transparent 93 disposal asis delay 0 .04s+ image #1 200

我们得到下面的文本

5.gif 19 images logical screen 200x196 global color table [128] background 93 loop forever extensions 1 + image #0 200x196 transparent 93 disposal asis delay 0.04s + image #1 200x188 transparent 93 disposal asis delay 0.04s ........

可以看到,global color table [128]就是它的调色盘,长度128。

为了确认,我们再用二进制查看器查看一下它的文件头

可以看到Packet里的字段的确符合我们的描述。

在实际情况中,GIF图具有下面的特征

(1)一张图像最多只会包含256个RGB值。

(2)在一张连续动态GIF里,每一帧之间信息差异不大,颜色是被大量重复使用的。

在存储时,我们用一个公共的索引表,把图片中用到的颜色提取出来,组成一个调色盘,这样,在存储真正的图片点阵时,只需要存储每个点在调色盘里的索引值。

如果调色盘放在文件头,作为所有帧公用的信息,就是公共(全局)调色盘,如果放在每一帧的帧信息中,就是局部调色盘。GIF格式允许两种调色盘同时存在,在没有局部调色盘的情况下,使用公共调色盘来渲染。

这样,我们可以用调色盘里的索引来代表实际的颜色值。

一个256色的调色盘,24bit的颜色只需要用9bit就可以表达了。

调色盘还可以进一步减少,128色,64色,etc,相应的压缩率就会越来越大……

还是以兔子为例,我们还可以尝试指定它的调色盘大小,对它进行重压缩

gifsicle --colors=64 5.gif > 5-64.gif gifsicle --colors=32 5.gif > 5-32.gif gifsicle --colors=16 5.gif > 5-16.gif gifsicle --colors=2 5.gif > 5-2.gif ......

依然使用gifsicle工具,colors参数就是调色盘的长度,得到的结果

注意到了2的时候,图像已经变成了黑白二值图。

居然还能看出是个兔子……

所以我们得出结论——如果可以接受牺牲图像的部分视觉效果,就可以通过减色来对图像做进一步压缩。

文件头所包含的对我们有用的信息就是这些了,我们继续往后看。

帧信息描述

帧信息描述就是每一帧的图像信息和相关标志位,在逐项了解它之前,我们首先探究一下帧的存储方式。

我们已经知道调色盘相关的定义,除了全局调色盘,每一帧可以拥有自己的局部调色盘,渲染顺序更优先,它的定义方式和全局调色盘一致,只是作用范围不同

直观地说,帧信息应该由一系列的点阵数据组成,点阵中存储着一系列的颜色值。点阵数据本身的存储也是可以进行压缩的,GIF图所采用的是LZW压缩算法。
这样的压缩和图像本身性质无关,是字节层面的,文本信息也可以采用(比如常见的gzip,就是LZW和哈夫曼树的一个实现)

基于表查询的无损压缩是如何进行的?基本思路是,对于原始数据,将每个第一次出现的串放在一个串表中,用索引来表示串,后续遇到同样的串,简化为索引来存储(串表压缩法)

举一个简单的例子来说明LZW算法的核心思路。

有原始数据:ABCCAABCDDAACCDB

可以看出,原始数据里只包括4个字符A,B,C,D,四个字符可以用2bit的索引来表示,0-A,1-B,2-C,3-D。

原始字符串存在重复字符,比如AB,CC,都重复出现过。用4代表AB,5代表CC,上面的字符串可以替代表示为45A4CDDAA5DB

这样就完成了压缩,串长度从16缩减到12。对原始信息来说,LZW压缩是无损的。

除了采用LZW之外,帧信息存储过程中还采取了一些和图像相关的优化手段,以减小文件的体积,直观表述就是——公共区域排除、透明区域叠加

这是ImageMagick官方范例里的一张GIF图。

根据直观感受,这张图片的每一帧应该是这样的。

但实际上,进行过压缩优化的图片,每一帧是这样的。

首先,对于各帧之间没有变化的区域进行了排除,避免存储重复的信息。
其次,对于需要存储的区域做了透明化处理,只存储有变化的像素,没变化的像素只存储一个透明值。

这样的优化在表情包中也是很常见的,举个栗子

上面这个表情的文件大小是278KB,帧数是14
我们试着用工具将它逐帧拆开,这里使用另一个命令行图像处理工具ImageMagick

gm convert source.gif target_%d.gif

可以看出,除了第一帧之外,后面的帧都做了不同程度的处理,文件体积也比第一帧小。

这样的压缩处理也是无损的,带来的压缩比和原始图像的具体情况有关,重复区域越多,压缩效果越好,但相应地,也需要存储一些额外的信息,来告诉引擎如何渲染,具体包括

帧数据长宽分辨率,相对整图的偏移位置

透明彩色索引——填充透明点所用的颜色

Disposal Method——定义该帧对于上一帧的叠加方式

Delay Time——定义该帧播放时的停留时间

其中值得额外说明的是Disposal Method,它定义的是帧之间的叠加关系,给定一个帧序列,我们用怎样的方式把它们渲染成起来。

详细参数定义,可以参考该网站的范例

Disposal Method和透明颜色一起,定义了帧之间的叠加关系。在实际使用中,我们通常把第一帧当做基帧(background),其余帧向前一帧对齐的方式来渲染,这里不再赘述。

理解了上面的内容,我们再来看帧信息的具体定义,主要包括

1和3比较直观,第二部分和第四部分则是一系列的标志位,定义了对于“帧”需要说明的内容。

帧数据说明。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 你首先是一个人,然后你才是程序员。 - 左潇龙

    你首先是一个人,然后你才是程序员。 - 左潇龙

    2017-03-22 14:00

  • 程序猿看小说还要去找TXT?自己动手爬一个TXT才是正确的打开方式 - JangoJing

    程序猿看小说还要去找TXT?自己动手爬一个TXT才是正确的打开方式 - J

    2016-06-29 17:00

  • Zynga德国主管:HTML5才是游戏行业未来_HTML5中文网

    Zynga德国主管:HTML5才是游戏行业未来_HTML5中文网

    2014-11-17 18:29

网友点评
-