tw.study.rs_screenout

之前接觸 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);


, , , , , , ,

changyy 發表在 痞客邦 PIXNET 留言(0) 人氣()