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

一、涉及到的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

1、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。

2、获取数组的长度:

jsize       (*GetArrayLength)(JNIEnv*, jarray);

3、释放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:释放模式。

4、构造一个指定长度的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);

5、给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编程,需要仔细阅读这个文档

二、图像灰度化

彩色转灰度的著名心理学公式: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

三、灰度化代码实现

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

作者:流星

时间: 2024-08-01 06:28:06

深入了解android平台的jni---图像灰度化处理的相关文章

java实现图像灰度化

/*在研究Java实现将一张图片转成字符画的时候,发现将图像转化字符串是根据照片的灰度采用不同的字符画出来,形成一个灰度表.于是就研究了下关于灰度值这个东西,于是跳了一个大坑...因为鄙人用的ubuntu,所以我的代码路径会有所不同.直接贴出原博文代码.故事的开始是这样的...*/ 1.关于Java实现将一张图片转成字符画(原文地址:http://blog.csdn.net/zhouli_05/article/details/7913263) 怎么样用Java实现将一张图片转成字符画?? 输入:

c#图像灰度化、灰度反转、二值化

图像灰度化:将彩色图像转化成为灰度图像的过程成为图像的灰度化处理.彩色图像中的每个像素的颜色有R.G.B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*255)的颜色的变化范围.而灰度图像是R.G.B三个分量相同的一种特殊的彩色图像,其一个像素点的变化范围为255种,所以在数字图像处理种一般先将各种格式的图像转变成灰度图像以使后续的图像的计算量变得少一些.灰度图像的描述与彩色图像一样仍然反映了整幅图像的整体和局部的色度和亮度等级的分布和特征.图像的灰度

图像 - 灰度化、灰度反转、二值化

原文地址:http://www.cnblogs.com/gdjlc/archive/2013/03/05/2943801.html 图像灰度化: 将彩色图像转化成为灰度图像的过程成为图像的灰度化处理.彩色图像中的每个像素的颜色有R.G.B三个分量决定,而每个分量有255中值可取,这样一个像素点可以有1600多万(255*255*255)的颜色的变化范围.而灰度图像是R.G.B三个分量相同的一种特殊的彩色图像,其一个像素点的变化范围为255种,所以在数字图像处理种一般先将各种格式的图像转变成灰度图

图像灰度化公式 颜色空间用途说明

图像的零碎基本知识点记录如下,一贯的习惯还是喜欢手写体,记录一些小知识点,今天就来贴图的形式与大家分享. 1.图像灰度化公式及增强,灰度化时可以用cvtColor函数,如若用公式方法,则一般标准为RGB各分量占比为0.3,,059 ,0.11. 2. 各颜色空间的性质及用途:

图像灰度化

1彩色图,灰度图,单色图 灰度图是指只含亮度信息,不含色彩信息的图像.灰度化处理是把含有亮度和色彩的彩色图像变化成灰度图像的过程. 图像灰度化处理一般采用以下三种算法: 平均值法: f(i,j)=(R(i,j)+G(i,j)+B(i,j))/3 最大值法: f(i,j)=max(R(i,j),G(i,j),B(i,j)) 加权平均值法:f(i,j)=0.30R(i,j)+0.59G(i,j)+0.11B(i,j) 2 图像灰度化opencv 1 #include <opencv2/opencv.

深入了解android平台的jni(二)

Android.mk是Android提供的一种makefile文件,用来指定诸如编译生成so库名.引用的头文件目录.需要编译的.c/.cpp文件和.a静态库文件等.要掌握jni,就必须熟练掌握Android.mk的语法规范. 一.Android.mk文件的用途一个android子项目中会存在一个或多个Android.mk文件1.单一的Android.mk文件直接参考NDK的sample目录下的hello-jni项目,在这个项目中只有一个Android.mk文件2.多个Android.mk文件如果

Java图像灰度化的实现过程解析

概要 本文主要介绍了灰度化的几种方法,以及如何使用Java实现灰度化.同时分析了网上一种常见却并不妥当的Java灰度化实现,以及证明了opencv的灰度化是使用“加权灰度化”法 24位彩色图与8位灰度图 首先要先介绍一下24位彩色图像,在一个24位彩色图像中,每个像素由三个字节表示,通常表示为RGB.通常,许多24位彩色图像存储为32位图像,每个像素多余的字节存储为一个alpha值,表现有特殊影响的信息[1]. 在RGB模型中,如果R=G=B时,则彩色表示一种灰度颜色,其中R=G=B的值叫灰度值

深入了解android平台的jni(一)

android中很多Java类都具有native接口,这些接口由本地实现,然后注册到系统中.     主要的JNI代码放在以下的路径中:frameworks/base/core/jni/,这个路径中的内容被编译成库 libandroid_runtime.so,被放置在目标系统的/system/lib目录下.此外,android还有其他的 JNI库.JNI中的各个文件,实际上就是普通的C++源文件.如果要深入了解android framework层,则必须Android Native层运行及开发机

C#图像处理---图像灰度化不完全(灰度化失败)的问题

//此原因是因为在保存副本时候图像深度改变: Bitmap curBmpfile;//当前图片 Bitmap iniBmpfile;//图片副本 string curFilename://源图片路径,为24位深度 -------------------------------------- curBitmap = (Bitmap)Image.FromFile(curFilename);//打开并保存 iniBitmap = (Bitmap)curBitmap.Clone(); //用克隆方法可以