2012年2月18日土曜日

[Android] BitmapクラスのOutOfMemoryErrorを防ぐ #2

How to correct the OutOfMemoryError of Bitmap class #2
前回は画像表示のたびにBitmapFactory.decodeResourceを実行して、表示後にrecycle()メソッドで解放する方法でOutOfMemoryErrorを防ぎました。
この方法は安定して動作しますが、表示のたびにファイルにアクセスしてデコード処理を実行するので効率が悪いような気がします。

そこで他の方法を考えました。
Bitmapクラスは画像を整数の配列に変換する getPixelsメソッド と、整数の配列を画像に戻す setPixelsメソッド があります
画像を配列に変換したり、配列を画像に変換する処理はCPUとメモリー(RAM)の間のデータ転送が主な内容になるはずです。
ファイルアクセスやデコード処理が1回で済むのでもっと効率が上がりそうです。

今回は1024×1024ピクセルの4枚の画像を整数の配列に変換することをを試してみます。
成功すればBitmapFactory.decodeResourceは各画像につき1度しか実行されないので効率が上がるはずです。

Main3
結果
整数の配列の確保(new int[1024 * 1024])でOutOfMemoryErrorが起きてしまいました。
Android1.6と2.1のエミュレーターで確認しました。
Androidのint型は4バイトなのでint[1024 * 1024]の配列は連続した4MBの空きメモリー(RAM)が必要になるわけですが、それを4つも確保するのは難しいようです。
int[1024][1024]の2次元配列を使う方法に直して試みましたがやっぱりOutOfMemoryErrorが起きました。

RAM容量の多い端末で正常動作するかもしれませんが、エミュレーターで動作しない方法なのでお勧めできません。

ちなみにgetPixelsメソッドはJNI(Android-NDK)のOpenGLでポリゴンのテクスチャを貼り付けるときに必須のメソッドです。
http://blog.fujiu.jp/2011/08/android-android-ndk.html

今回はわざと大きい画像や配列を扱ってエラーが出ることを確認しました。
将来のAndroid端末は今以上にRAMの大容量化、画面の高解像度化が予測されます。
Android-SDKやOSも進化して大きいBitmapを扱いやすくなってます。
古い端末でも簡単に扱えるようになったらいいですね。


以上、参考になれば幸いです。

0 件のコメント:

コメントを投稿