作为网页开发者,我们每天都需要和各种图片格式打交道,以至于有些知识几乎成了常识。比如我们应该都知道PNG可以支持透明,jpg可以压缩成较低质量,gif可以显示动态图片……但是,你知道这些不同的图片格式是如何产生并演化到今天的吗?起源最早的图片格式现在无从考证,但可以肯定的是,数字图片自从计算机诞生以来就已经存在,就像我们在没有计算机的时候创造出“杨回三角”这样的图形一样。然而,在互联网诞生后,由于信息(biaoqingbao)传输效率的迅速提高,我们有更多机会看到数字图像格式的发展。1982年,随着社交网络的兴起,一种名为ASCIIArt的艺术形式开始出现在互联网上。人们开始用一些字符组成一些复杂的形状:██████╗██████╗███╗███╗███╗███╗█████╗███████╗██╔════╝██╔═══██╗████╗████║████╗████║██╔══██╗██╔════╝██║██║██║██╔████╔██║██╔████╔██║███████║███████╗██║██║██║██║╚██╔╝██║██║╚██╔╝██║██╔══██║╚════██║╚██████╗╚██████╔╝██║╚═╝██║██║╚═╝██║██║██║████████║╚═════╝╚═════╝╚═╝╚═╝╚═╝╚═╝╚═╝╚═╝═════╝我们可以将每个单元视为显示屏的光学组件。这些光学器件在显示画面时,有的可能不发光(对应上面的空白部分),有的可能颜色不一样(对应上面的█或║)。这样,我们就用计算机非常直观的“编码”保存了这张图片——这里我不妨命名为“逗号编码”。通过Commas编码,“我们只需要保存一个二维数组,对应图中不同的位置,在数组的每一项中记录对应的字符(颜色)”。这就是我们今天看到的大多数图片的保存方式:“位图”,或者用术语来描述:“位图”。如果按照我们上面描述的方式保存这张图片,它的存储效率是多少?没错,上面的代码块其实就是图片文件本身!因为我们使用的是Unicode而不是二进制来保存,所以它的像素个数是55*6,每个像素需要存储一个Unicode字符。假设我们使用UCS-2编码,这张图片使用我们的编码方式需要“660B”的存储空间。PNM:ColorandBinary在真实的计算机世界中,真的存在像Commas编码这样的图像格式吗?事实上有。在万维网诞生之前,已经有一种用于电子邮件传输的图片格式,称为PBM(PortableBitMap)。目前,它使用.pbm后缀和image/x?portable?bitmapMIME类型。PBM是单色图像,也就是说它只有黑色和白色两种颜色,也就是游戏美术中常说的1-bit。在存储的时候,我们可以用0和1来表示黑白。比如上面的COMMAS图片,如果使用PBM,它的编码方式如下:P1#Thisiscomment5560111111001111110011000011101110000111001111100111111101100000011000011011110011110111100111101100011011000000110000001100001101101111011011011110110111111101111111011000000110000110110011001101100110011011000110000001100111111001111110011000000110110000001101100011011111110您可以将其保存为一个`。pbm`文件并使用MacOS的图片查看器查看它。与Commas编码相比,PBM失去了表达颜色的能力,但多了更多的注释结构。但是单色显然不能满足我们发表情的需求,至少黑白电视都支持不同亮度的黑色。为了让PBM支持灰度,我们可以将0和1扩展为0-255,也就是PGM;更进一步,我们还可以用255255255把每个像素点展开成真彩色,也就是大家熟悉的RGBEncoding,这就是PPM。PBM开头的P1起到描述编码的作用。P1、P2、P3分别代表PBM、PGM、PPM三种格式,统称为PNM。现在,让我们考虑一下存储空间。PBM以ASCII明文存储,上图文字长度为575,所以占用575B。当然,我们还可以进一步压缩,去掉注释后,它的长度为557B,但仅限于此;如果使用支持颜色的PPM,每个像素可能会占用11个文字长度,所以一个简单的55*6COMMASLogo需要用“3,857B”来保存!有没有办法进一步压缩图像?聪明的你一定能想到,我们可以用二进制。PBM的编码可以使用P4-P6表示它使用二进制存储。所以我们可以用两个字节来表示编码,两个Int32,也就是8个字节来表示大小,后面的330个像素可以把每个真彩色转换成一个3字节的颜色空间,所以我们总共只需要1000个B可以存储上面的COMMASLogo图片,而且还是支持真彩色的!GIF:SpaceandEncodingCompression在1980年代,1K的大小还是难以想象的——只是一个小小的Logo,比Commas文档还要大!有什么办法可以继续优化尺寸?在那个连支持真彩的显示器都买不到的年代,使用真彩编码的图片绝对是一种浪费。我们还可以缩小颜色空间以减少每个像素占用的空间。除了1-bit之外,还有一种像素游戏中常用的绘画风格叫做8-bit,意思是用8位或者1个字节来存储颜色。我们只需要将颜色限制为256种,我们就可以使用Furthercompression来进行颜色存储。假设我们把PPM的CommasLogo缩小到256色范围,每个像素可以用1个字节存储,这样上面1000B的COMMASLogo图片就可以压缩到340B,甚至比文本格式的PBM图片还好更小!玻璃的光影只需要用四种颜色就可以完成。另一方面,学过数据结构的同学可以想到一种常见的压缩方式:“霍夫曼编码”。简单的说,我们可以记录一个字典,用更小的位序列来记录更频繁出现的字符。比如逗号,如果用ASCII的话,每个字母需要1个字节或者8bit,但是如果用1来表示m,10来表示c,11来表示o……我们只需要12位来表示这个字符串!只要字典占用的空间少于压缩减少的空间,霍夫曼编码就可以有效地减小文件大小。沿着这个思路,终于诞生了一种主流的图片格式,这就是GIF。虽然现在我们一提到GIF就会想到动图,但其实GIF是最早流行的图片编码方式。GIF的全称是“GraphicsInterchangeFormat”,意思是“图像交换格式”。显然,它是为高效传输而生的。GIF使用一种称为LZW的压缩技术,该技术源自几乎所有现代压缩软件。与标准的霍夫曼编码相比,其字典是动态生成的,因此传输的大小会进一步减小。所以GIF相当于用压缩文件对图片进行编码,是不是很神奇!另外,NetscapeNavigator推出后不久,就支持GIF的多帧动画,以及定义动画重复能力的功能——这就是表情之王的发挥空间!GIF迅速风靡Internet,包含Netscape定义的动画格式成为事实上的标准。那么,除了GIF,为什么我们现在不再使用GIF了?一方面是因为GIF只支持256色,对于摄影图片来说几乎无法忍受;开放给大家使用,但是另一家公司Unisys声称已经在LZW申请了“W的专利”,要求大家支付高额的专利费……于是很快,开源社区开始抵制GIF并开始开发新的。图像格式。所以虽然从2006年开始GIF不再受专利限制,但是一个巨人已经悄然站在GIF面前,它就是PNG。PNG:PNG的全称是“PortableNetworkGraphics”,意思是“便携式网络图形”。这意味着它是从头开始设计的:Web演示方案。体积更小。替换GIF。事实上,确实如此!PNG的诞生离不开GIF的消亡,正如PNG也被解读为“PNGisNotGIF”……PNG从诞生之日起就完全免许可,被IETF作为RFC2083发布,正如我们知道很多Internet相同的底层协议(如RFC791IP、RFC1034DNS、RFC2616HTTP/1.1~~等),并在发布后不久成为W3CRecommendations。很容易理解为什么PNG可以取代GIF:毕竟,谁不喜欢免费卖淫呢?更重要的是,PNG完美解决了GIF的另一个痛点:PNG支持真彩色!!!其次,PNG还有一个很大的特点:“向前兼容”。PNG格式类似于PNM和GIF,由一个协议头+多个内容块组成,但PNG在制定标准时规定块可以分为两类:“关键数据块”和“辅助数据块”。PNG解析器必须支持对关键数据块的解析,对于辅助数据块,能识别就识别,不能识别就忽略。这个特性有什么用?我们可以重新审视,在什么情况下我们会使用GIF而不是PNG?显然,最常见的场景就是上面提到的动画。2004年,Mozilla推出了APNG格式。APNG将动画的第一帧作为PNG的关键数据块,后续帧和其他动画信息作为辅助数据块,这样即使在不支持APNG的场景中,也可以将这些图片显示为静态图片。注意这是一张PNG格式的图片!另外一个大家可能感兴趣的问题是我们经常使用TinyPNG之类的工具来压缩PNG,那么一张PNG图片是如何压缩的呢?特别是因为我们已经知道GIF拥有其压缩算法的专利?事实上,PNG和GIF的算法非常相似。前面我们提到过,GIF为LZW的W部分申报了专利,而剩下的LZ部分其实就是LZW的原始算法——LZ77,它来自于1977年两位首字母为L和Z的大佬提出的压缩算法.PNG的压缩是基于LZ77的另一种算法:DEFLATE,也是Web领域常见的GZIP压缩算法。虽然细节有所不同,但是基于动态字典的思路和GIF类似,这也保证了PNG有很高的压缩效率。JPEG:有损压缩事情已经到了这个阶段:PNG几乎处于接管的边缘,但为什么不呢?主要原因还是LZ77——它的压缩效率相对于原始数据已经很高了,但还不够。LZ77等压缩算法类似于霍夫曼编码:数据的多样性越低,压缩效率越高。这意味着对于早期互联网上的那种剪贴画,PNG是非常有优势的;但是随着图像复杂度的增加,PNG可以压缩的空间越来越有限。有没有办法压缩那些复杂的图片,比如摄影作品?JPEG就是这样诞生的。JPEG的全称是“JointPhotographicExpertsGroup”,意思是“联合图像专家组”。我们通常所说的JPEG就是这个专家组提出的第一个编码标准。在JPEG之后,其实还有更高级的标准如JPEG2000.standard,但一直没能撼动JPEG的地位(后面会提到)。事实上,JPEG出现的时间早于PNG,但相比于GIF残酷的256着色和PNG偏执的无损压缩,JPEG采用了更务实的策略:“人眼识别的有损压缩”。与我们在PNM中使用的RGB颜色空间不同,JPEG使用称为YUV的颜色空间。YUV这三个字母分别代表亮度、色调和饱和度,和现代比较流行的HSL很接近。正如设计师提倡HSL的主要原因是HSL更接近人眼感知颜色的方式,因此更适合做渐变处理。YUV在电视色频调制领域的应用也很广泛,因为:“人眼对亮度的感知超过了Hue和Saturation”。大家可以尝试打开或关闭手机的夜景模式和真彩显示,然后尝试调节亮度,你会发现我们对亮度非常敏感。不仅如此,“人眼对一定范围内的亮度差异更敏感”,比如我们会明显感觉到10%和20%比20%和25%更接近,但10%却很难区分%和90%以及20%和80%两者对比的差异。通过一些矩阵变换技术,我们可以丢弃频域中的一些细节。这个过程称为“量化”。这是JPEG有损压缩的主要来源。通常,JPEG压缩时可以选择压缩质量,这会影响量化过程的系数。从上图中我们可以看出,一些亮度变化明显的部分是JPEG损失最大的地方,比如鸟嘴周围会有明显的噪点。尽管如此,对于我们平时看到的图片,JPEG在合理保证质量的前提下,可以极大地压缩图片的尺寸,这一点在一些“画”中体现得尤为明显,因为这些作品通常亮度都比较均匀。不过,JPEG的专利问题仍然不能幸免。2002年,一家公司声称拥有JPEG的专利,在PC领域引起轩然大波,这与JPEG专家组成立时所期望的免版税标准背道而驰。经过四年的争论,此案在庭外和解。这件事也暴露了JPEG2000的专利风险,导致JPEG2000虽然技术更先进,但最终没有普及。WebP:JinShengyuzhen数据压缩是一个非常经典的信息学问题。我们之所以能够压缩数据,往往是因为数据“本来就有冗余信息”。例如,霍夫曼编码利用了不同数据出现频率的不一致,这是一种统计冗余。但是无论如何,我们没有办法在1bit中传输2bit的信息,因为信息也需要受到熵的限制。到这里,也许我们已经用尽了所有可以使用的方式:尝试过二进制编码、压缩算法,甚至为了人眼的感知而放弃部分图像信息……但是,真的是这样吗?超过?动动脑筋仔细想一想,有没有可能“把更多的图片信息部分变成冗余”呢?让我们把注意力从图片转移到其他方面。有一种格式看似和JPEG息息相关就是MPEG,但其实两者的关系类似于张飞和王菲。但是正如JPEG是一群专家的名字一样,MPEG也是,实际上是一个提出多种音视频编码标准的组织。我们通常所说的MPEG其实就是MPEG-1,它是一种音频标准。它最经典的应用是MPEG-1的第三音频层,俗称MP3。MPEG发布的最有影响的标准是MPEG-4,它包含27个子部分。每个部分都详细说明了视频编码、控制、实例、优化方法等,我们最熟悉的应该是Part14,俗称MP4。在MPEG-4中,视频编码部分由第二部分(XVID)和第十部分(AVC)组成,其中AVC更为先进;同时,由于AVC是由MPEG和国际电信联盟共同制定的,这个规范在国际电信联盟还有一个别名,就是“H.264”。H.264仅通过记录帧与帧之间的变化就可以极大地压缩视频,也就是我们通常所说的“运动补偿”。很明显,这种方式保存每一帧图片的存储效率比GIF要高出几个数量级!除了运动补偿之外,还有一些先进的压缩方法,例如“帧内预测”。这意味着当解码器解码某一帧时,“可以从某个单元的相邻单元中预测出该单元的值,这样视频文件只需要记录实际值和预测值的差值.由于其极高的压缩效率,H.264很快就统治了视频编码领域。但是,正如GIF和JPEG所面临的那样,MPEG的标准实际上包含专利。因此,很多公司都在尝试开发可以替代H.264的视频编码。谷歌在2010年收购的一家名为On2的公司就是这样做的。收购完成后不久,谷歌在当年的谷歌I/O上宣布开源On2的最新视频编码VP8。为什么?因为与此同时,谷歌推出了一种新的开源视频格式,也就是本章主角的兄弟——WebM。我们现在知道,WebM其实并没有掀起太大的波澜,但在当时依然是划时代的进步,尤其是半年后谷歌给出了基于VP8技术的全新图像格式WebP。经历了那么多版权和专利纠纷,Web领域终于有了“开源+免版税”的新业态,而且还是图片视频打包!正是因为WebP技术是从VP8衍生出来的,它继承了视频领域的有损压缩方式,也就是上面说的“帧内预测”。WebP会使用每个块上面的三个块和左边的三个块进行预测,并且包含了H.264的四种帧内预测模式,这就是为什么WebP可以比PNG更小——实现了更多原始信息的冗余通过帧内预测。在此基础上,WebP还采用了字典编码等无损压缩技术,使图像的尺寸尽可能缩小到最低。展望WebP是图像压缩的终结吗?当然不是!WebP诞生之初,其实并不支持无损压缩和透明通道,其有损压缩甚至不如JPEG;但也正是因为开源的力量,WebP才逐渐成为最占主导地位的主流Web图片格式。那么现在,除了WebP,我们还有哪些选择?如果有任何格式可以胜过WebP,BPG一定是其中之一。前面我们提到,WebP的实现来自于VP8,而VP8来自于H.264。现在你可能知道H.264已经不能满足今天大量4k、8k甚至更高显示的需求,所以在2013年国际电信联盟发布了新的视频标准H.265,学名是简称HEVC——“HighEfficiencyVideoCoding”,高效视频编码。HEVC相对于H.264做了很多改进,比如帧内预测从4种增加到33种!BPG使用基于HEVC帧内预测算法的有损压缩,这意味着它的性能明显领先于JPEG甚至WebP。不过,由于HEVC和H.264一样保留了版权,这也成为了BPG未能广泛普及的主要原因。无损压缩领域有没有?显然是有的,FLIF(https://github.com/FLIF-hub/FLIF)就是一个典型的例子。FLIF于2015年发布,也是完全开源的。FLIF采用了类似于H.264的动态学习压缩算法,在无损压缩方面将压缩性能优化到一个新的水平。然而,作为一个纯粹的社区项目,FLIF在发布后不久就逐渐没落,但其核心思想被新的JPEG标准JPEGXL所继承,JPEGXL最终在2020年作为免版税标准发布;BPG和FLIF也终于启发了MPEG,发布了基于HEVC的图像格式HEIF。WebP的后现代艺术Last故事的结局回到我们的流量王谷歌。在VP8对标H.264、国际电信联盟发布H.265后,谷歌推出VP9对标H.265;虽然不如预期,但最终促成了AOMedia(开放标准联盟,由谷歌、苹果、微软组成,由Facebook、Mozilla等创建)。基于VP10的AV1是AOMedia为替代H.265而开发的最新免版税标准。从2021年开始,谷歌将开始开发基于AV1视频编码的下一代WebP,称为WebP2。或许在不久的将来,我们就能看到一种新的图片格式的出现,并建立它的世界。
