AndroidでBitmapFactoryを使ってサイズの大きな画像を読み込むサンプル

Androidで開発をやっていると、何度もOutOfMemoryErrorに出くわすことが多いです。Androidは搭載メモリ自体が少なく、1アプリケーションあたり最高で16M。推奨だと8M程度(実際使ってみるとそれより少ない感じ)とされています。そのため、普段PCで開発するのとは違って、結構メモリの容量を意識してプログラムしないといけなかったりします。

普通にちょっとしたプログラムを組む分にはいいのですが、結構困るのはサイズのでかい画像イメージを扱う場合です。特にデジカメなんかで撮った画像は最近のデジカメの画素数がすごいため、jpgファイルの段階で数メガバイトあったりします。

そうした画像をBitmapFactory.decodeFileメソッドなんかで、一度に何枚も読み込んでしまうと、もともとサイズの大きなjpgがメモリ中で展開されて更に大きくなってしまうため、あっという間にOutOfMemoryErrorとなってしまいます。

ということで、そんな場合にはBitmapFactory.Optionsを使って、元画像を読み込む段階で小さくして読み込むといい感じになります。

//読み込み用のオプションオブジェクトを生成
BitmapFactory.Options options = new BitmapFactory.Options();
//この値をtrueにすると実際には画像を読み込まず、
//画像のサイズ情報だけを取得することができます。
options.inJustDecodeBounds = true;

//画像ファイル読み込み
//ここでは上記のオプションがtrueのため実際の
//画像は読み込まれないです。
BitmapFactory.decodeFile(path, options);

//読み込んだサイズはoptions.outWidthとoptions.outHeightに
//格納されるので、その値から読み込む際の縮尺を計算します。
//このサンプルではどんな大きさの画像でもHVGAに収まるサイズを
//計算しています。
int scaleW = options.outWidth / 380 + 1;
int scaleH = options.outHeight / 420 + 1;

//縮尺は整数値で、2なら画像の縦横のピクセル数を1/2にしたサイズ。
//3なら1/3にしたサイズで読み込まれます。
int scale = Math.max(scaleW, scaleH);

//今度は画像を読み込みたいのでfalseを指定
options.inJustDecodeBounds = false;

//先程計算した縮尺値を指定
options.inSampleSize = scale;

//これで指定した縮尺で画像を読み込めます。
//もちろん容量も小さくなるので扱いやすいです。
Bitmap image = BitmapFactory.decodeFile(path, options);

現時点でのAndroidの画面解像度はHVGAしかないので、画像オリジナルの大きさそのものを読み込む必要はあんまり無いってことなんですよね。

特に複数画像を読み込んでサムネイルを作るような場合は、一度オリジナルの画像を読み込んで縮小して。。。なんてことをやってるとすぐにメモリを使い果たしてしまうので、読み込む段階で小さな画像として読み込むと使い勝手がいいんじゃないかなぁと思います。

Twitterでも情報配信中!



コメント(7)


nanashi

参考になりました。
ありがとうございます。


yankoba

超参考になりました。
本当にいいポストだと思います。


wani

超超参考になりました。
最近のカメラはむやみにデータがでかいので、これは必須です。


artsylar

ありがとうございます。
参考になりました!。


Toshio

とっても参考になりました。
ありがとうございます。


匿名

参考になりました。
ありがとうございます!


たらお

まさにこれで困っていた所だったのですごく参考になりました。
ありがとうございます


コメントを残す

メールアドレスが公開されることはありません。



次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

※コメントは承認制です。承認されるまで表示されません。