2013年6月29日土曜日

[Android] OpenGLの簡易画像ビュアーをAndroid-NDKでビルドする (失敗談)

OpenGL and JNI
AndroidアプリをAndroid-NDKで開発するとネイティブコード(Javaインタープリターを通らないマシン語)で書かれたJNI(Java Native Interface)の動作比率を増やすことができ、Javaだけで開発したアプリに比べて高速な動作やバッテリーの長持ちが期待できます。
Android-NDKで開発するデメリットとして「マルチプラットフォーム(CPUが異なる端末)で動作しなくなる」という点があげられます。
Android-NDK-r8d では
・armeabi
・armeabi-v7a
・MIPS
・x86
の4種類のCPUがサポートされています。
PowerPC系のAndroid端末が普及しない限りマルチプラットフォームの心配はないようです。
そこで、 前回 公開したOpenGLによる簡易画像ビュアーをAndroid-NDKに移植してみました。

Android-NDKの弱点
アプリケーションのresフォルダーに保存された画像や音声ファイルを直接読み込む方法がありません。
SDカードに保存された画像ファイルなら読み込むことはできますが、画像をテクスチャに表示するためには画像ファイルをBitmap(1次元配列)にデコードする必要があります。
ところがAndroid-NDKには画像ファイルをデコードするライブラリーが見当たりません。
Android-NDKで画像を扱うには次の選択肢があります。

1. AndroidのJavaのAPIで画像ファイルをデコードしたint配列をJNIに渡す。
2. 画像ファイルをデコードする処理をC/C++で自作する。
3. C言語で書かれたオープンソースの画像ローダーを利用する。

デバッグのしやすさから1番目の方法で画像ファイルをNDKで扱うことにします。

留意点
Android端末の機種によりますが、ビットマップ画像の扱い中にOutOfMemoryErrorが起きやすいです。
SH-03C(Android2.2)は 1440x1440ピクセルの画像を int配列(約8MB)にバッファーしようとすると必ず次のエラーが発生します。
Out of memory on a 8294416-byte allocation.
試行錯誤した結果、今回は次のような仕様にしました。

1. Javaで画像ファイルを読み込み、512×512に伸縮する。
2. 伸縮した画像をint配列に変換しJNIに渡す。
3. JNIのOpenGL APIで画像をテクスチャとして表示する。

このブログを書いている時点の開発環境は次の通りです。
・Windows8 (64bit)
・Eclipse Juno (32bit) (XP互換モードで起動)
・Android SDK r21.0.1
・Cygwin
・Android-NDK-r8d
※Android-NDKのビルド方法は環境に強く依存するため省略します。

2点以上のタッチ操作が必要なので、Android2.2以降でマルチタッチ対応の端末が必要です
新品で発売されているAndroid端末なら、中華Padも含めてほぼど対応していると思います。

以下ソースです。

MainActivity.java
jni.cpp
glu.h (Android-NDKのsampleの com.example.SanAngeles から抜粋しました)
Android.mk
jni.cpp、glu.h、Android.mk はプロジェクトにjniというフォルダーを追加して、そこにコピーします。
※特別な権限(Permission)は不要なのでマニフェストは省略します。
Android2.2以降で動作します。
Target SDK Version が8以上の設定でビルドできます。
Android-NDKのビルド方法は環境に強く依存するので省略させて頂きます。

留意点でも書きましたが、古いスマートフォン(Android2.2以前)で実際に使ってみると 前回のJavaだけで作ったアプリに比べて
java.lang.OutOfMemoryError: bitmap size exceeds VM budget
が起きやすいです。
画像をint配列に変換するためのメモリーを確保したり、その逆の変換をするためのメモリーを確保したりするためメモリーの空き領域が不足がちになるようです。
さらにJavaだけで書いたアプリと体感速度を比べるても差がありませんでした。
当初の予想とは裏腹にデメリットの方が多かったのでタイトルに「失敗談」と付けました。

Android4.0なら安定して動作しますが体感速度は変わりません。

関連ブログ
[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


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

2013年6月22日土曜日

[Android] OpenGLの簡易画像ビュアーにSDカード内の画像を表示する

How to load the image files in a SD card

前回 はフリーサイズの画像を伸縮してOpenGL APIで表示するアプリを作りました。
このアプリはプロジェクトのリソースとして組み込んだ画像しか表示することができません。
今回はSDカードに保存されている画像をOpenGL APIで表示するアプリを作ります。
既に次の様な操作方法が実装済みです。
・スクロールで移動
・ピンチアウトで拡大
・ピンチインで縮小

SDカードには複数の画像ファイルが保存されているとし、一枚ずつ表示する画像を差し替えていきます。
画像を差し替える操作方法
・画面の左から右へ大きくスワイプしたら次の画像を表示
・画面の右から左へ大きくスワイプしたら前の画像を表示
とします。
画面の横幅の半分以上の距離をスワイプしたら画像を差し替える様にします。

画像の表示順は画像ファイル検索時に見つけた順です。
表示する画像の種類は拡張子が「.png」「.jpg」「.jpeg」「.gif」のファイルとします。拡張子の大文字小文字は区別しません。
隠しファイルに設定されている画像ファイルや隠しフォルダーに保存されている画像ファイルは表示しないことにします。

ところでAndroid端末のSDカードのパスは機種ごとに異なります
実際に手持ちの機種で調べたところメーカーごとに違うことを確認しています。
SDカードのパスを取得するに当たり
とむ・やむくんさんの 戌印-INUJIRUSHI- (Androidあれこれ)
http://inujirushi123.blog.fc2.com/blog-entry-30.html
を参考にさせて頂きました。

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

SDカード内の画像ファイルの検索は時間がかかるので AsyncTask を使います。
検索が完了したら最初に見つけた画像を表示します。

以下ソースです。

Activity(MainActivity.java)

※特別な権限(Permission)は不要なのでマニフェストは省略します。
Android2.2以降で動作します。
Target SDK Version が8以上の設定でビルドできます。

実行すると下の様になります。
本のページをめくるようにフリックするとスマートフォンのカメラ機能で撮影した画像や保存したスクリーンショットが次々と表示されます。

関連ブログ
[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

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

2013年6月15日土曜日

[Android] フリーサイズの画像をOpenGLのテクスチャに表示する

How to stretch and reduce images.
前回までに作ったOpenGLで簡易画像ビュアーの機能を強化します。
ピンチイン・ピンチアウトの認識とOpenGL ES 2.0 のAPIを利用するので、Android2.2以降でマルチタッチ対応の端末が必要です。

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

OpenGLで画像をテクスチャとして表示するためには、辺の長さが2の累乗(べき乗)の正方形である必要があります。
256×256ピクセル、512×512ピクセルなど。
このルールを守らないと端末によってはテクスチャが表示されないことがあります。

OpenGLの仕様とは言え、表示したい画像が全て正方形とは限りません。
今回は、縦と横のサイズが異なる画像を伸縮し、OpenGLで表示できる様にします。
そして1画面に2枚の画像を表示します。

300×200ピクセルの orientation.png


200×300ピクセルの portrait.png

二つの画像ファイルをプロジェクトの
res - drawable-mdpi
にコピーします。
resフォルダーの下に drawable-nodpi というフォルダーを作ってそこに画像ファイルをコピーしてさい
drawable-nodpi 以外のフォルダーに保存した画像は端末の解像度に応じて自動でスケーリングされるようです。(2014年5月31日訂正)
※ ic_launcher.png はAndroid-SDKのデフォルトでインストールされるアイコン画像です。

フリーサイズの画像をテクスチャに表示するため伸縮させ正方形に納めます。余白は透明のピクセルで埋めます。

伸縮させた画像がギザギザにならないようにMatrixを使ってアンチエイリアス処理をします

Activity(MainActivity.java) ※公開後、数カ所の不具合を発見したので修正させて頂きました。(2013年6月15日)

※特別な権限(Permission)は不要なのでマニフェストは省略します。
Android2.2以降で動作します。
Target SDK Version が8以上の設定でビルドできます。

実行するとこんな感じになります。

横長・縦長の画像を正方形のポリゴンにテクスチャとして表示しています。

前回のソースを元にしているのでフリックで移動、ピンチアウト・ピンチインで拡大縮小ができます。

関連ブログ
[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

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

2013年6月13日木曜日

[Application] アンドロイダー様制作のEye元気!2紹介動画が公開されました

アンドロイダー様 https://androider.jp/ にて制作されたEye元気!2の紹介動画がYoutubeにて公開されました。

アプリを紹介しているのは「アイドル社員種ちゃん」の宮元 詩乃さんです。
宮元 詩乃さんのFacebookはこちら
https://www.facebook.com/shino.tane.miyamoto

ストレッチからエクササイズまで Eye元気!2

ありがとうございます!

Eye元気!2はPlayストアから無料でダウンロードできます。
https://play.google.com/store/apps/details?id=jp.fujiu.eye_genki2
※ダウンロード前に エンドユーザーライセンス契約(EULA)プライバシーポリシー を必ずお読みください。


2013年6月9日日曜日

[Application] Eye元気!2/Vigorous eyes!2 v1.06を公開しました

Androidアプリケーション Eye元気!2/Vigorous eyes!2 をバージョンアップしました。
V1.06 バージョンアップ内容
重音テトの「二の腕のエクササイズ」 追加
ボディラインが気になる方やメタボが心配な方におすすめです

The exercise forupper arms (KASANE TETO) appended
위팔을 위한 엑서사이즈 (카사 네 테토) 추가

Eye元気!2はツボマッサージなどのストレッチを支援するAndroidアプリケーションです。
目の健康を守るお手伝いをします。
スマートフォンやパソコンを使うと目が疲れます。疲労がたまれば頭痛やめまいを感じたり首や肩が凝ります。
Eye元気!2を使えば、1分ほどでストレッチすることができます。
症状にあったストレッチを朝晩1~2セットずつ行って、目の疲れを癒し頭痛・めまい・肩凝り・腰痛を予防しましょう。
ボディラインが気になる方やメタボが心配な方にもおすすめです。
ぜひEye元気!2をご活用ください。
VOCALOIDやUTAUのの初音ミク・鏡音リン/レン・巡音ルカ・GUMI(メグッポイド)・SeeU・KAITO・亞北ネル・弱音ハク・重音テトが音声や振動でストレッチをご案内します。

Android1.6以上対応、QVGA以上の解像度推奨。
価格は無料。
※SDカードへの移動はAndroid2.2以降に対応。


Eye元気!2はPlayストアから無料でダウンロードできます。
https://play.google.com/store/apps/details?id=jp.fujiu.eye_genki2
※ダウンロード前に エンドユーザーライセンス契約(EULA)プライバシーポリシー を必ずお読みください。

Eye元気!2/Vigorous eyes!2 の詳細はこちらからご覧いただけます。
http://fujiu.jp/AndroidApp/app009_eyegenki2.html

※アンドロイダー公認アプリです。
https://androider.jp/official/app/4f09c53030a63a82/

"Vigorous eyes!2" supports stretching with the TSUBO massage and exercise.
VOCALOID and UTAU characters will guide you.
Attention: If you feel bad, stop stretching.
Casting VOCALOIDs: HATSUNE MIKU, KAGAMINE RIN, KAGAMINE LEN, MEGURINE LUKA, GUM(Megpoid), SeeU, KAITO, AKITA NERU, YOWANE HAKU, KASANE TETO

"Eye 건강!2" 는 경혈안마 스트레칭을 지원합니다
VOCALOID와 UTAU가 안내합니다
주의: 몸상태가 좋지 않다 때는 중지하십시오
출연 VOCALOID・UTAU :하츠네 미쿠・카가 미네 린・카가 미네 렌・메구 리네 루카・구미(메굿포이드)・시유・카이토・아키타 네루・요와네 하쿠・카사 네 테토

使用したMMDモデル
・Lat式 初音ミク
・508式 鏡音リン/鏡音レン
・ula式 巡音ルカ
・ままま式 GUMI(メグッポイド)
・hzero式 KAITO
・Ki式 亞北ネル
・キオ式 弱音ハク
・ななみ式 重音テト
・無駄P式ソファー
・esukuremento式 iPhone4改
Copyright (C) CRYPTON FUTURE MEDIA, INC. All Rights Reserved.
Copyrignt (C) INTERNET Co., Ltd. All rights reserved.
Copyright (C) SBSARTECH. All rights reserved.
Copyright (C) CAFFEIN All rights reserved.
Copyright (C) 線 All rights reserved.
Copyright (C) 小山乃舞世 All rights reserved.

このアプリケーションはピアプロ・キャラクター・ライセンスに基づいてクリプトン・フューチャー・メディア株式会社のキャラクター「初音ミク」「鏡音レン」「鏡音リン」「巡音ルカ」「KAITO」、依拠して制作されたキャラクター「亞北ネル」「弱音ハク」、「線」のビジュアルデザインによるキャラクター「重音テト」を描いた画像を使用しています。

2013年6月8日土曜日

[Android] ジェスチャーでOpenGL簡易画像ビュアーに拡大縮小機能を追加する

How to enlarge and reduce images on gestures
前回前々回はOpenGL APIを使って画像を表示するアプリを作りました。
今回はジェスチャーのピンチイン・ピンチアウトの操作で画像を拡大縮小する機能を追加します。

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

2点以上のタッチ操作が必要なので、Android2.2以降でマルチタッチ対応の端末が必要です
新品で発売されているAndroid端末なら中華Padも含めてほぼ対応していると思います。
Android2.2以降を対象にするため、OpenGL ES 2.0 のAPIも利用します。

画像は前々回と同じ256×256ピクセルのものを使います。


画像ファイル(image256x256.png)はプロジェクトの
res - drawable-mdpi
にコピーします。
resフォルダーの下に drawable-nodpi というフォルダーを作ってそこに画像ファイルをコピーしてさい
drawable-nodpi 以外のフォルダーに保存した画像は端末の解像度に応じて自動でスケーリングされるようです。(2014年5月31日訂正)

※ ic_launcher.png はAndroid-SDKにデフォルトでインストールされるアイコン画像です。

ピンチイン・ピンチアウトの操作に対応させるため OnScaleGestureListener インターフェイスを継承します。
※特別な権限(Permission)は不要なのでマニフェストは省略します。
Target SDK Version が8以上の設定でビルドできます。

Activityクラス (MainActivity.java)

画像を拡大縮小するに当たり GLU.gluPerspective の視野角を変化させます。

なぜ拡大縮小に視野角を利用したか
将来、複数の画像を表示させたいと思ってます。
複数の画像を並べて表示し拡大縮小した場合、それぞれの画像の位置関係を保ったまま画像を拡大縮小したように見せるためです。
拡大縮小の処理をそれぞれの画像のサイズを変える方法では、拡大した複数の画像が重ならない様に位置を調整する必要があり処理が複雑になってしまいます。
描く画像の位置関係を保ったまま拡大縮小した様に見せるため、視野角を変化させる方法を採用しました。
ただし視野角を変化させると立体的な見え方が不自然になることがあります。
このアプリは平面を表示するだけなので視野角を変化させても弊害はありません。
視野角を変化させるほか、カメラの位置を近づけたり遠ざけたりする方法もいいと思います。

OpenGL ES 2.0 のAPIである GLES20.glTexParameteri を使ってテクスチャーの表示方法をClipに指定します。

Android2.2にバージョンアップしたdocomoのSH-03C(シャープ)で動作確認しました。
フリックで移動、ピンチアウトで拡大、ピンチインで縮小です。

これで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

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