FPs

圖片優化筆記

這裏說的圖片優化,目標是想儘可能降低圖片大小,但又要保證質量不錯,非常矛盾。不過降低圖片大小,可以剩一大筆流量錢,降低負載,還能提升用戶體驗,值得花點功夫。

前端方面有一些關於圖片加載速度的優化,例如CSS 畫圖,CSS 合併素材,甚至用CSS 把圖片Base64 編碼(不推薦),和這份筆記關係不大。

格式選擇

不同的需求選擇不同的格式, JPEG 能夠滿足的需求沒必要選擇PNG。

format-tree

圖片來源:《web前端图片极限优化策略》,原圖是Google 的Image Optimization

WebP、SharpP

目前對於WebP 的支持已經很好了,所以新業務能夠選擇WebP,就選WebP。
豆瓣的相冊切到了WebP,另外提供了一個讓圖片變清晰的思路:把圖片尺寸拉大到2倍,然後縮小成1倍。
圖片清晰度大大提升,還降低了圖片大小:2x WebP(73k) < 1x JPG(119k),效果如下圖(圖片來源 豆瓣 波希米亚的日記)。

douban.webp

不過採用WebP 之後,用戶“另存爲”不太方便,畢竟大家對PNG和JPEG 比較熟悉。

豆瓣的WebP 實踐:

有趣的是,WebP 基於VP8,VP8 的下一代是VP9,VP9 的對手是HEVC/H.265BGP 基於HEVC,據說表現比WebP 好很多,不知爲啥應用不多,因爲專利?

騰訊基於HEVC 搞出了一個SharpP 格式,聽說秒天秒地,目前已在騰訊雲CDN 上應用,不過接入的大都是騰訊自家的產品:

SharpP.jpg

圖片模糊的沒辦法:( ,
圖片來源:《图片流量节省大杀器:基于 CDN 的 sharpP 自适应图片技术实践》

看起來確實不錯,聽說在移動端解碼速度也很快,不過如此大規模使用估計花了不少專利費。第三方用戶使用也不方便,得使用X5內核,且只能用騰訊雲的CDN,這樣被活活綁死的事情,願意的人應該不多。另外騰訊還搞了一個TPG

不過各種專利之爭,只會導致推廣受阻,我們還是想想怎麼優化JPEG 和PNG 吧。

各種格式的介紹可以參考:《web前端图片极限优化策略》

Yelp 的圖片優化經驗

寫這篇筆記,也是因爲看到Yelp 的一篇博文:Making Photos Smaller Without Quality Loss,然後延伸看了一些東西。 Yelp 的優化圍繞JPEG 和PNG,而且看起來很通用,值得學習。

用Pillow 優化圖片

Yelp 用Pillow 來保存圖片,Pillow 支持optimize的參數:

optimize If present and true, indicates that the encoder should make an extra pass over the image in order to select optimal encoder settings.

另外也還有其他優化方式,例如大名鼎鼎的Tinypng智圖 等。推薦Pillow,Pillow 的效果不差,而且開源、免費。

選擇漸進式(Progressive) JPEG

常見的JPEG 有2種,基本式(Baseline)和漸進式(Progressive),明顯的區別是前者從上至下加載,後者加載過程從模糊到清晰。參考下圖:

baseline-tiny progressive-tiny

漸進式一般會比基本式小一些,而且加載速度更快。

speed

圖片來源:《渐进式jpeg(progressive jpeg)图片及其相关》

而且從用戶體驗上來說,從模糊到清晰比從空白展開到全部,前者體驗更好。

關於爲何漸進式會更小,需要從JPEG 的原理說起(對這一塊也一知半解),JPEG被按照8x8,從坐標變換,DCT 變換,重排列,最後量化,得到的結果左上角是大量正數,右下角聚集大量0,然後再Zig-Zag 掃描,再用霍夫曼編碼壓縮。漸進式的情況下,相當於分層了,前面的掃描包含着大量正數,後面的掃描關注更多細節,包含大量的0,這樣導致0 一起出現的概率增加,從而更易於壓縮。

對此一知半解,看到DCT 變換,涉及到傅里葉變換,感覺高數都忘記了,慚愧,有興趣的同學請自行閱讀以下兩份資料:

大尺寸的PNG 判斷,然後轉換爲JPEG

PNG 無損壓縮,體積都很大,所以能不用PNG 就不用,不過如果像Yelp 這種,用戶會上傳PNG 的話,例如iPhone 的屏幕截圖保存的格式就是PNG,完全可以轉換爲JPEG。Yelp 遇到的問題是如果用戶傳的是LOGO 之類的,需要無損,就不能轉換成JPEG,所以他們想了一個辦法:
生成一份PNG 的縮略圖,如果大於300KiB,再檢查這個縮略圖是否包含超過2^16 種不同的色彩。一般來說LOGO 的色彩都比較少和單一。

動態設置JPEG 質量因子(Quality)

JPEG 有一個質量因子,從0到100,表示圖片的質量從差到好。Yelp 做了一個實驗,發現在quality 在80~85 之間的時候,圖片效果肉眼看基本沒差別,SSIM 在0.9~0.95。SSIM 中文名稱:結構相似性,用來判斷兩張圖片的相似程度,拿一張壓縮後的圖片和原圖比較,相似越高,說明失真越小,數學原理可以看維基百科,Yelp 用pyssim來計算SSIM。

ssims-strategies

質量設置爲80~85 之間某一個值的時候,SSIM 還能保持在0.9到0.95,多奇妙啊。Yelp 提供了一段腳本來找出圖片合適的quality 值:dynamic_quality.py,用類似二分法猜數字的方法:P。

不過個人覺得對於一些色彩比較單一的圖片,可以激進一點,例如從20~85 開始找最合適的壓縮比。爲什麼色彩單一的可以調低質量呢,因爲肉眼看不出來啊。所以是不是可以延伸一下,用大量的訓練數據,用AI 的方法找到最合適的quality ?想起來Google之前推出的RAISR,非常厲害。

RAISR

扯遠了。

Yelp 博客提到的其他兩篇相關文章,類似的思路,並且文中都有成型的開源工具:

其他

  • 用Mozjpeg 替代libjpeg-turbo 或 libjpeg,性能提升明顯。
  • Subsampling
  • 嘗試有損的PNG 編碼
  • SVG
  • 。。。

END

目前,工作上沒有實踐的機會,紙上談兵,希望以後有機會練手、實踐。

This article is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
If you reprint it, please indicate the source: http://fangpeishi.com/optimizing-images.html