说说大家耳熟能详的几种老牌图片格式:JPEG是目前最常见的图片格式。它诞生于1992年,是一种非常古老的格式。它只支持有损压缩,其压缩算法可以精确控制压缩比,用画质换取存储空间。它是如此普遍,以至于许多移动设备CPU都支持对其进行硬编码和硬解码。PNG诞生于1995年,比JPEG晚了几年。它本身就是为了取代GIF格式而设计的,所以它与GIF有更多的相似之处。PNG只支持无损压缩,所以它的压缩率是有限的。与JPEG、GIF相比,它最大的优势在于支持完整的透明通道。GIF诞生于1987年,并在第一代互联网中流行起来。它有很多缺点,比如通常只支持256色,透明度通道只有1位,文件压缩率不高。它唯一的优点是它支持多帧动画,这一特性使它从Windows1.0时代就开始流行,并且仍然流行。上述图像格式诞生后,许多公司或团体试图对其进行改进,或创造出其他更好的图像格式,例如JPEG组的JPEG2000、微软的JPEG-XR、谷歌的WebP,以及个别开发者的发布。BPG、FLIF等。它们是对旧图片格式的重大改进,但由于各种原因,只有少数几种格式流行起来。以下三种是目前比较强势的新兴格式:APNG是Mozilla在2008年发布的一种图片格式,旨在替代质量较差的GIF动画。它实际上只是PNG格式的扩展,所以Mozilla一直试图将其纳入PNG标准。不过PNG开发团队并没有接受APNG扩展名,而是一直在推广自己的MNG动画格式。MNG格式过于复杂,任何系统或浏览器都无法支持,而APNG格式因其简单易用而逐渐流行起来。Mozilla自己的Firefox首先支持了APNG,后来Apple的Safari也开始支持了。Chrome也尝试开始支持它。可以说,未来的前景非常好。WebP是谷歌在2010年发布的一种图像格式,希望以更高的压缩比取代JPEG。它以VP8视频帧内编码为算法基础,取得了很好的压缩效果。支持有损和无损压缩,支持完全透明通道,也支持多帧动画,没有版权问题。它是一种理想的图像格式。随着谷歌在网络世界的影响力,WebP在几年内得到了广泛的应用。看看你手机里的App:微博、微信、QQ、淘宝、网易新闻等等,每个App里面都有WebP。Facebook更进一步,使用WebP在聊天界面上显示动画贴纸。BPG是著名程序员FabriceBellard去年(2014)发布的一种超高压缩比的图片格式。可能有人会觉得这个程序员比较陌生,但是大家一定知道他的作品FFmpeg和QEMU。BPG采用HEVC(即H.265)帧内编码作为其算法的基础,在这方面无疑是目前最先进的图像压缩格式。与JP2、JPEG-XR、WebP相比,BPG在同等体积下可以提供更高的图像质量。另外,得益于自身基于视频编码算法的特点,可以保存多帧动画,文件体积非常小。FabriceBellard的聪明之处在于,他知道自己无法单独获得各大浏览器厂商的支持,所以他还专门开发了一个Javascript版本的解码器,只要任何浏览器加载这个76KB的JS文件,就可以直接将图片以BPG格式显示。目前阻碍其普及的原因是HEVC的版权问题和较长的编解码时间。虽然这种图片格式才发布一年,但已经有很多大厂开始尝试了,比如阿里、腾讯。移动端对图片类型的支持目前主流移动端对图片格式的支持有哪些?我们分别看一下目前Android和iOS的图像编解码架构:Android的图像编解码由Skia图形库负责,Skia通过挂接第三方开源库实现对常见图像格式的编解码支持。目前Android原生只支持JPEG、PNG、GIF、BMP、WebP(Android4.0新增),上层可以直接调用的编码方式只有JPEG、PNG、WebP。目前Android不支持直接动画编解码。iOS底层是ImageIO.framework实现的图片编解码器。目前iOS原生支持的格式有:JPEG、JPEG2000、PNG、GIF、BMP、ICO、TIFF、PICT。从iOS8.0开始,ImageIO增加了对APNG、SVG和RAW格式的支持。在上层,开发者可以直接调用ImageIO对上述图片格式进行编解码。对于动画,开发人员可以解码动画GIF和APNG,并可以对动画GIF进行编码。两个平台在导入第三方编解码库的时候,都对其做了一些修改。例如,Android调整了libjpeg以更好地控制内存,iOS修改了libpng以支持APNG,并增加了更多线程编解码器的特性。另外,iOS开发了专门针对JPEG编解码的AppleJPEG.framework,实现了更高性能的硬编码和硬解码。只有当硬编码和解码失败时,才会使用libjpeg。静态图片编解码由于本人目前主要做iOS开发,以下性能评测均以iPhone为例,主要测试代码可见此处。测试资料很少,只有两个:第一个是Dribbble的Logo,里面有alpha通道,用来测试简单的图形图像。第二张经典莉娜图,用于测试细节丰富的照片级图像。每张图片有四种分辨率:64x64、128x128、256x256、512x512。测试材料太少可能会导致一些测试不准确,但作为参考一般是可以的。JPEG有以下三个著名的JPEG库:libjpeg:最早也是使用最广泛的JPEG库。这个库是JPEG事实上的标准,因为JPEG标准太复杂和模糊,其他任何人都无法实现它。libjpeg-turbo:一个致力于提高编码和解码速度的JPEG库。基于libjpeg进行改造,部分代码用SIMD指令集(MMX、SSE2、NEON)重写。官网声称相比libjpeg有2到4倍的性能提升。MozJPEG:一个致力于提高压缩率的JPEG库。它是Mozilla于2014年发布的一个基于libjpeg-turbo的库,与libjpeg相比压缩率提升了5%~15%,但其编码速度也相应慢了很多。除了以上三个库,苹果还开发了一个AppleJPEG,但是没有开源。它调用芯片提供的DSP硬编码和硬解码函数。虽然没有上面三个库功能全面,但是性能非常高。在我的测试中,它的编解码速度通常是libjpeg-turbo的1~2倍。遗憾的是,开发人员目前无法直接访问该库。下面是ImageIO(AppleJPEG/libpng)在iPhone6上的编解码性能:可以看出,JPEG编码中质量越小,图像尺寸越小,质量越差,编码越短时间。解码时间差别不大,可能大部分时间花在了函数调用和硬件调用上。Apple在自己的专辑Demo中提供的质量默认值为0.9。围绕这个值,可以在画质、体积和编解码时间之间取得很好的平衡。#p#PNG与JPEG相比,PNG标准更加清晰简单,所以很多公司或者个人都有自己的PNG编解码实现。但目前使用最广泛的是PNG官方发布的libpng库。iOS和Android底层就是调用这个库实现的PNG编解码。下面是PNG在iPhone6上的编解码表现:可以看出,在编解码图形类型(颜色少,细节少)的图片时,PNG和JPEG的区别不大;但对于照片类型(丰富的色彩和细节)的图片,PNG在文件大小和编解码速度方面都比JPEG差很多。与JPEG不同,PNG是无损压缩,不提供压缩比的选项,而且它的压缩比是有上限的。目前网上有很多针对PNG优化的工具和服务,旨在提高PNG的压缩率。下面是几种常用PNG压缩工具的性能对比:pngcrush是Xcode自带的PNG压缩工具。与设计师使用Photoshop生成的图像相比,它可以达到很好的压缩效果。ImageOptim更进一步,将每张图片与多种压缩方式进行比较,选择压缩率更高的结果,进一步减小文件大小。与其他工具相比,TinyPNG.com的压缩率高得离谱。它使用类似于GIF的颜色索引表来压缩PNG,因此会导致色彩丰富的图像丢失一些细节。如果使用TinyPNG,压缩完成后最好让设计师看看颜色效果是否可以接受。WebPWebP标准由谷歌定制,目前只有谷歌发布的libwebp实现了该编解码器。所以这个库也是格式的事实标准。WebP编码主要有几个参数:lossless:YES:有损编码NO:无损编码。WebP的主要优势在于有损编码,其无损编码的性能和压缩比一般。quality:[0~100]图像质量,0表示质量最差,文件最小,细节丢失严重,100表示??图像质量最高,文件较大。此参数仅对有损压缩有显着影响。Google官方的推荐是75,腾讯对WebP评测的推荐也是75。围绕这个数值,WebP可以在压缩比和图像质量上取得更好的平衡。method:[0~6]压缩比,0表示压缩快,耗时短,压缩质量一般,6表示压缩极度,耗时长,压缩质量好。该参数也只对有损压缩有显着影响。调整这个参数可以得到更高的压缩率20%到40%,但相应的编码时间会增加5到20倍。谷歌推荐值为4。对于编码无损图片来说,quality=0,method=0~3是比较合适的参数,可以节省编码时间,压缩比也不错。对于图像的无损编码,quality=75,method=2~4是比较合适的参数,可以在编码时间、图像质量和文件大小之间取得很好的平衡。WebP解码有3个参数:use_threads:是否开启pthread多线程解码。该参数只对宽度大于512的有损图片有效,开启后内部使用多线程解码,CPU占用率会更高,解码时间可以缩短10%~20%一般。bypass_filtering:是否禁用过滤。此参数仅适用于有损图片。开启后,可缩短解码时间约5%至10%,但会在部分颜色过渡平滑的区域出现条带现象。no_fancy_upsampling:是否禁用上采样。此参数仅适用于有损图像。在我的测试中,开启这个参数后,解码时间会增加5-25%。同时会丢失一些图像细节,线条边缘会增加噪点,看起来不自然。通常情况下,这三个参数都设置为NO。如果想追求更高的解码速度,可以尝试开启use_threads和bypass_filtering这两个参数。而且no_fancy_upsampling在任何情况下都不需要开启。由于WebP测试数据较多,这里只贴出部分512x512的测试结果。有兴趣的可以看文末的Excel附件。对于简单的图形图像(比如App中的各种UI素材),WebP无损压缩的文件大小和解码速度在某些情况下甚至优于PNG。如果想优化App安装包的大小,可以试试WebP。对于复杂的图像(如照片),WebP无损编码不好,但有损编码非常好。WebP和JPEG之间质量相近的图片解码速度和JPEG相差不大,但是文件压缩比可以提高很多。BPGBPG是目前最著名的有损压缩格式,在同等质量下与JPEG相比可以减少50%的体积。以下是经典的莉娜形象对比。在这里还可以看到大量其他图片的BPG、JPEG、JPEG2000、JPEG-XR、WebP压缩效果在线对比。效果非常明显。BPG目前仅适用于作者发布的libbpg。但是作者基于libbpg编译了一个Javascript解码器,大大扩展了可用范围。bpg可以通过两种方式进行编码:无损压缩和有损压缩。在有损压缩中,质量参数可以用来控制压缩率。可选范围为0~51,数值越大,压缩率越高。一般来说,25左右是不错的选择,BPG官方工具默认值为28。libbpg目前并未针对ARMNEON进行优化,因此在移动端表现一般。下面是在iPhone6上的性能测试:因为bpg编码时间太长,我没有把数据放到表里。可以看出,在同等质量下,BPG的解码速度还是比JPEG差很多,大约慢了3到5倍。目前,BPG适用于对流量非常敏感但对解码时间不敏感的地方。从网上消息来看,手机淘宝和手机QQ都试过了,但不清楚是否优化了BPG解码。运动图片的编码和解码运动图片在互联网上非常流行。它类似于视频,但通常实现简单,文件体积小,应用范围广。动画的始祖是GIF,它从Windows1.0时代就开始流行于网络,直到今天仍然难以被其他格式所取代。尽管它很古老,但它使用的原理与当今的几种新兴格式几乎相同。下面是一个GIF格式的QQ大表情:这个表情由6张静态图片组成,每张图片都有一定的生存时间,连续播放形成动画:这些图片中的大部分内容都是相似的,为了压缩文件大小,通常动画格式支持一些特殊的方式来裁剪相似的图像,只保留前后帧的不同部分:解码动画时,解码器通常使用所谓的“画布模式”进行渲染。想象一下:游戏区是一块画布。第一帧播放前先清空画布,然后将第一帧完整绘制;当播放第二帧时,画布不再清空,只是将第一帧的不同区域叠加到画布上,就像油画的创作一样。像这样的第一帧称为关键帧(即I帧,帧内编码帧),通过补偿计算的后续帧称为预测编码帧(P帧)。在压缩良好的运动画面中,通常只有少量的关键帧,其余都是预测编码帧;劣质压缩工具制作出来的动画,基本上都是有关键帧的。不同的动画压缩工具通常会给出不同的结果。另外,动画格式通常会有更详细的参数来控制每一帧的绘制过程。以下是GIF/APNG/WebP的常用参数:#p#DisposalMethod(清除方法)DoNotDispose:put将当前帧递增绘制到画布上,不清除画布。恢复背景:在绘制当前帧之前将画布清除为默认背景颜色。恢复到上一帧:在绘制下一帧之前,将画布恢复到当前帧的上一帧。BlendMode(混合模式)BlendNone:绘制时,所有通道(包括Alpha通道)都会覆盖在画布上,相当于在绘制之前先清除画布的指定区域。Blendover:绘制时会将Alpha通道合成到画布上,即正常情况下两张图片重叠的效果。以上技术是常见动画格式的基础。下面介绍不同动画格式的特点。GIFGIF的缺陷非常明显:它通常只支持256种颜色索引颜色,这导致它只能通过抖动、差异等方式模拟出更丰富的颜色;它的Alpha通道只有1位,这意味着一个像素只能是完全透明或完全不透明。以上是腾讯博客的demo图片。可以看到由于Alpha通道的问题,GIF出现了严重的“毛刺”现象。目前通常的解决办法是在图片边缘加上白边来减少这种视觉效果:大家可以仔细观察QQ、微信等APP中的动画表情,几乎每个表情都被一圈白边包围,不得不说是一个很无奈的解决办法。制作GIF的工具很多,但是效果好、压缩率高的工具却寥寥无几。对于已经制作好的GIF,使用imagemagick进行处理,可以将文件大小压缩很多。如果您需要将视频转换为GIF,CinemagraphPro是一个很好的防呆工具。这里有一篇介绍如何用ffmpeg压缩GIF的文章。虽然参数调整有点麻烦,但是效果很理想。以下是未优化的GIF和ffmpeg优化的GIF。可以看到差距很大。APNG目前还没有被PNG官方接受,所以libpng不能直接解码APNG。但是,由于APNG只是基于PNG的简单扩展,所以在已经支持PNG的平台上用少量的代码很容易实现APNG编解码。为了支持APNG播放,Chromium只添加了不到600行代码。我还用大约500行C代码实现了一个简单的APNG编解码工具。另外,在支持canvas的浏览器上,可以使用apng-canvas直接显示APNG动画。目前最好的APNG压缩工具是apngasm,大部分图形化工具如腾讯的iSparta都是基于该工具开发的。就目前而言,APNG是GIF的最佳替代方案:实现简单、适用范围广、压缩比好、显示效果好。WebP2010年WebP发布时,它不支持动画。2012年libwebpv0.2发布时,谷歌开始尝试支持动画,但实际上问题多多,性能太差,Chrome团队一直没有接受。直到2013年libwebpv0.4的时候,动画格式才稳定下来,被Chrome接受。WebP动画实际上是简单地将多个单帧WebP数据打包到一个文件中,而不是从单帧WebP扩展而来,这样动画格式就不能向上兼容静态图片。如果要支持动态图片,需要先在编译libwebp的时候加入demux模块。解码WebP时,需要先尝试用WebPDemuxer解包,再用WebPDecode解码单帧。为了方便编译,我写了一个脚本来打包iOS的静态库,并添加了mux和demux模块。Google提供了两个简单的制作动画的命令行工具:gif2webp可以将GIF转成WebP,webpmux可以将多张WebP图片打包成动态图片,还有很多参数可以调整。这两个工具对相似帧的压缩效果并不理想,以至于在某些情况下压缩率不如APNG,但目前没有其他更好的工具可用。BPGBPG本身是基于HEVC(H.265)视频编码的,设计之初就考虑到了动画的实现。由于充分利用了HEVC的高压缩比和视频编码特性,其动画压缩比远超其他格式。这里和这里是BPG动画的几个例子。可以看到同等质量的BPG动画,大小只有APNG/WebP/GIF的十分之几。这里写了一个简单的使用libbpg解码动画的方法,有需要的可以参考。动画性能对比我将下面的GIF转成WebP、APNG、BPG动画,并在iPhone6上对其所有帧进行解码,评测结果如下:APNG在文件大小上略胜GIF,解码时间为相似的。WebP在大小和解码时间上有很大的优势。BPG在大小上有最大的优势,但它也需要最长的解码时间。从这个角度来看,APNG和WebP都是不错的选择,而BPG还有待性能优化。原文链接:http://blog.ibireme.com/2015/11/02/mobile_image_benchmark/
