前阵子使用JNI希望在Android中掉用C/C++写的函数,函数的功能是对图片进行处理,这里就涉及到图片作为参数传递的问题。因为JNI就只能对那几种基本操作,不能直接将图片作为参数,需要对图片进行处理转换成其他类型而保证其信息没有损耗。最初我使用整型数组传递图片信息,关键代码如下:
JNI接口:
public static native int[] ImgFun(int[] buf, int w, int h);
JNI函数调用(JAVA):
Bitmap img1 = ((BitmapDrawable) getResources().getDrawable(R.drawable.test1)).getBitmap(); int w = img1.getWidth(), h = img1.getHeight(); int[] pix = new int[w * h]; img1.getPixels(pix, 0, w, 0, 0, w, h); int[] resultInt=ImgActivity.ImgFun(pix, w, h);
JNI函数实现(C++):
JNIEXPORT jintArray JNICALL Java_xj_example1_opencvjnitest_ImgActivity_ImgFun (JNIEnv *env, jclass, jintArray buf, jint w, jint h) { jint *cbuf = env->GetIntArrayElements(buf,0); if(cbuf == NULL) { return 0; } Mat myimg(h, w, CV_8UC3, (unsigned char*)cbuf); imwrite("/sdcard2/objdetect/test1.jpg", myimg); //对图像做处理 imwrite("/sdcard2/objdetect/test2.jpg", myimg); int size = w * h; jintArray result = env->NewIntArray(size); env->SetIntArrayRegion(result, 0, size, cbuf); env->ReleaseIntArrayElements(buf, cbuf, 0); return result; }但是这样做对于一些操作会出现问题,比如我传递过去一张图片,传递前图片是这个样子的:
而且图片大小也发生了变化。我认为是mat为了实现字节对齐,需要保证每行是4的倍数,从而导致了这种问题(只是个人观点)。所以不建议用这种方式传递图片数据,推荐使用下面这种传递图片地址的方式:
JNI接口:
public static native void detect(long imgaddr);JNI函数调用(JAVA):
Mat dstMat = Highgui.imread("/sdcard2/objdetect/img/t4.jpg"); //call jni to detect DetectionActivity.detect(dstMat.getNativeObjAddr());
JNI函数实现(C++):
JNIEXPORT void JNICALL Java_hisense_xj_objdetect_DetectionActivity_detect (JNIEnv *env, jclass, jlong imgaddr) { Mat *img = (cv::Mat*)imgaddr; }