深刻了解android平臺的jni---圖像灰度化處理

1、涉及到的jni編程知識
Java基本類型的數組,在JNI中都是jArray的類型格式。具體類型以下:
typedef jarray jbooleanArray;
typedef jarray jbyteArray;
typedef jarray jcharArray;
typedef jarray jshortArray;
typedef jarray jintArray;
typedef jarray jlongArray;
typedef jarray jfloatArray;
typedef jarray jdoubleArray;
typedef jarray jobjectArray;
jArray類型JNI定義的類型,經過它JNIEnv能夠操做Java數組,但它並非C/C++的數組,因此咱們要把jArray類型轉換爲C/C++中的數組。
JNIEnv定義了一系列的方法來把一個jArray類型轉換爲C/C++數組,和把C/C++數組轉換爲jArray
一、Java基本類型的數組轉換成相應的C數組類型 
    jboolean*   (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*);
    jbyte*      (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*);
    jchar*      (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*);
    jshort*     (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*);
    jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
    jlong*      (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*);
    jfloat*     (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*);
    jdouble*    (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);
參數:
env:JNI 接口指針。        
array:Java 字符串對象。        
isCopy:指向布爾值的指針。        
返回值:        
返回指向數組元素的指針,若是操做失敗,則爲 NULL。
二、獲取數組的長度:
     jsize       (*GetArrayLength)(JNIEnv*, jarray);
三、釋放C/C++的數組內存
     void        (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray,jboolean*, jint); 
     void        (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray,jbyte*, jint);
     void        (*ReleaseCharArrayElements)(JNIEnv*, jcharArray,jchar*, jint);
     void        (*ReleaseShortArrayElements)(JNIEnv*, jshortArray,jshort*, jint);
     void        (*ReleaseIntArrayElements)(JNIEnv*, jintArray,jint*, jint);
     void        (*ReleaseLongArrayElements)(JNIEnv*, jlongArray,jlong*, jint);
     void        (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray,jfloat*, jint);
     void        (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray,jdouble*, jint);
參數:        
env:JNI 接口指針。        
array:Java 數組對象。        
elems:指向數組元素的指針。        
mode:釋放模式。
四、構造一個指定長度的Java基本類型的數組
     jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize);
     jbyteArray    (*NewByteArray)(JNIEnv*, jsize);
     jcharArray    (*NewCharArray)(JNIEnv*, jsize);
     jshortArray   (*NewShortArray)(JNIEnv*, jsize);
     jintArray     (*NewIntArray)(JNIEnv*, jsize);
     jlongArray    (*NewLongArray)(JNIEnv*, jsize);
     jfloatArray   (*NewFloatArray)(JNIEnv*, jsize);
     jdoubleArray  (*NewDoubleArray)(JNIEnv*, jsize); 
五、給java基本類型的數組賦值
     void  (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,jsize, jsize, const jboolean*);
     void  (*SetByteArrayRegion)(JNIEnv*, jbyteArray,jsize, jsize, const jbyte*);
     void  (*SetCharArrayRegion)(JNIEnv*, jcharArray,jsize, jsize, const jchar*);
     void  (*SetShortArrayRegion)(JNIEnv*, jshortArray,jsize, jsize, const jshort*);
     void  (*SetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, const jint*);
     void  (*SetLongArrayRegion)(JNIEnv*, jlongArray,jsize, jsize, const jlong*);
     void  (*SetFloatArrayRegion)(JNIEnv*, jfloatArray,jsize, jsize, const jfloat*);
     void  (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray, jsize, jsize, const jdouble*); 
把java基本類型的數組中的指定範圍的元素用C/C++的數組中的元素來賦值
參數:        
env:JNI 接口指針。        
array:  Java 數組。        
start:起始下標。        
len:要複製的元素數。        
buf:源緩衝區。        
拋出:        
ArrayIndexOutOfBoundsException:若是區域中的某個下標無效。
注意:
若是是c程序,要用 (*env)-> 
若是是C++要用 env->
在linux下若是.c文件中用 「env->」 編譯會找不到此結構,必須用「(*env)->」,或者改爲.cpp文件,以 c++的方式來編譯。
具體請看一下jni.h的代碼。另外還有些省略的內容,能夠參考JNI的文檔:Java Native Interface 6.0 Specification,在JDK的文檔裏就能夠找到。若是要進行更深刻的JNI編程,須要仔細閱讀這個文檔
 
2、圖像灰度化
彩色轉灰度的著名心理學公式:Gray = R*0.299 + G*0.587 + B*0.114
實際應用中爲了不浮點運算,而後就有了移位運算代替了。
2至20位精度的係數:
Gray = (R*1 + G*2 + B*1) >> 2 
Gray = (R*2 + G*5 + B*1) >> 3 
Gray = (R*4 + G*10 + B*2) >> 4 
Gray = (R*9 + G*19 + B*4) >> 5 
Gray = (R*19 + G*37 + B*8) >> 6 
Gray = (R*38 + G*75 + B*15) >> 7 
Gray = (R*76 + G*150 + B*30) >> 8 
Gray = (R*153 + G*300 + B*59) >> 9 
Gray = (R*306 + G*601 + B*117) >> 10 
Gray = (R*612 + G*1202 + B*234) >> 11 
Gray = (R*1224 + G*2405 + B*467) >> 12 
Gray = (R*2449 + G*4809 + B*934) >> 13 
Gray = (R*4898 + G*9618 + B*1868) >> 14 
Gray = (R*9797 + G*19235 + B*3736) >> 15 
Gray = (R*19595 + G*38469 + B*7472) >> 16 
Gray = (R*39190 + G*76939 + B*14943) >> 17 
Gray = (R*78381 + G*153878 + B*29885) >> 18 
Gray = (R*156762 + G*307757 + B*59769) >> 19 
Gray = (R*313524 + G*615514 + B*119538) >> 20
 
3、灰度化代碼實現
JNIEXPORT jintArray JNICALL Java_org_join_image_util_JoinImage_imgToGray( 
        JNIEnv* env, jobject obj, jintArray buf, int w, int h) { 
    LOGE("==imgToGray=="); 
 
    jint * cbuf; 
    cbuf = (*env)->GetIntArrayElements(env, buf, 0); // 獲取int數組元素 
   
    int alpha = 0xFF; // 不透明值 
    int i, j, color, red, green, blue; 
    for (i = 0; i < h; i++) { 
        for (j = 0; j < w; j++) { 
            color = cbuf[w * i + j]; // 得到color值 
            red = (color >> 16) & 0xFF; // 得到red值 
            green = (color >> 8) & 0xFF; // 得到green值 
            blue = color & 0xFF; // 得到blue值 
            color = (red * 38 + green * 75 + blue * 15) >> 7; // 灰度算法(16位運算下7位精度) 
            color = (alpha << 24) | (color << 16) | (color << 8) | color; // 由ARGB組成新的color值 
            cbuf[w * i + j] = color; // 設置新color值 
        } 
    } 
 
    int size = w * h; 
    jintArray result = (*env)->NewIntArray(env, size); // 新建一個jintArray 
    (*env)->SetIntArrayRegion(env, result, 0, size, cbuf); // 將cbuf轉存入result 
    (*env)->ReleaseIntArrayElements(env, buf, cbuf, 0); // 釋放int數組元素 
    return result; 
 
 
本文歡迎轉載,但請註明出處與做者
出處:http://blog.sina.com.cn/staratsky
做者:流星
相關文章
相關標籤/搜索