HTML5技术

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

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

成文迪, 在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦。 GIF格式的历史 GIF(Graphics Interchange Format)原义是“图像互换格式”,是CompuServe公司在1987年开发出的图像文件格式,可以说是互联网界的老古董了。 GIF格式

成文迪, 在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦。

GIF格式的历史

GIF(Graphics Interchange Format)原义是“图像互换格式”,是CompuServe公司在1987年开发出的图像文件格式,可以说是互联网界的老古董了。

GIF格式可以存储多幅彩色图像,如果将这些图像连续播放出来,就能够组成最简单的动画。所以常被用来存储“动态图片”,通常时间短,体积小,内容简单,成像相对清晰,适于在早起的慢速互联网上传播。

本来,随着网络带宽的拓展和视频技术的进步,这种图像已经渐渐失去了市场。可是,近年来流行的表情包文化,让老古董GIF图有了新的用武之地。

表情包通常来源于手绘图像,或是视频截取,目前有很多方便制作表情包的小工具。

这类图片通常具有文件体积小,内容简单,兼容性好(无需解码工具即可在各类平台上查看),对画质要求不高的特点,刚好符合GIF图的特性。

所以,老古董GIF图有了新的应用场景。

本文的应用场景

新的应用场景带来新的需求,本文所探究的问题来自于某个业务场景下——为用户批量推送GIF表情包。

一批图像大约有200-500张,以缩略图列表的形式展示在客户端。

根据我们使用测试数据进行的统计GIF图表情包的尺寸大部分在200k-500k之间,批量推送的一个重要问题就是数据量太大,因此,我们希望能够在列表里展示体积较小的缩略图,用户点击后,再单独拉取原图。

传统的GIF缩略图是静态的,通常是提取第一帧,但在表情包的情形下,这种方式不足以表达出图片中信息。比如下面的例子

——第一帧完全看不出重点啊!

所以,我们希望缩略图也是动态的,并尽可能和原图相似。

对于传统图片来说,文件大小一般和图片分辨率(尺寸)正相关,所以,生成缩略图最直观的思路就是缩小尺寸,resize大法。

但是在GIF图的场合,这个方式不再高效,因为GIF图的文件大小还受到一个重要的因素制约——帧数

以这张柴犬表情为例,原图宽度200,尺寸1.44M,等比缩放到150之后,尺寸还是1.37M,等比缩放到100,相当于尺寸变为原来的四分之一,体积还是749K

可见,resize大法的压缩率并不理想,收效甚微。

而且,我们所得到的大部分表情图素材,分辨率已经很小了,为了保证客户端展示效果,不能够过度减少尺寸,不然图片会变得模糊。

所以,想要对GIF图进行压缩,只能从别的方向入手。

探寻GIF格式的存储

想要压缩一个文件,首先要了解它是如何存储的。毕竟,编程的事,万变不离其宗嘛。

作为一种古老的格式,GIF的存储规则也相对简单,容易理解,一个GIF文件主要由以下几部分组成。

下面我们来分别探究每个部分。

文件头

GIF格式文件头和一般文件头差别不大,也包含有

格式声明

Signature 为“GIF”3 个字符;Version 为“87a”或“89a”3 个字符。

逻辑屏幕描述块

前两字节为像素单位的宽、高,用以标识图片的视觉尺寸。

Packet里是调色盘信息,分别来看——

Global Color Table Flag为全局颜色表标志,即为1时表明全局颜色表有定义。

Color Resolution 代表颜色表中每种基色位长(需要+1),为111时,每个颜色用8bit表示,即我们熟悉的RGB表示法,一个颜色三字节。

Sort Flag 表示是否对颜色表里的颜色进行优先度排序,把常用的排在前面,这个主要是为了适应一些颜色解析度低的早期渲染器,现在已经很少使用了。

Global Color Table 表示颜色表的长度,计算规则是值+1作为2的幂,得到的数字就是颜色表的项数,取最大值111时,项数=256,也就是说GIF格式最多支持256色的位图,再乘以Color Resolution算出的字节数,就是调色盘的总长度。

这四个字段一起定义了调色盘的信息。

Background color Index 定义了图像透明区域的背景色在调色盘里的索引。

Pixel Aspect Ratio 定义了像素宽高比,一般为0。

什么是调色盘?我们先考虑最直观的图像存储方式,一张分辨率M×N的图像,本质是一张点阵,如果采用Web最常见的RGB三色方式存储,每个颜色用8bit表示,那么一个点就可以由三个字节(3BYTE = 24bit)表达,比如0xFFFFFF可以表示一个白色像素点,0x000000表示一个黑色像素点。

如果我们采用最原始的存储方式,把每个点的颜色值写进文件,那么我们的图像信息就要占据就是3×M×N字节,这是静态图的情况,如果一张GIF图里有K帧,点阵信息就是3×M×N×K。

下面这张兔子snowball的表情有18帧,分辨率是200×196,如果用上述方式计算,文件尺寸至少要689K。

但实际文件尺寸只有192K,它一定经历过什么……

我们可以使用命令行图片处理工具gifsicle来看看它的信息。

gifsicle -I snowball.gif > snowball.txt

 

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

网友点评
h