tdnki @ ウィキ
FasterDrawing
最終更新:
tdnki
-
view
3. 描画の高速化
前回、Canvas#drawBitmap()が意外に遅いことがわかってしまった。
3-1. drawBitmap(Bitmap, float, float, Paint)を使う
このメソッドに、今まではintの配列を渡していたが、Bitmapを渡すオーバーロードを呼んでみたところ、int[]に比べて3倍ほど高速であった。
そこで、描画データはBitmapで持つように修正する。
そこで、描画データはBitmapで持つように修正する。
MainActivity.java
@Override protected void onResume() { : : // 描画用Bitmap previewBitmap = Bitmap.createBitmap(previewSize.width, previewSize.height, Bitmap.Config.ARGB_8888); : : } @Override protected void onPause() { super.onPause(); if (camera != null) { camera.stopPreview(); camera.release(); } if (previewBitmap != null) { previewBitmap.recycle(); } }
3-2. nativeコードでBitmapを扱う
int[]からBitmapを生成する処理もそこそこ重く、描画データをBitmapに変更することで浮くであろうマージンを食い潰してしまう。
幸いnativeからBitmapのピクセルデータに触る方法があるので、Bitmapをそのまま渡し、書き換える形に変更する。
C++がJavaのクラスを意識するのは気持ち悪いが、速度にはかえられない。
C++がJavaのクラスを意識するのは気持ち悪いが、速度にはかえられない。
ComicFinder.hpp
JNIEXPORT bool JNICALL Java_com_example_comicfinder_MainActivity_processImage (JNIEnv *, jobject ,jbyteArray, jobject, jint, jint);
ComicFinder.cpp
#include <stdlib.h> #include <android/bitmap.h> #include "ComicFinder.hpp" JNIEXPORT bool JNICALL Java_com_example_comicfinder_MainActivity_processImage (JNIEnv *env, jobject me, jbyteArray src, jobject dst, jint width, jint height) { int ret; unsigned char *p_dst; if ((ret = AndroidBitmap_lockPixels(env, dst, reinterpret_cast<void **>(&p_dst))) < 0) { return false; } unsigned char *p_src = reinterpret_cast<unsigned char *>(env->GetPrimitiveArrayCritical(src, NULL)); if (NULL == p_src) { AndroidBitmap_unlockPixels(env, dst); return false; } for (int k = 0; k < width*height; k++) { p_dst[k*4+0] = p_dst[k*4+1] = p_dst[k*4+2] = p_src[k]; p_dst[k*4+3] = 0xff; } env->ReleasePrimitiveArrayCritical(src, p_src, 0); AndroidBitmap_unlockPixels(env, dst); return true; }
jnigraphicsをリンクする。
Android.mk
LOCAL_LDLIBS := -ljnigraphics
3-3. まとめ
描画が10msで回るようになった。
ここまでのソース
ComicFinder.zip
添付ファイル