3

私はアンドロイドの画像に水彩画の効果のためのいくつかのコードを実装しましたが、それは遅くなりました(2分以上かかります)今私はバッタースピードのためにこれをJNIに実装しようとします、聞いて私のJavaコードは

inPixelsはビットマップのピクセルです。

 protected int[] filterPixels( int width, int height, int[] inPixels ) 
    {
        int levels = 256;
        int index = 0;

        int[] rHistogram = new int[levels];
        int[] gHistogram = new int[levels];
        int[] bHistogram = new int[levels];
        int[] rTotal = new int[levels];
        int[] gTotal = new int[levels];
        int[] bTotal = new int[levels];
        int[] outPixels = new int[width * height];

        for (int y = 0; y < height; y++) 
        {
            for (int x = 0; x < width; x++) 
            {
                for (int i = 0; i < levels; i++)
                    rHistogram[i] = gHistogram[i] = bHistogram[i] = rTotal[i] = gTotal[i] = bTotal[i] = 0;

                for (int row = -range; row <= range; row++) 
                {
                    int iy = y+row;
                    int ioffset;
                    if (0 <= iy && iy < height) 
                    {
                        ioffset = iy*width;
                        for (int col = -range; col <= range; col++) 
                        {
                            int ix = x+col;
                            if (0 <= ix && ix < width) {
                                int rgb = inPixels[ioffset+ix];
                                int r = (rgb >> 16) & 0xff;
                                int g = (rgb >> 8) & 0xff;
                                int b = rgb & 0xff;
                                int ri = r*levels/256;
                                int gi = g*levels/256;
                                int bi = b*levels/256;
                                rTotal[ri] += r;
                                gTotal[gi] += g;
                                bTotal[bi] += b;
                                rHistogram[ri]++;
                                gHistogram[gi]++;
                                bHistogram[bi]++;
                            }
                        }
                    }
                }

                int r = 0, g = 0, b = 0;
                for (int i = 1; i < levels; i++) 
                {
                    if (rHistogram[i] > rHistogram[r])
                        r = i;
                    if (gHistogram[i] > gHistogram[g])
                        g = i;
                    if (bHistogram[i] > bHistogram[b])
                        b = i;
                }
                r = rTotal[r] / rHistogram[r];
                g = gTotal[g] / gHistogram[g];
                b = bTotal[b] / bHistogram[b];
                outPixels[index] = (inPixels[index] & 0xff000000) | ( r << 16 ) | ( g << 8 ) | b;
                index++;
            }
        }

        return outPixels;
    }

**出力画像** ここに画像の説明を入力してください

javaそして私はこのコードをコードに変換しようとしcますが、私は何が間違っているのかわかりません、C

 void filterPixels( int width, int height, int inPixels[] )
    {



        int levels = 256;
        int index = 0;

        int rHistogram [levels];
        int gHistogram [levels];
        int bHistogram [levels];
        int rTotal   [levels];
        int gTotal [levels];
        int bTotal [levels];
        int outPixels [width * height];

        //Loop Variables
        int y ;
        int x ;
        int i ;
        int row ;
        int col ;
        int j ;

        int range = 5 ;

        for ( y = 0; y < height; y++)
        {
            for ( x = 0; x < width; x++)
            {
                for ( i = 0; i < levels; i++)
                    rHistogram[i] = gHistogram[i] = bHistogram[i] = rTotal[i] = gTotal[i] = bTotal[i] = 0;

                for ( row = -range; row <= range; row++)
                {
                    int iy = y+row;
                    int ioffset;
                    if (0 <= iy && iy < height)
                    {
                        ioffset = iy*width;
                        for ( col = -range; col <= range; col++)
                        {
                            int ix = x+col;
                            if (0 <= ix && ix < width) {
                                int rgb = inPixels[ioffset+ix];
                                int r = (rgb >> 16) & 0xff;
                                int g = (rgb >> 8) & 0xff;
                                int b = rgb & 0xff;
                                int ri = r*levels/256;
                                int gi = g*levels/256;
                                int bi = b*levels/256;
                                rTotal[ri] += r;
                                gTotal[gi] += g;
                                bTotal[bi] += b;
                                rHistogram[ri]++;
                                gHistogram[gi]++;
                                bHistogram[bi]++;
                            }
                        }
                    }
                }

                int r = 0, g = 0, b = 0;
                for ( j = 1; j < levels; j++)
                {
                    if (rHistogram[j] > rHistogram[r])
                        r = j;
                    if (gHistogram[j] > gHistogram[g])
                        g = j;
                    if (bHistogram[j] > bHistogram[b])
                        b = j;
                }
                r = rTotal[r] / rHistogram[r];
                g = gTotal[g] / gHistogram[g];
                b = bTotal[b] / bHistogram[b];
                outPixels[index] = (inPixels[index] & 0xff000000) | ( r << 16 ) | ( g << 8 ) | b;
                index++;
            }
        }
    }

javaコードのピクセル値をチェックし、cコードは両方とも同じです(同じ画像の場合)

私のAndroidアクティビティからネイティブ関数を呼び出すためのコード。

int[] pix = new int[oraginal.getWidth() * oraginal.getHeight()];

                Bitmap bitmap = oraginal.copy(oraginal.getConfig(), true);
                bitmap.getPixels(pix, 0, bitmap.getWidth(), 0, 0,bitmap.getWidth(), bitmap.getHeight());
                filterPixelsJNI(bitmap.getWidth(), bitmap.getHeight(), pix);

                 bitmap.setPixels(pix, 0, bitmap.getWidth(), 0, 0,bitmap.getWidth(), bitmap.getHeight());
                 myView.setImageBitmap(bitmap);

これはJNIの私の最初の試みなので、plzはこれで私を助けてくれます。

アップデート

public native void filterPixelsJNI( int width, int height, int inPixels[] );

JNI

 JNIEXPORT void JNICALL Java_com_testndk_HelloWorldActivity_filterPixelsJNI (JNIEnv * env, jobject obj , jint width,jint height,jint inPixels[]){

     filterPixels( width, height, inPixels);
 }

filterPixelsメソッドwitchはcコードから呼び出されます。

4

1 に答える 1

2

JNIコードにはいくつかの問題があります。アルゴリズムの部分はおそらく正しいですが、Java配列からC配列への変換を正しく処理していません。

まず、の最後の引数は、タイプではなくJava_com_testndk_HelloWorldActivity_filterPixelsJNI、タイプである必要があります。これは、Java配列をCコードに渡す方法です。jintArrayjint []

この配列を取得すると、直接処理することはできません。C配列に変換する必要があります。

JNIEXPORT void JNICALL Java_com_testndk_HelloWorldActivity_filterPixelsJNI (JNIEnv * env, jobject obj , jint width, jint height, jintArray inPixels) {

    int *c_inPixels = (*env)->GetIntArrayElements(env, inPixels, NULL);
    filterPixels( width, height, c_inPixels);
    // passing 0 as the last argument should copy native array to Java array
    (*env)->ReleaseIntArrayElements(env, inPixels, c_inPixels, 0);
}

配列の処理方法を説明しているJNIドキュメントを参照することをお勧めします:http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html

AndroidNDKを使用してJavaビットマップオブジェクトを処理する簡単な方法があることに注意してください。詳細については、ここにある他の私の回答を参照してください。

于 2012-11-26T10:59:21.080 に答える