UC內核支持更好的動畫格式-APNG
來自專欄 UC 內核發布
簡介
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規範
推薦閱讀: