Hatena::Groupandroid-dev

今日のGの1

2008-12-31

Bitmapへの画像読み込み

23:23

iPhone OSのUIImageに相当するものがBitmapかなと思っています。例えばこんな状況を考えてみましょう。Bitmap bitmap_aは変更可能なBitmapで、そこに変更可能ではないかも知れないBitmap bitmap_bの画像を流し込みたい。その時はCanvasを介してこんな風にできる訳です。

 		Canvas canvas_a = new Canvas(bitmap_a);
 		canvas_a.drawBitmap(bitmap_b, 0, 0, null);

この時拡大縮小なり合成なりが必要であれば、drawBitmapの後ろ三つの引数にちゃんと値を設定してあげると。で、この結果、bitmap_aの内容は書き変わるし、この後も自分のコードの中でdrawなんちゃらで中身を書き換えられると。

そんな訳で、Bitmapに画像情報を入れるというのは常套手段のようでして、例えば端末内にある画像を読むのにも、MediaStore.Images.Media.getBitmap()という便利なのが用意されていて、こんな感じで読めます。

ContentResolver cont_reslv = activity.getContentResolver();
Uri image_uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Bitmap bitmap = MediaStore.Images.Media
		  .getBitmap(cont_reslv,
				  Uri.withAppendedPath(image_uri, 
				  image_ids[i]));

まぁActivity activity;とかString[] image_ids;は予め用意しとく必要はもちろんありますが。とにかく、ファイル操作とか意識する事なく、こんな感じで画像ファイルを読めます。ちなみにこの例はEXTERNAL_CONTENT_URIという事で外部ストレージ(Dev Phone1とかならmicro SD)にあるファイルを読む場合です。

写真サムネイルや、お絵描きソフトで描いた画像を読む場合はこれで行けるのですが、実はカメラで撮った写真をこれで読もうとするとメモリ不足で落ちてしまいます。ではどうするか。

ちなみにiPhone OSのUIImageだと画像サイズが1,000×1,000までに制限されていますし、imagePickerController:didFinishPickingImage:editingInfo:みたいなのでUIImageもらってきてもその画像サイズははじめから縮小されていますので、逆にそれが原因でメモリ不足に陥る事はないようになっています。

Androidの方はバックグラウンドで他のサービスも走ってるかも知れないとかの理由で、よりユーザー側に細かい制御をさせようという事なんでしょうか。いや、どういう事情か知りませんが。とにかく、画像を読む前に画像サイズを取得しておいてから、どの程度に縮小した画像を受け取るかを決めてから読む必要があります。具体的にはこんな感じのコードで。

Bitmap bitmap;
InputStream imgis;
BitmapFactory.Options bm_opt;
int zoomx, zoomy;

bm_opt = new BitmapFactory.Options();
imgis = _cont_reslv.openInputStream(Uri.withAppendedPath(image_uri, 
			  image_ids[j]));
bm_opt.inJustDecodeBounds = true;
bitmap = BitmapFactory.decodeStream(imgis, 
		null, bm_opt);
imgis.close();

zoomx = (int) Math.floor((double)bm_opt.outWidth / _width);
zoomy = (int) Math.floor((double)bm_opt.outHeight / _height);
bm_opt.inJustDecodeBounds = false;
bm_opt.inSampleSize = Math.min(zoomx, zoomy);
imgis = _cont_reslv.openInputStream(Uri.withAppendedPath(image_uri, 
			  image_ids[j]));
bitmap = BitmapFactory.decodeStream(imgis,
		null, bm_opt);
imgis.close();

bm_opt.inJustDecodeBounds = true / false ってのがミソでして、ここをtrueにしておくと実際にbitmapに中身を入れずにbm_opt.outWidth, bm_opt.outHeightに画像サイズを入れてくれます。後はその値を見て、必要な縮小率で画像を読み込めばいいと。

この例では _width×_height をすっぽり覆うようなギリギリ(とは言え整数値だけど)の大きさでそれを読み込んでます。まぁ、後、本当は先にbyte[]とかにimgisからの中身を読み込んでおいてからそれをByteArrayInputStreamにして再利用すると同じファイルを二回もopen/closeしなくて済むのですが、そこはこの例では端折ってます。てへ。

AgathaAgatha2011/10/01 12:37Haha. I woke up down today. You've cheeerd me up!

vvnbuwavvnbuwa2011/10/02 00:328WLzNG <a href="http://kjlpqljuwlrt.com/">kjlpqljuwlrt</a>

qvqxaydfqvqxaydf2011/10/02 22:04oDTMRf , [url=http://ppwlrjfiioer.com/]ppwlrjfiioer[/url], [link=http://grbyxbqcpkhx.com/]grbyxbqcpkhx[/link], http://xklleylptvvf.com/

qpecbyznqpecbyzn2011/10/03 20:323i4KCs <a href="http://bttlbisvfshe.com/">bttlbisvfshe</a>

vcrfyfvcrfyf2011/10/06 23:08zXzYEn , [url=http://lngyvleelqtv.com/]lngyvleelqtv[/url], [link=http://bgtclakwlzvq.com/]bgtclakwlzvq[/link], http://hgijqywgrtac.com/

xbszyblrloxbszyblrlo2014/12/03 03:35iryneboespje.efw, <a href="http://www.kfydoocdtn.com/">kqxsepdkqk</a> , [url=http://www.mmrqcyfcbh.com/]crujyytzvc[/url], http://www.ierldzbzbj.com/ kqxsepdkqk