一 gif原理
简单来说,gif就是通过一张张静态图片连续播放产生的。
使用以下gifsicle命令将gif进行拆分,可以看出该gif是由三个帧合并得到的
三个帧的内容分别为
第三帧可以明显看出进行了处理,gif中会存储一些额外的信息,在后期gif播放时引擎会根据这些信息进行渲染,从而肉眼看到的为正常的动图。
gif信息包含: 1.文件头、2.图像帧信息、3.注释。
1 文件头(格式声明、逻辑屏幕描述符、全局调色盘)
1 .1格式声明
一般先声明是gif文件,然后再加上版本号。
通过命令行vim查看gif文件,可以看到文件开头为GIF,89a表示格式,格式有87a或者89a。
在命令行中输入hexdump xx.gif可以看到gif的16进制文件,对照ASCII码,474946代表GIF,383961代表89a。
1.2 逻辑屏幕描述符
紧跟在文件头后,固定有7个字节,表明图片需要占用的空间,包括图片宽Width(2字节)、高Depth(2B),调色盘信息Packet(1B),背景色索引(1B),像素高宽比(1B)
通过gifsicle -I xx.gif查看图片信息(需提前下载安装gifsicle)
(1)宽、高
十六进制的f8表示十进制的248,73表示十进制的115
(2)调色盘信息
十六进制f5表示二进制的1111 0101 ,以下从最高位开始描述
1)全局颜色表标志global color table flag(1bit),若为0,表示没有全局颜色表示表,若为1,后面则会跟上全局颜色表,示例图片为1;
2)颜色分辨率color resolution(3bit),代表每个像素点的颜色由多少位表示,000为无效,001表示2bits/pixel(即黑白图片),111表示8bits/pixel。
3)排序标志sort flag(1bit),表示是否按照优先顺序排序,把常用的颜色放到前面,主要是为适应早期颜色度低的时期,目前较少使用,但仍保存该位。
4)颜色表长度Global Color Table(3bit),2^(N+1)为颜色表项数,101表示2^6=项,表示最多支持64色的位图。
可在gifsicle -I信息中查看到Global Color Table的值
调色盘总长度 = 颜色表长度 * 3,这里调色盘总长度为64*3=192,相当于64种颜色,RGB表示颜色,每种占3字节。
(3)背景色索引、像素高宽比
背景色索引表示图片的背景颜色。看两篇参考链接,貌似现在没有太多作用了。
1.3 全局调色盘
颜色表长度为64,代表全局调色盘占64个颜色,用gifsicle --cinfo xx.gif可以查看颜色表信息
若调色盘信息中的全局颜色表标志为1,则在十六进制文件中,逻辑屏幕描述符后紧跟着全局调色盘数据,否则不存在全局调色盘数据。
gifsicle使用--colors参数可以对颜色参数表进行修改,可以发现只有2^2种颜色了。
2 图像帧信息
89a标准下新增了帧数据扩展,
(1)程序扩展结构、(2)注释扩展结构 、(3)图形控制扩展、(4)平滑文本扩展结构
四种扩展均以21打头,程序扩展结构为21 ff、注释扩展结构21 fe 、(3)图形控制扩展21 f9、(4)平滑文本扩展结构21 01,开始位标志后就是块大小字段。
二 gifsicle压缩gif
通过gifsicle进行gif压缩,有如下方式:
(1)通过减少帧数
gifsicle -U input.gif `seq -f "#%g" 0 2 100` -o output.gif
通过seq语句,输出格式如“#0”的在0到100范围内以2为步长的帧;
-U 有的图片会通过透明化处理压缩图片,-U参数将每一帧恢复到未优化状态,使其能够独立存在;
由于减少帧数,而且每张图片延迟的时间和之前一样,会导致图片播放过快的情况,通过延时减缓
如上减去一半的帧,则延时增加2倍,原来的时间为0.05,现在变为0.1,命令如下
gifsicle input.gif -d10 -o output.gif
gif的帧数和延迟时间可以以下命令查询
gifsicle -I input.gif
执行后结果为,紧跟在图片名后的数字为帧数,每个图片的delay信息为延时信息
(2)通过默认的算法优化
gifsicle input.gif -O3 -o output.gif
-O 对gif进行优化输出,不同数字代表不同优化级别,其中有以下三种算法:
-O1:仅存储每个图像的更改部分,这是默认设置;
-O2:进一步使用透明化来优化图片,将图片进行透明化输出,该方式会将多张图片中相同的部分透明化,只保存第一张图片出现的像素;
-O3:通过尝试几种算法,选择最优的结果。通常时间会增加一些,但有时会获取到更好的结果。
(3)减少颜色
减少调色盘的大小,值为2的次方。数字越小压缩越高,图片质量越差。
gifsicle input.gif -o output.gif --colors 64
通过计算压缩调色盘大小
gifsicle input.gif --color-method blend-diversity -o output.gif
其中的方法有:
diversity:使用xv多样性算法获取现有调色盘的子集
blend-diversity:有些颜色通过调色盘合成,而不是所有的颜色存储到调色盘中
median-cut:通过中值切割算法减少
(4)减小大小
按比例收缩,以下表示变为原来的0.5倍
gifsicle input.gif --scale 0.5 -o output.gif
减小宽高
gifsicle input.gif --resize 300x200 -o output.gif
(5)减少其他内容
去除扩展
gifsicle input.gif --no-extensions -o output.gif
牺牲画质来减少大小,值越大,画质越差,文件压缩得越小,默认值为20
gifsicle input.gif --lossy=30 -o output.gif
去除comment
gifsicle input.gif --no-comments -o output.gif
去除name
gifsicle input.gif --no-names -o output.gif
可以使用gifsicle --help 或者gifsicle官方文档查看gifsicle的具体命令。
参考链接:
http://www.lcdf.org/gifsicle/man.html
https://www.cnblogs.com/qcloud1001/p/6647080.html
https://www.jianshu.com/p/df52f1511cf8
https://qastack.cn/graphicdesign/20908/how-to-remove-every-second-frame-from-an-animated-gif