PNG格式图片原理

转载请注明出处:http://blog.csdn.net/asdzheng/article/details/51476818

本篇文章翻译自谷歌出的优化视频里面的光头佬(Colt McAnlis),原文地址需翻墙,以下正文:

便携式网络图型( Portable Network Graphics [PNG])在过去几十年已经变成App开发里重要的组成部分。它广泛的运用在游戏开发、网页开发和Android开发里,但也可能被大量的滥用。

正如我之前讨论的那样,PNG是一个不错和高分辨率的图片格式,但也意味着对于数据压缩率来说我们有很多的提高空间。在探讨怎么压缩PNG文件前,我们首先得知道PNG格式的原理。

压缩原理

PNG的压缩过程是完全无损的,压缩过的文件可以准确的还原出原图,这要分两个阶段完成:推断(又称过滤[filtering])和压缩。

1. 过滤

差分编码(Delta encoding)是最强大的数字压缩法之一。原理是根据前一个数据的值将后面的值替换成其他值,例如:

[2,3,4,5,6,7,8]可以变成[2,1,1,1,1,1,1],算法是
[2, 3-2=1, 4-3=1, 5-4=1, 6-5=1, 7-6=1, 8-7=1]

这样看就很明显了,如果你的数据是线性相关的(线性相关的意思是,一组数据里的前后值都差别不大,或者具有相关性),就可以把你的数据集转换成一组重复的、低的值,这样的值更容易被压缩。

PNG格式使用了差分编码(Delta encoding)里的过滤。原理是,对于每一行的像素,一个当前的像素都跟它的左边像素、上边的像素和左上角的像素有关系。



举个例子,如果我们要编码一个给定的像素通过它与A和B平均值的差异(X-(A+B)/2),那么我们将得到:



我们使用了ABC去推断出X的值,然后我们将X替换成更小的值。

需要注意的是,每一行的像素都有可能不同,PNG允许5种不同的推断算法,它们是:

  • 不过滤
  • X-A
  • X-B
  • X-(A+B)/2(又称平均值)
  • Paeth推断(A,B,C的线性方法,这种比较复杂可看W3C的规定)

这里说明一下,每一行像素应该选择最适合的过滤算法,这样才能得到最少数量的特殊值。下面是我们关于不同模式的例子:



需要注意的是这些过滤器都是对每一行像素起作用而不是单个像素。也就是说过滤器会对每一行的红色像素起作用,再分别对蓝色的像素起作用。(尽管同一行的像素会用同样的过滤器)

现在PNG格式在选择过滤器上有一些不错的方法,开发人员根据对不同类型图片的使用经验摸索出一些不错的规律。例如对于调色板的图像(palette images)和8位的灰色图就不要过滤。对于其他图片,就选择那种能最大限度地减少绝对差异总和的值的过滤器:将所有值的绝对值相加,然后对比不同过滤器得到的值,选择那个相加起来得到最小值的过滤器。

2. 压缩

在一行像素被过滤后,就会执行DEFLATE压缩,这是LZ77延伸出来的一种算法。该算法结合了LZ77编码和哈夫曼编码,它跟PKWARE、PKZIP、GZIP等差不多相同。这种实现方式虽然是现成的,但用在压缩图片数据上,还是有一些需要注意的点:

  1. Deflate算法只能匹配3到258个之间符号,所以最大的压缩比只能到1035:1;

  2. 如果匹配到的符号小于3,那么你会产生一些额外的开销来表示这些符号;

上面的这两点意味着你的图片大小会受到每一行像素的匹配程度影响。

你可以看一下面这两张图片,左边那张270x90的图只有20k,而右边那张270x92的图是左边那张的2倍大。



这似乎不符合逻辑,一张图片多540像素在压缩率上就少了一半。不过我们看仔细点,就能知道原因了,下面这张图表示压缩器怎么去压缩一个给定的像素的。深蓝色代表压缩率很高的区域,黄色/红色代表没怎么被压缩的区域。



这是怎么出现的呢,原因是小图的每一行像素的匹配度更高,那么它的压缩率就更高。你要是调整了大小,匹配度一变化,这种情况就有可能出现。一些潜在的匹配对象不在压缩区域里,它们没有匹配到,这就又可能导致出现一张大图。

如果你想知道你的PNG图片的压缩率如何,可以下个PNGThermal看一下。

对于格式的理解

值得注意的是,PNG格式不仅仅只有在过滤和压缩两个层面,PNG还是一种非常易扩展的容器格式,它可以支持各种类型的图片和附加数据。

首先PNG文件格式里面包含不同的区块(chunks),各个区块带有不同类型的数据。例如,PNG的Header chunks(头部块)就包含有图片的宽度、高度、位的深度和颜色类型;

图片的数据块(Image data chunk)包含了实际的图像信息(数据块可以有多个)。除此之外有一个单独的区块来记录颜色调色板(palette chunk)。最后就是图片的结束区块了(end-of-file chunk)。上面的这些都是主要区块,但也有一大堆附加区块,例如:

  • 默认的背景色
  • 色度如何显示白点上的坐标
  • 图像γ数据块
  • 文本数据,语言或元数据信息
  • 颜色空间信息
  • 立体图像数据
  • 图像最后修改时间数据块
  • 图像透明数据块

上面的这些区块是你特别需要注意的地方,因为很多垃圾信息是在图片编辑软件编辑后添加进去的。举个例子,你在Photoshop保存了一张PNG格式图片,这行图片里就会有一个区块记录着”这张图片是由photshop创建的”。这样的信息对于一张显示给人看的图片并没什么鸟用,但它还是会包含在图片里。因此,删除没有的区块是减少文件大小的关键。下面是一张16X16像素的图片,左边那张是Photoshop保存的普通图片,右边那张是用了photoshop的”导出web格式”选项保存的图片,这个选项会去掉了所有的附加信息。



像素格式

PNG也支持很多种类型的像素格式,你可以选择一种最佳的:

  • Indexed(索引色) = 1个频道,可以为1,2,4,8 bpc
  • Grayscale(灰度) = 1个频道,可以为1,2,4,8,16 bpc
  • Gray+Alpha(带透明通道的灰度) = 2个频道,可以为8或16 bpc
  • Truecolor(RGB 真彩色) = 3个频道,可以为8或16 bpc
  • RGBA(RGBA 带透明通道的真彩色) = 4个频道,可以为8或16 bpc

像素格式是图片作者自己选择,我没多大的兴趣讨论,只要你确保选择正确的像素格式,不要把一张灰度图片保存为RGB/RGBA就行了。

GIF和PNG诞生的故事

在今天,当你打开一个大量内容的网页时,图片是最大的承载者。(尽管有一种观点认为视频将稍后赶超)

但真正让人感兴趣的是,尽可能多的压缩可以解决一些网页的臃肿问题,每个人都应该着手去压缩图片。

先让我们回到1985年,当时Unisys公司申请了LZW压缩算法专利,没人对它感兴趣。几年后,CompuServe公司发明了89A格式(也就是后来的GIF格式),他们用了LZW算法作为主要实现方式,没有意识到LZW是受专利保护的。而Unisys公司并没在意,直到1993年,网景浏览器增加了对IMG HTML标签的支持,并将89a格式一并支持。那一年动图就风靡于互联网上,之后Unisys就开始执行专利保护。1994年12月CompuServe和Unisys在法院上达成协议,Unisys将对所有使用89a格式图片的软件收取专利许可费。在这个协议宣布后的几个月里,一群工程师开发了一种全新的免专利的格式,这就是大家所熟知的PNG格式。

2004年,LZW算法专利终于过期,但在这10年里,GIF/PNG图片格式之争一直是网络的热点话题。

尾声

PNG是一种非常灵活和强大的图片格式类型,支持透明度的能力也使它在网页流行起来。但它并不适用于任何一种情况,在工作上使用最适用你的工具才是硬道理。如果你的图片是摄影作品且你对无损没有要求的话,JPG
或其他一些有损的处理方法可能更有效。不过你要是需要一种更小的像素格式,或者需要支持透明通道,那么PNG就绝对要比JPG好。

如果你对PNG编码器的核心技术感兴趣的话,可以看看这个叼炸天的gist,仅仅40行代码就把它搞定。

当然,如果你用WebP格式,小容量和无损都不是问题。不过,那就是另外一篇文章了。

一些翻译时候找的参考资料:

浅谈PNG无损优化
PNG格式文件分析
PNG维基百科
图片原理与优化

由于文人水平有限,如有翻译得不好的地方,请留言讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值