有时候,咱们有压缩gif的需求——例如为了优化网页加载速度。在unix环境下,可使用ImageMagick工具。算法
压缩gif使用-layers
方法Optimize
:segmentfault
convert source.gif -layers Optimize dest.gif
惋惜的是,以上的命令只适用于卡通类的gif……若是你的gif是从录制的视频转化而来的,一般压缩不了多少,甚至可能比原文件更大。这是为何呢?工具
要知道这是为何,咱们先看看这个Optimize
到底作了哪些事情?优化
gif的每一帧,有一部分元素是和前一帧相同的,所以保存的时候,每一帧一般不是完整的画面,而一个较小的区块(这个区块包括了改变的部分),这样能够压缩尺寸。动画
例如,上面一帧gif,背景是不变的,因此实际储存的时候,每一帧多是这样的:spa
Coalesce就是将这些动画还原成完整的一帧一帧画面,方便后期的处理。unix
Coalesce以后的图像,从新计算、生成新的帧。这个过程能够说是“螺旋式地前进”,看起来是抵消了coalesce,其实在从新计算、生成的过程当中,使用的算法、参数可能比原图的更好,所以最终能够压缩体积。这就是基本帧优化。code
gif的帧和帧之间,有不少颜色是同样的。因此,咱们能够将这些颜色一致的区域视做背景,保存下一帧的时候,和背景重合的像素都保存为透明像素,这样就能够省去保存不少与背景像素如出一辙的像素的色彩信息。视频
例如,上面的gif图像,后面的几帧,四边使用透明像素:class
加大透明区域,就能够省去更多重复的色彩信息,从而进一步压缩尺寸,这就是透明度优化。
上面说了,对于视频转化而来的gif,压缩的效果很差。缘由就是透明度优化环节出了问题。
视频转化而来的gif,背景可能会有轻微的抖动,同时,视频的每一帧画面采用了有损压缩,相近的颜色会被压缩为同一种颜色,所以一样的颜色,在不一样的帧里面可能会被近似成不一样的颜色。这两个因素就致使透明度优化效果不好。因为透明度优化是一个很是复杂的过程,牵涉到LZW压缩算法,所以这种状况下,优化可能反而使得LZW压缩的选择变差。因此最终优化过的gif,大小就和原图差很少,甚至更大。
一旦咱们弄明白了缘由,那么解决方案就很显然了:优化的时候,将相近的颜色视为相同的颜色,这样就能够抵消抖动和色彩压缩的影响。这经过设置fuzz因子来达成:
convert test.gif -fuzz 15% -layers Optimize result.gif
-fuzz
选择多少能取得最大的压缩效果,同时对画质的影响能够接受,则须要耐心地尝试。
注意:以上的方案是假定你只有gif文件,可是若是你有视频原文件的话,就是另外一回事了。