UC内核支持更好的动画格式-APNG

UC内核支持更好的动画格式-APNG

简介

APNG(Animated Portable Network Graphics),基于PNG(Portable Network Graphics)规范的扩展动画文件格式。APNG文件类似于GIF文件,但是支持了GIF不支持的24-bit图像以及透明通道。另外,基于GIF生成的APNG尺寸往往小于GIF。因此,APNG是一种可以用来代替GIF的文件格式,因为你可以选择比GIF更好的效果或者选择比GIF更小的文件尺寸。

本文的主要目的是推荐前端同学将当前的GIF格式替换到APNG格式。如果你尚未了解APNG格式,建议你花5分钟时间读完兼容方案章节即可。如果你对APNG格式细节感兴趣也可以多花一些时间读完全文。

几种动画格式的对比

目前最流行的动画格式是GIF格式,除此之外,本文提到的APNG格式,以及WebP格式都是比较常见的动画格式。本文建议使用的动画格式是APNG格式。

尺寸

相同图像效果下:WebP < APNG < GIF

说明:理论上来说WebP的压缩率是最高的,但是经过实际测试发现如果同样是从GIF转换过来的图片格式,APNG的文件尺寸往往小于GIF的文件尺寸。

效果

从图像质量的维度来看,WebP = APNG > GIF。因为WebP和APNG都可以提供24-bit图像已经透明通道,因此这两种格式的动画的图像质量都要远远好于GIF格式。

性能

从加载时间的维度来看,WebP > APNG > GIF。由于APNG图片的第一帧是一张完整的PNG图片,因此WebP格式的首图像显示时间要小于APNG格式的首帧显示时间,点击这里可以查看一个关于APNG和WebP的文件尺寸,加载时间的对比说明。另外,UC的开发者工具Trace工具也可以直观的查看到不同格式的动画显示时间,CPU占用率。

支持情况

GIF > APNG > WebP

GIF毫无疑问是支持的最好的,全平台支持。

APNG目前在safari和最新版本的chrome for android上支持,android的系统webview尚未支持。

WebP在iOS上尚未支持。

安卓版的UC内核,WebP的动画格式已经支持,APNG格式支持的开发工作已经完成,不久后会正式上线。

APNG实战

前面简要的介绍了APNG。接下来我们会通过实例,使用GIF文件生成APNG格式的文件进行比较。

压缩工具

本文选用了gif2apng作为压缩工具,版本是1.9,工作环境是ubuntu16。工具可以从这里下载,使用方法如下:

gif2apng options anim.gif anim.png

-z0:zlib压缩

-z1:7zip压缩(缺省)

-z2:Zopfli压缩

-i##:7zip和Zopfil的循环次数(缺省为15)

实例

选择了天猫超市首页的三张gif图片做测试,原始图片如下:

图1:


图2:


图3:

压缩命令如下:

例如使用Zopfil压缩方案,循环100次压缩gif3.gif文件,生成png3-z2-100.png

实验结果如下:

实验结论:

  • APNG格式的尺寸一定小于GIF,普遍可以节省15% ~ 30%的空间
  • Zopfil比7zip的压缩率更高,可以节省1%的空间
  • 循环次数对压缩比影响小于算法
  • 循环次数增加会导致压缩时间变长

压缩后的效果如下(下例使用Zopfil压缩,循环15次):

APNG(本来是APNG格式的图片,被知乎转码了)

GIF


另外,不同的压缩方式,不同的压缩循环次数目前没有对图片的显示有明显的影响(包括CPU使用率,内存等),不过这个结论还需要继续观察。

视频转APNG

大家都知道ffmpeg可以将视频转为GIF,实际上ffmpeg同样也支持APNG的编码。

ffmpeg -i your.mp4 -plays 0 out.apng

转码支持各种参数。没有任何参数的情况下,生成的apng格式文件的尺寸很感人。

点击这里可以看到同样的视频分别转码APNG和GIF的对比效果。

兼容方案

UC内核近期更新后会支持APNG格式动画,那么对于尚未更新到最新UC版本内核(例如早期版本的U4 SDK,系统webview等)的应用应该如何做兼容处理?回退到GIF动画么?

答案是不必。apng-canvas是一个JS版本的兼容方案。如果你的应用不支持APNG格式时可以使用这个库做兼容方案。

如何检测你的应用是否支持APNG格式

示例代码

/*
 * apng-detect.js
 * 2010-06-13
 * By Eli Grey, http://eligrey.com
 *
 * Detects if a browser supports the APNG format and sets a
 * global `APNG` boolean indicating if the browser supports APNG.
 *
 * Public Domain.
 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 */
(function() {
  "use strict";
  var apngTest = new Image(),
  ctx = document.createElement("canvas").getContext("2d");
  apngTest.onload = function () {
    ctx.drawImage(apngTest, 0, 0);
    self.APNG = ( ctx.getImageData(0, 0, 1, 1).data[3] === 0 );
  };
  apngTest.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACGFjVEwAAAABAAAAAcMq2TYAAAANSURBVAiZY2BgYPgPAAEEAQB9ssjfAAAAGmZjVEwAAAAAAAAAAQAAAAEAAAAAAAAAAAD6A+gBAbNU+2sAAAARZmRBVAAAAAEImWNgYGBgAAAABQAB6MzFdgAAAABJRU5ErkJggg==";
  // frame 1 (skipped on apng-supporting browsers): [0, 0, 0, 255]
  // frame 2: [0, 0, 0, 0]
}());

APNG表示你的应用是否支持APNG格式。代码来自这里。原理,不支持APNG的应用只能绘制第一帧,支持APNG的应用可以绘制到第二帧,判断canvas的数据是否为第二帧数据即可以判断应用是否支持APNG。

兼容方案示例

这里下载最新的(其实最后更新也是2年前了)库,页端加载"app-canvas.min.js"即拥有纯JS绘制APNG动画的能力。

示例代码

  var img1 = document.getElementById("z1")
  img1.src = "./resources/test.png"
  img1.onload = function() {
    APNG.animateImage(img1);
  }

图片加载成功后,调用APNG.animateImage绘制的img元素。

通过trace工具查看,使用兼容方案绘制APNG动画不会有明显的CPU占用率提升的现象。实际使用过程中也未发现有明显卡顿,掉帧等现象。另外,该JS库的尺寸为15K,因此当页面中原始GIF文件的总尺寸超过100K时,即使你的应用不支持APNG解码,使用该JS兼容方案也能获得收益。

关于APNG的一些技术细节

前面章节介绍了APNG的优势(尺寸,效果等),下面章节主要是介绍APNG本身的一些技术细节,跳过后面的章节并不影响你使用APNG。

PNG结构

一个标准的PNG格式由PNG签名(8 bytes)和多个PNG块构成。一个PNG块由4部分构成:块长度(4 bytes),块类型(4 bytes),块数据以及CRC校验(4 bytes)。

最简单的PNG格式由3种PNG块构成,IHDR(图像头)块,一个或多个IDAT(图像数据)块和IEND(图像结尾)块。

APNG结构

PNG格式在设计之初就考虑到扩展性,解码器在解码PNG格式或基于PNG扩展的格式的文件时,只需要解码支持的PNG块,忽略尚未支持的PNG块。因此一个仅支持PNG格式的解码器解码APNG文件时,识别到APNG文件中的PNG签名,IHDR块,IDAT块,IEND块也可以将缺省图片解码出来。因此APNG格式是向后兼容的。

acTL结构

IDAT块之前一定有acTL块

fcTL结构

IDAT块或fdAT块之前一定有fcTL块

  • 缺省图片,如果存在fcTL块则一定出现在第一个IDAT块之前。不存在相对于acTL块的位置
  • 缺省图片以外的第一帧,fcTL块一定会出现在全部IDAT块之后,fdAT块之前
  • 其余帧,第N帧的fcTL块一定出现在第N-1帧的fdAT块之后,第N帧的fdAT块之前

GIF文件尺寸比较

APNG和GIF都是增量渲染,即仅渲染帧变化的区域,这样可以降低文件尺寸。那么为什么同样的动画文件,APNG尺寸小于GIF?

以下是相同的动画内容不同文件格式的数据解析,显示了每一帧在文件内所占用的尺寸:

上图为GIF文件解析结果,下图为APNG文件解析结果。

GIF文件的压缩方式导致它每一帧都会大于同等质量的APNG文件。另外,GIF每一帧的额外数据尺寸大约为200Bytes,而APNG每一帧的额外数据尺寸大约为40Bytes。因此,帧数越大GIF文件的尺寸也会越大。

参考文档

APNG Wiki

APNG那些事

APNG规范

文章被以下专栏收录