Hatena::ブログ(Diary)

superdry memorandum :-D

20101208

[]Bitmap quality, banding and dithering 04:04

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

適切なビットマップ形式を選択すると実行時のパフォーマンスも向上します。以下は表示実行時間。

16bits16bits by dither32bits
ARGB_888819ms10ms11ms
ARGB_444415ms15ms14ms
RGB_56510ms10ms13ms

RGB_565が一番互換性に富んでいるのがわかるよね。

空のBitmap作成時とBitmaFactory.Optionsで画像をデコードするとき画像のエンコード形式を選べる。Bitmap.getConfig()で存在するBitmapのエンコード形式もとれる。windowのエンコード形式が知りたければonCreate()でgetWindow().getAttributes().formatを呼べば取得できるので、これらをつかって最適なエンコード形式で最適なパフォーマンスを実現してください。

今回使ったソースコードこちら

今回の記事には関係ないけど、OpenGL Surfaceはその互換性のために16bitsのままらしい…

トラックバック - http://d.hatena.ne.jp/Superdry/20101208/1291835054