之前接觸 Renderscript - HelloCompute 時,第一次了解 Mono 特效是怎樣做的。這次則是要來筆記純用 Java 和 NDK 作的方式。
環境概述(以 Renderscript - HelloCompute 架構為例):
private Bitmap mBitmapIn;
private Bitmap mBitmapOut;
private Bitmap loadBitmap(int resource) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
return BitmapFactory.decodeResource(getResources(), resource, options);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
...
mBitmapIn = loadBitmap(R.drawable.data); // R.drawable.data 是一張圖片
mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(), mBitmapIn.getConfig()); // 空資料,大小跟 mBitmapIn 一樣
...
// doMonoByJava(); // use Java only
// doMonoByNDK(); // use NDK
// createScript(); // use Renderscript
...
}
純 Java 版:
private void doMonoByJava() {
final float gMonoMult[] = {0.299f, 0.587f, 0.114f};
int imageHeight = mBitmapIn.getHeight();
int imageWidth = mBitmapIn.getWidth();
/* only assign, 速度慢
for( int i=0 ;i<imageWidth; ++i )
for( int j=0;j<imageHeight; ++j)
mBitmapOut.setPixel(i, j, mBitmapIn.getPixel(i, j));
*/
/* only assign, 速度快
int[] pixels = new int[imageWidth*imageHeight];
mBitmapIn.getPixels(pixels,0,imageWidth,0,0,imageWidth,imageHeight);
mBitmapOut.setPixels(pixels, 0, imageWidth, 0, 0, imageWidth, imageHeight);
*/
int[] pixels = new int[imageWidth*imageHeight];
mBitmapIn.getPixels(pixels,0,imageWidth,0,0,imageWidth,imageHeight);
for( int i=0 ; i<imageHeight*imageWidth ; ++i ) {
int R = (pixels[i] >> 16) & 0xff;
int G = (pixels[i] >> 8) & 0xff;
int B = pixels[i] & 0xff;
int m = (int)((float)R*gMonoMult[0] + (float)G*gMonoMult[1] + (float)B*gMonoMult[2] );
R = m;
G = m;
B = m;
pixels[i] = 0xff000000 | (R << 16) | (G << 8) | B;
}
mBitmapOut.setPixels(pixels, 0, imageWidth, 0, 0, imageWidth, imageHeight);
}
使用 NDK 版:
HelloCompute.java:
package com.example.android.rs.hellocompute;
public class HelloCompute extends Activity {
...
static {
System.loadLibrary("my-jni");
}
public native void doByNDK( int [] pixels, int size);
private void doMonoByNDK() {
int imageHeight = mBitmapIn.getHeight();
int imageWidth = mBitmapIn.getWidth();
int size = imageWidth*imageHeight;
int[] pixels = new int[size];
mBitmapIn.getPixels(pixels,0,imageWidth,0,0,imageWidth,imageHeight);
doByNDK(pixels,size);
mBitmapOut.setPixels(pixels, 0, imageWidth, 0, 0, imageWidth, imageHeight);
}
...
}
my-jni.c:
#include <jni.h>
void Java_com_example_android_rs_hellocompute_HelloCompute_doByNDK( JNIEnv* env, jobject thiz, jintArray pixels, jint size) {
float gMonoMult[] = {0.299f, 0.587f, 0.114f};
int i, R, G, B, m;
jboolean isCopy = JNI_FALSE;
jint *jpixels = (*env)->GetIntArrayElements(env, pixels, &isCopy);
for(i=0 ; i<size ; ++i ) {
R = (jpixels[i] >> 16) & 0xff; //bitwise shifting
G = (jpixels[i] >> 8) & 0xff;
B = jpixels[i] & 0xff;
m = (int)((float)R*gMonoMult[0] + (float)G*gMonoMult[1] + (float)B*gMonoMult[2] );
R = m;
G = m;
B = m;
jpixels[i] = 0xff000000 | (R << 16) | (G << 8) | B;
}
}
若要計算效率,可以再用這段程式碼:
Long timeCost = System.currentTimeMillis();
// do something ...
timeCost = System.currentTimeMillis() - timeCost;
System.out.println("Cost:"+timeCost);
沒有留言:
張貼留言