深刻了解android平台的jni---图像灰度化处理

1、涉及到的jni编程知识java

Java基本类型的数组,在JNI中都是jArray的类型格式。具体类型以下:linux

typedef jarray jbooleanArray;c++

typedef jarray jbyteArray;算法

typedef jarray jcharArray;编程

typedef jarray jshortArray;数组

typedef jarray jintArray;指针

typedef jarray jlongArray;对象

typedef jarray jfloatArray;blog

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

做者:流星