2013年7月6日土曜日

[Android] Android-NDK(JNI)で画像ファイルをデコードする

How to decode image files on JNI
前回 までにOpenGLとAndroid-NDK(JNI)で画像をテクスチャとして表示するアプリのソースをいくつか紹介させて頂きました。
前回はAndroid-SDK(Java)のAPIを使って画像ファイルをRBGのビットマップ配列にデコードし、JNIに渡す方法を使いました。

今回はAndroid-NDKを使ってJNIでSDカード内の画像ファイルをデコードする機能を作ってみました。

仕様は次の通りです。
1. JavaのコードからJNIに画像ファイルのパスを渡す。
2. JNIで画像ファイルをデコードしint配列のビットマップとしてJavaで受け取る。
3. int配列のビットマップをImageViewerに表示する。

JNI(C言語)で画像ファイルをデコードするため
http://nothings.org/
で公開されている stb_image.c を使いました。

stb_image.c はプロジェクトの
jni
フォルダーにコピーします。C言語のソースファイルやAndroid.mkと同じ場所です。


このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit)(XP互換モードで起動)
・Android SDK r21.0.1
・Cygwin
・Android-NDK-r8d

以下ソースです。

MainActivity.java

activity_main.xml (res/layoutフォルダー)

jni.cpp

Android.mk

※特別な権限(Permission)は不要なのでマニフェストは省略します。
Target SDK Version が4以上の設定でビルドできます。
Android1.6以降で動作します。
Android-NDKのビルド方法は環境に強く依存するので省略させて頂きます。

実行するとSDカードを検索して最初に見つけた画像を表示します。
ボタンをタップするたびに画像ファイルを見つけた順に表示します。
前回同様Anndroid2.xでは OutOfMemoryError が起きやすいです。改善の余地ありです。

JNIとJavaとで画像ファイルをint配列にデコードするまでの時間を比べてみました。
測定したのはONDA Vi30というAndroid4.1.1の中華Padです。
過去のベンチマークからVi30はthumbモードよりarmモードの方が速いことが分かっているのでarmモードでビルドしました。

画像のサイズ
JNI
Java
600 x 1024
82ms
189ms
950 x 483
62ms
82ms
1680 x 1050
199ms
257ms

全く同じ処理内容ではないので断言できませんがJNIの方が速そうです。

余談
JNIで画像の伸縮ができればJavaを使わずにOpen GLのテクスチャー用に加工することができるはずです。
前回 悩まされた OutOfMemoryError も減るはず、と思ったのですが残念ながらAndroid-NDKにはCanvas APIがありません。
とても難しそうですがいつかはチャレンジしてみたいと思います。

関連ブログ
[Android] OpenGLの簡易画像ビュアーをAndroid-NDKでビルドする (失敗談)
[Android] BitmapクラスのOutOfMemoryErrorを防ぐ
[Android] BitmapクラスのOutOfMemoryErrorを防ぐ #2
[Android] フリーサイズの画像をOpenGLのテクスチャに表示する
[Android] OpenGLで簡易画像ビュアーを作る
[Android] ジェスチャーでOpenGL簡易画像ビュアーに拡大縮小機能を追加する
[Android] OpenGLでプロ生ちゃんをアニメーションさせる
[Android] OpenGL ESで文字を表示する
[Android] OpenGLで頂点の多いポリゴンを扱うには
[Android] OpenGLでシャープ製端末用3D(立体視)アプリケーションを作る
[Blender] obj2opengl.plをJava用に改造する
[Windows8][Android] Can't bind to local 8600 for debugger

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

0 件のコメント:

コメントを投稿