Bitmap quality, banding and dithering
Romain Guyさんが自身のブログで、Android 2.3 (Gingerbread)のBitmap表示品質向上対応について語っている。適当に訳してみた。
AndroidのBitmapエンコード形式には以下の3つが用意されています。
- RGB_565…昔のAndroidのBitmapエンコード形式。透過できない。16ビット。
- ARGB_4444…透過できる。16ビット。でも表示が美しくない。
- ARGB_8888…透過できる。32ビット。美しいけどメモリくう。
しかし、16ビット領域でARGB_8888を表示した場合など、最適なエンコードで表示されないと画像が汚くなります。32ビットの画像は32ビット領域で、16ビットの画像は16ビット領域で、横方向に帯が入ります。
対処法として、例えばRGB_565をPhotoshopなどで事前にディザ加工してきれいに表示する方法があります。しかしこの方法はおすすめしません。ノイズを焼き込んだり、再利用がむずかしいからです。
そこで今までは、Paint.setDither(boolean)とかDrawable.setDither(boolean)とかで、見かけ上きれいな表示を実現してました。
2.3からはすべてのwindowで32ビット表示となります。
- RGBX_8888…透過しない。32ビット。
- RGBA_8888…透過できる。32ビット。
画像もすべて32ビット表示。
- ARGB_8888
適切なビットマップ形式を選択すると実行時のパフォーマンスも向上します。以下は表示実行時間。
16bits 16bits by dither 32bits ARGB_8888 19ms 10ms 11ms ARGB_4444 15ms 15ms 14ms RGB_565 10ms 10ms 13ms RGB_565が一番互換性に富んでいるのがわかるよね。
空のBitmap作成時とBitmaFactory.Optionsで画像をデコードするとき画像のエンコード形式を選べる。Bitmap.getConfig()で存在するBitmapのエンコード形式もとれる。windowのエンコード形式が知りたければonCreate()でgetWindow().getAttributes().formatを呼べば取得できるので、これらをつかって最適なエンコード形式で最適なパフォーマンスを実現してください。