今年も残すところ1週間、2015年に向けて準備を始める時期……というわけで(?)、今回も前回に続き「PNG」について。ただし内容は実践的、手もとにあるPNGをいかにして軽量化するかにターゲットを絞り、話を進めていきたい。

ロッシーなPNG圧縮エンジン「pngquant」

高い圧縮率を誇るPNGフォーマットだが、よりコンパクトにしたい、少しでもファイルサイズを小さくしたい、というニーズも高い。特に、一部のユーザにとっては、PNGのファイルサイズが嵩むことは死活問題(さすがに大げさか)ともいえる。

前回も触れたが、それはアプリ開発者だ。iOSアプリはただでさえ多くのPNGファイルを必要とするが、Retinaディスプレイに対応するためには通常解像度とRetina向け解像度の2パターンを用意しなければならず、画像点数が増えるうえに全体のファイルサイズも増す。現在App Storeでは、100MB超のアプリについてモバイル回線経由でのダウンロードを制限しているため、その制限にかかりそうなアプリであればPNGのコンパクト化は見逃せない。

そこで検討したいのが「PNGの最適化」だ。この場合の最適化とは、PNGのクオリティを大きく損なうことなくファイルサイズを小さくすること。PNGは基本的に可逆圧縮(ロスレス)だが、非可逆圧縮することでファイルサイズを稼ごうというのだ。

ここに紹介する「pngquant」は、非可逆圧縮を用いたPNG圧縮エンジンだ。ベクトル量子化アルゴリズムにより色数を256色の異なるRGBAの組み合わせに量子化し、誤差拡散法(フロイド-スタインバーグ)によりディザリングすることで、ある程度の品質を保ちつつファイルサイズを小さくすることを狙いとする。TrueColorアルファチャネルを持つPNG画像(PNG-24)を例にすると、2分の1から4分の1のサイズにまでコンパクトにできるため、前述したアプリ開発にはもってこいの存在といえる。

pngquangを利用すれば、大きく品質を落とすことなくPNG画像のファイルサイズを小さくできる

pngquantでPNGを「軽く」する

pngquantは圧縮エンジンであり、OS Xでは「Pngyu」や「ImageAlpha」といったGUIベースの画像加工ツールを通じて利用できるが、独立して動作するコマンドの形でも配布されている。既存のPNG画像を軽量化することが目的であれば、CUIのほうが一括変換などバッチ処理は容易なため、本稿では敢えてpngquantをチョイスする。まずは以下のとおりコマンドラインを実行し、インストールしてみよう。

$ curl -O http://pngquant.org/pngquant.tar.bz2
$ tar xzf pngquant.tar.bz2
$ sudo cp pngquant /usr/local/bin
Password:

これで、Terminalからpngquantコマンドが利用できるようになる。使い方はかんたん、引数にPNG画像を与えて実行すればOK。これで、TrueColorのPNG画像(PNG-24/32)はアルファチャンネルつきの8bit(256色、PNG-8)に変換され、「[元のファイル名]-fs8.png」として出力される。

たったこれだけの処理だが、効果は大きい。Yosemiteで撮ったスクリーンショット(1366×768、PNG-24)を例にすると、オリジナルのファイルサイズは約1.24MBだったところが、約4分の1となる325KBにまで縮小された。部分的に拡大してみると、JPEGに見られるようなモスキートノイズを確認できるが、全体を俯瞰するかぎりさほど気にならない。

$ pngquant sshot.png

OS Xのスクリーンショットをpngquantコマンドで処理したところ。ファイルサイズが約4分の1にまで縮小している点に注目しよう

では、WEBサイトのようなビットマップ画像とテキストが主体の画像はどうなるのか。マイナビニュースのトップページをフルスクリーン表示し(1366×768)、そのスクリーンショットをpngquantで処理したところ、やはりファイルサイズは約4分の1にまで縮小された。使用されている写真の部分は、拡大するとJPEG的な劣化を見せるが、テキスト部分や"ベタ塗り"部分は拡大してもほとんど劣化を感じさせない。

拡大すると、写真やグラデーションがかかった部分にはモスキートノイズが発生しているが、テキストやベタ塗り部分にはほとんど劣化がない(左:処理前、右:処理後)

pngquantコマンドには、いくつかオプションも用意されている。なかでも有用なのは「--speed」オプションで、1から11の範囲でスピードを指定すると(デフォルトは「3」)、その速度に応じて圧縮率が上下する。処理速度は低下するが、圧縮率がもっとも高くなる「1」にすれば、ファイルサイズをよりコンパクトにすることができる。わずかでもいいからファイルサイズを小さくしたいという場合は、このオプションを使おう。

$ pngquant --speed 1 sshot.png

アプリをビルドする直前でPNG画像が大量にあり、しかも1つのフォルダにまとめられているとしたら、pngquantコマンドを試さない手はない。以下に示すコマンドラインは、カレントディレクトリに「pics」というフォルダがあり、そこに大量のPNG画像が収録されている場合、すべてをpngquantで圧縮/縮小してくれる。その出力結果と処理にかかる時間をチェックしたうえで、アプリに採用するかどうか検討してはどうだろうか。

$ pngquant --force --speed 1 --ext .png pics/*.png

コマンドなだけに一括処理はお手のもの。この実行例では、フォルダにあるPNG画像すべてを最高品質で圧縮/置換している