2012年2月11日土曜日

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

How to correct the OutOfMemoryError of Bitmap class

Android端末は種類が多く、画面解像度も機種ごとに違うので画像の扱いは大きな悩みどころです。
たとえばSurfaceViewに画像を表示する場合、大きめの画像データ(1024×1024ピクセル)を用意して画面解像度に合わせて縮小表示する方法が一番簡単のように思います。
ところが、Androidは大きい画像を下手に扱うと BitmapFactoryクラスが OutOfMemoryError が発生することがよくあります。

すでに多くの開発者がOutOfMemoryErrorを回避する方法を公開しています。
今更ながらMtkもいくつか方法を考えてみました。

4枚の1024×1024ピクセルの画像を1秒ごとに表示するアプリケーションで説明します。
画像は画面解像度に収まるように拡大縮小表示します。

1024×1024ピクセルのこんな画像を4種類用意します。
それぞれのファイル名はimage1.png、image2.png、image3.png、image4.pngとしました。
Androidのプロジェクトのresフォルダーの下にdrawableフォルダーを作成し、この4つの画像を保存します。

OutOfMemoryErrorが出るサンプルです。Android1.6のエミュレーターで確認しています。
※Android2.1のエミュレーターでは正常に動作しましたが実機ではOutOfMemoryErrorが起こり不安定です。
Main.java(Activity)
※Android1.6以上、パーミッション不要のため、マニフェストは省略します
Android1.6エミュレーターでアプリを実行すると
bmp2 = BitmapFactory.decodeResource ・・・
でOutOfMemoryErrorが発生します。
1024×1024ピクセルの画像(Bitmapのインスタンス)をメモリー(RAM)に置くことができないようです。

次はOutOfMemoryErrorが起きないように修正したサンプルです。
Main2.java(Activity)
Bitmapの表示のたびにファイルからロードし、次のbitmapファイルを開く前にrecycle()メソッドを実行します
表示するたびにファイルにアクセスするのは効率が悪いような気がしますが、Bitmapをメモリー(RAM)に置いておけないのだから仕方ありません。

今回はSurfaceViewを使いました。
GLSurfaceViewでポリゴンにテクスチャを貼り付けるときも GLUtils.texImage2D の直前でBitmapをロードし直後にrecycle()すると安定する思います

次回は他の方法を試してみる予定です。
公開しました http://blog.fujiu.jp/2012/02/android-bitmapoutofmemoryerror-2.html


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

0 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。