原文は「 https://github.com/bither/bither-android-lib/blob/master/REASON.md 」
なぜ iPhone の画像は Android の画像よりもずっと高品質なのか
Android と iPhone との比較は多くの点で議論されており、どちらがより良いかは、Android の画像の質は iPhone とくらべてずっと劣るという点を除けば、未だ結論が出ていません。Facebook、Twitter、Instagram 等どれを使っていても、写真をとって、フィルタをかけて、ソーシャルネットワーク上に公開すると、いつも Android から投稿される写真は画質が劣化しています。しかし何故でしょう?
私達は昨年の間調査をし、そしてついに、Google が犯したほんのちょっとしたミスが原因であることを突き止めました。それは本当にちょっとしたミスでしたが、その影響はすべての画像を扱うアプリケーションに波及するほど大きく、現在に亘っても影響が続いています。
問題は、libjpeg
です。
libjpeg
といえば、数多くのオープンソースプロダクトでも使用されており、Android も画像の圧縮に使っています。Android のソースコードを見ると、Android では、libjpeg
を直接使用せず、Skia
という画像処理エンジンをベースに使用していることがわかります。Skia
は Google がメンテナンスをしているエンジンで、必要な機能はすべて実装されており、Google や他の多くのプロダクト(Chrome、Firefox、Android など)で広く使われています。Skia
はうまくlibjpeg
をカプセル化しており、だれでも簡単に画像処理ライブラリを作ることが出来るようになっています。
libjpeg
を使って圧縮を行うとき、非常に重要なoptimize_coding
というパラメータがあります。ドキュメントによると、このパラメータについて以下のような説明があります。
boolean optimize_coding TRUE causes the compressor to compute optimal Huffman coding tables for the image. This requires an extra pass over the data and therefore costs a good deal of space and time. The default is FALSE, which tells the compressor to use the supplied or default Huffman tables. In most cases optimal tables save only a few percent of file size compared to the default tables. Note that when this is TRUE, you need not supply Huffman tables at all, and any you do supply will be overwritten.
optimize_coding
をTRUE
に設定すると、より多くのディスクスペースと時間を要するために、デフォルト値はFALSE
とされていることがわかります。
ドキュメントも普通ですし、libjpeg
も安定していることから、何も問題はなさそうに見えます。しかし、このドキュメントが 10 年以上前に書かれた、ということにもっと注目すべきです。その頃は、メモリも計算能力もとても限られていました。しかし、今日のコンピュータやスマートフォンが持っている計算能力を鑑みると、これはもはや問題ではなくなりました。その代わりに、私達は画質と画像サイズについてより注目していくべきなのです。
Google のSkia
を担当しているエンジニアは、このパラメータを設定しませんでした。つまり、Skia
のlibjpeg
はoptimize_coding
がFALSE
のままです。そしてSkia
はこのパラメータを完全にライブラリに隠蔽してしまったため、Skia
の外からこのパラメータを設定することすらも出来ません。このことが大きな問題となり、私達は大きなファイルサイズと劣化した画像を強いられています。
私達はoptimize_coding
を様々な画像でテストしました。圧縮後の画質を同じにしようとしたとき、optimize_coding
をTRUE
にした時に比べて、FALSE
にした時のファイルサイズは 5〜10 倍に膨れ上がりました。この違いはとても大きなものです。
私達はまた、iOS と Android での Jpeg 圧縮の差異についても検証しました。同じ原画像に対し、おなじ画質レベルを保つ場合、Android のほうが 5〜10 倍のファイルサイズを必要とします。
結果は明らかです。Apple はoptimize_coding
とHuffman tables
についての重要性を良く知っており、Google はそうではなかったということです(Apple は独自の Huffman table アルゴリズムを使っており、画像圧縮についてより多くのチューニングをしているようです)。
最終的に、私達は Android の提供する画像圧縮機能を使わないことにしました。その代わりに、自分たちでビルドしたlibjpeg-turbo
をベースとしたライブラリを使うことにしました(libjpeg-turbo もパフォーマンスが改善されています)。これによって、私達はこれまでより 5〜10 倍スペースを確保し、同じかよりよい画質を得ることができました。これは誰もがすべきことだと思います。
という訳で、Android の libjpeg
が何故腐っていると言われ続けているのかが良くわかる記事の紹介でした。