Edited at
HTML5Day 23

PNGの非可逆圧縮ーLossy PNG

More than 3 years have passed since last update.


背景

Webページの高速化するためにはイメージサイズをできるだけ小さくすることが必要です。たとえば、最近のWebページのコンテンツタイプごとのサイズは以下のようのなっており、イメージが全体の半分程度を占めています。

さらにイメージの中でのフォーマットは、以下の図のようにJPEGで約半分、PNGとGIFがぞれぞれ1/4ずつとなっています。

JPEGは基本的に画質のトレードオフでコンテンツ作成者がサイズを決めていると思いますが、GIFやPNGは可逆圧縮のためサイズを小さくすることが難しいです。特に透明画像を使いたい場合はPNGしか選択肢はありませんが、パフォーマンスを考えるとPNGでもサイズをなるべく小さくしたいです。この秋に開催されたO'Reilly Velocity Euro Conferenceでもいつくかのセッションで挙げられていましたが、Lossy PNGを使うことで画像のサイズを小さくできます。


Lossy PNGの原理

PNGの圧縮にはRGBからindex colorに減色する方法がありますが、ここではRGBのままでの非可逆圧縮について説明します。なお、index colorの非可逆圧縮は以下の説明と違うアルゴリズムが必要です。


PNGの圧縮の原理

通常のPNGのエンコーダは、大きく分けて次の3段階の処理で行われます。


  1. スキャンライン化などの前処理

  2. フィルタ処理

  3. 圧縮処理

圧縮処理はDeflate方式で圧縮を行います。これは、よく使われるZIPとほとんど同じです。画像データをそのまま圧縮処理してもあまり圧縮されないため、フィルタ処理でより効率的に圧縮できるよう画像データを変換します。

フィルタ処理を簡単な例で説明します。

例としてR成分だけの赤い画像を考えます。R成分だけを抜き出すと、

190, 191, 192, 193, 194, 193, 192, 191, 190, 189

これを左隣との差分に置き換えると

190, 1, 1, 1, 1, -1, -1, -1, -1, -1

となります。左端は0との差分なのでそのままの値になります。このように変換することでより高い圧縮率を得られます。


非可逆圧縮

差分を計算するところで、少々「うそ」をついて

190, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

とすればどうでしょう? デコードした画像は

190, 190, 190, 190, 190, 190, 190, 190, 190, 190

となり、元の微妙な赤の陰影が単色の画像に劣化しますが、より圧縮することができます。

これがPNGの非可逆圧縮の原理です。

こうして出来上がったPNGファイルは通常のPNGファイルと全く同じです。言い換えれば、PNGファイルだけを見て非可逆圧縮されたものか、もともと単色の画像だったかは判別できません。

したがって、非可逆圧縮されたPNGファイルも通常のPNGデコーダでデコードできます。

これがLossy PNGの最大の利点です。WebPなど圧縮率を改善した新しいフォーマットが提案されていますが、使えるWebブラウザは限られています。しかし、Lossy PNGの場合、フォーマットそのものは通常のPNGであるため、ほとんどすべてのWebブラウザで表示できます。


使用したツール

今回はソースコードが確認できる

lossypng

を使用しました。実際の圧縮アルゴリズムは上記より複雑です。

また、圧縮した画像の評価には

dssim

を使用しました。これは画像の評価で標準的に使われているstructual similairityを計算するツールで数字の小さいほど画像間の差がないことを表します。


評価


写真

まず、写真を圧縮してみました。

元画像です。



475KB

lossypngは-sオプションで圧縮率を指定できます。-s=0でlosslessで、数字が大きくなるほど圧縮率が大きくなります。以下は何種類かの圧縮率で圧縮した画像です。



-s=20 84KB (18%) DSSIM 0.033773

ファイルサイズは元画像の18%まで小さくなりましたが、パッと見た目はほとんど劣化が目立ちません。



-s=30 61KB (13%) DSSIM 0.055768

サイズは13%ですが、肌などで劣化がわかるようになりました。



-s=50 40KB (8%) DSSIM 0.101474

ここまで小さくすると劣化がはっきりと目立ちます。



-s=80 28KB (6%) DSSIM 0.169919

参考までにかなり圧縮率をあげた例です。


まとめ

lossy PNGでサイズを大幅に小さくすることができます。また、表示するために特別なデコーダは必要ないので、PC、モバイルなどのほとんどのWebブラウザで表示可能です。