2015年2月15日日曜日

Androidアプリからスクリーンショット /system/bin/screencap


前回に続きスクリーンショットについてです。

/system/bin/screencap -p test.png

前回は上記のように-pオプションを付けて実行し、ファイルの拡張子も.pngにしていたので、pngファイルで保存されていました。

普通の用途ではそれでいいんだと思いますが、今回は訳あって1200ミリ秒ぐらいの中で全部やりたいので、時間的にギリギリです。

そこで、pngへの変換を省いて生のBitmap画像を得る方法について実験します。


/system/bin/screencapコマンドについては、pオプションやファイル名を指定せずに実行すると、いわゆるフレームバッファの生データが標準出力に出力されます。

データのはじめにはwidth、height、formatの各4byteで12byteのヘッダが付いてくるそうです。

とりあえずヘッダの中身を見てみます。

 2684682240
 655360
 16777216

うーん、まったく意味が分からない。。
実際のwidthやheightで割ってみても意味のありそうな数字になりません。

LITTLE_ENDIANで読み直してみます。

 1440
 2560
 1

これだ!

そしてその後には14,745,600byteのデータが飛んできました。

Nexus6で実験しているので、画面サイズは縦×横が2,560×1,440です。

2560 * 1440 = 3686400

14745600 / 3686400 = 4

1ピクセルあたり4byteということは、普通に考えれば32bitということでしょうか。
ただ、ネットで調べると16bitのダブルバッファリングだという説があったので、適当に16bitのヘッダを付加して表示してみます。

はい。ぜんぜんダメでした。

素直に32bitのヘッダを付加してみます。

上下が逆転しています。

Bitmapのデータはなぜか左下から右方向に向かって格納されているそうなのですが、フレームバッファには普通に並んでいるので、byte配列を逆さにしてからBitmapに食わせます。

色情報の順番も変わってしまいました。また、左右は入れ替えなくて良いようです。

行単位で逆にします。

まだちょっと色がおかしい。
どうやらRとBが逆になっているようですね。

このサンプルだと分かりにくいのでもう少しカラフルなサンプルでRとBを入れ替えると。

完成。


正体の良く分からないバイナリをいい感じに加工して読めるデータにする作業って、何か高度なパズルを解いているようで楽しいです。

まぁちゃんと調べれば正体は分かるんでしょうけど。。


0 コメント:

コメントを投稿