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

2008-12-22

ネイティブ

16:17

こちらをそのまま参考に。

http://android-dev.g.hatena.ne.jp/takuma104/20081219

例によってMacでビルドできないか試行錯誤してみたのですが、「どの方法も既に他の人が通った(そして失敗した)道」だという事がわかっただけでした。

コマンドラインからのビルドであれば手元のマシンで実行する必要そもそもないので、ちょっと遠くにdebianサーバがあったのを思い出して、そっちでtakuma104さんのと同じ方法で環境構築。sudo apt-get update; sudo apt-get dist-upgradeでsudo apt-get install emdebian-toolsしてからsudo emsetup --arch armelというところは全く同じ。まぁ既にetchで稼動していてdist-upgradeとかに時間がかかったというのはありますが。

http://android-dev.g.hatena.ne.jp/takuma104/20081219/1229695594

ただ、

sakira:tmp sakira$ adb push a.out data/hello
failed to copy 'a.out' to 'data/hello': Permission denied

なんじゃいおりゃー。adb shell して su しようとしても permission denied だし。やっぱりsdcardの上では066とかいうパーミッションだし。

$ cd data
$ ls
opendir failed, Permission denied
$ mkdir /data/tmp
mkdir failed for /data/tmp, Permission denied

うーん、さすがにDev Phoneとは違う。こんな小手先のはダメか。

ただ、

$ ls -l /
drwxrwxrwt root     root              2008-12-22 15:54 sqlite_stmt_journals
drwxrwx--- system   cache             2008-11-30 23:09 cache
d---rwxrwx system   system            2008-12-22 15:49 sdcard
lrwxrwxrwx root     root              2008-12-22 00:22 etc -> /system/etc
-rwxr-x--- root     root        98260 1970-01-01 09:00 init
-rw-r--r-- root     root           93 1970-01-01 09:00 default.prop
-rw-r--r-- root     root        11336 1970-01-01 09:00 logo.rle
-rwxr-x--- root     root         1347 1970-01-01 09:00 init.trout.rc
drwxr-xr-x root     root              2008-09-13 16:13 system
drwxrwx--x system   system            2008-11-30 23:10 data
drwxr-xr-x root     root              1970-01-01 09:00 sys
dr-xr-xr-x root     root              1970-01-01 09:00 proc
-rwxr-x--- root     root         1564 1970-01-01 09:00 init.goldfish.rc
-rwxr-x--- root     root         8630 1970-01-01 09:00 init.rc
drwxr-x--- root     root              1970-01-01 09:00 sbin
drwx------ root     root              1970-01-01 09:00 root
drwxr-xr-x root     root              2008-12-22 00:22 dev

という事で、sqlite_stmt_journalsってのが使っちゃいけないっぽいけど、ちょっと魅惑的。なので、

sakira:tmp sakira$ adb push a.out sqlite_stmt_journals/hello
887 KB/s (551292 bytes in 0.606s)

として、adb shellの中で実行。

$ /sqlite_stmt_journals/hello
hello!!

行けたっぽいですねー。わーい。

BusyBoxも

16:33

http://android-dev.g.hatena.ne.jp/takuma104/20081219/1229707664

の手順を何も考えずに実行してsqlite_stmt_journalsに置いたら行けました。ただ、当然ですが ./busybox su とかが効く訳でもなく、

$ ./busybox df -h
Filesystem                Size      Used Available Use% Mounted on
tmpfs                    48.4M         0     48.4M   0% /dev
tmpfs                     4.0M      2.8M      1.2M  71% /sqlite_stmt_journals
/dev/block/mtdblock3     67.5M     63.4M      4.1M  94% /system
/dev/block/mtdblock5     74.8M     38.3M     36.4M  51% /data
/dev/block/mtdblock4     67.5M      1.1M     66.4M   2% /cache
/dev/block/mmcblk0p1      3.8G     72.6M      3.7G   2% /sdcard

の通り、このディレクトリってtmpfsなんですねー。うーん。

/data/localは使えるらしい

18:09

またadb shellで遊んでます。こんな感じで/data/local/はファイルシステムもまともっぽいし、書き込みもできるようです。

$ ls -l /sdcard/
d---rwxrwx system   system            2008-12-04 22:53 rerware
d---rwxrwx system   system            2008-12-04 13:54 albumthumbs
d---rwxrwx system   system            2008-12-04 22:53 atweeter
d---rwxrwx system   system            2008-12-04 22:53 com
d---rwxrwx system   system            2008-12-10 22:47 dcim
d---rwxrwx system   system            2008-12-17 00:43 download
d---rwxrwx system   system            2008-12-04 22:53 Music
----rw-rw- system   system         16 2008-12-21 15:15 a.txt
----rw-rw- system   system     551292 2008-12-22 15:49 hello
$ cd /data/local/
$ cat /sdcard/hello > ./hello
$ ls -l
-rw-rw-rw- shell    shell      551292 2008-12-22 18:03 hello
drwxrwx--x shell    shell             2008-11-30 23:10 tmp
$ chmod +x hello
Bad mode
$ chmod 777 hello
$ ls -l
-rwxrwxrwx shell    shell      551292 2008-12-22 18:03 hello
drwxrwx--x shell    shell             2008-11-30 23:10 tmp
$ ./hello
hello!!

MarijaMarija2012/08/14 09:41That's a well-thought-out answer to a challenging qetuison

NasrulNasrul2012/08/14 09:42Heck yeah bay-bee keep them comnig!

fjunqieefjunqiee2012/08/14 23:17aEVVRB <a href="http://bdmmqlqcwape.com/">bdmmqlqcwape</a>

qmbpibqmbpib2012/08/15 03:51b9ESG4 , [url=http://vmsnomfeukkx.com/]vmsnomfeukkx[/url], [link=http://rfjguntiehcm.com/]rfjguntiehcm[/link], http://wrksisseoltx.com/

lyobdoszzklyobdoszzk2012/08/16 13:21QYSmGp <a href="http://vzamqtchnodw.com/">vzamqtchnodw</a>

2008-12-20

はてなダイアリーの方に書いてあったやつ

22:08

へのリンクをとりあえず並べておきます。…と思ったけど一つしかまだ書いてなかったです。

http://d.hatena.ne.jp/sakira09/20081206#1228580027

ではあんまりなので

22:32

アプリケーションの終了時にファイルに書いて、次回起動時に読み込む部分を。本当なら面倒なので(ぉぃ) preferences の中にPNGなりのデータを入れたかったのだけど、やりかたがよくわからなかったので自分の書いていい場所(iPhone OSなら ~/Documents/ みたいなとこかな?)にファイルとしてPNGを書くようにしました。

	void savePreferences() {
		SharedPreferences pref = getPreferences(0);
		SharedPreferences.Editor editor = pref.edit();
		editor.putInt(keyAPLayerNumber, APView.LayerNumber);
		editor.commit();
		
		OutputStream ostream;
		for (int li = 0; li < APView.LayerNumber; li ++) {
			try {
				ostream = openFileOutput(imageStateKeyName(li), 0);
				_view.outputPNG(li, ostream);
				ostream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	void loadPreferences() {
		InputStream istream;
		for (int li = 0; li < APView.LayerNumber; li ++) {
			try {
				istream = openFileInput(imageStateKeyName(li));
				_view.inputImage(li, istream);
				istream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		_view.clear_pen_layer();
		_view.change_layer(0);
	}

いや、この説明不足もひどいか... まぁおいおいちゃんとした記事も書いていこうと思いますのでご勘弁を。

CandyCandy2011/09/29 18:18Why does this have to be the ONLY reilbale source? Oh well, gj!

lqplfdisdxylqplfdisdxy2011/09/30 03:021f2QuW <a href="http://bvizaeihheyo.com/">bvizaeihheyo</a>

gwprieoygwprieoy2011/10/03 20:16bKl768 <a href="http://yodvbhnzxsnm.com/">yodvbhnzxsnm</a>

cuviofxcuviofx2011/10/06 01:09bH9tH2 , [url=http://mpumknxrwjcr.com/]mpumknxrwjcr[/url], [link=http://ymglepeynajm.com/]ymglepeynajm[/link], http://jqjkafwkhctz.com/

BethaBetha2012/10/30 17:59This is a most useful cntoribution to the debate

fedjzlnfedjzln2012/10/31 00:14F9zJPS <a href="http://hojzlzcmpnzd.com/">hojzlzcmpnzd</a>

bwotctstbwotctst2012/11/01 06:19jmv3cl , [url=http://rrcacklmybme.com/]rrcacklmybme[/url], [link=http://zswqmdiamwua.com/]zswqmdiamwua[/link], http://gqykgwkielpv.com/

ghmmshnghmmshn2012/11/01 12:56NNpfpy <a href="http://idepmnpgujzw.com/">idepmnpgujzw</a>

iobevzdgsvciobevzdgsvc2012/11/02 01:45KOAfSw , [url=http://amorgtqzlmek.com/]amorgtqzlmek[/url], [link=http://tzmilyvkfrxe.com/]tzmilyvkfrxe[/link], http://heurxouiiack.com/