需求:
NDK开发,输入一张Bitmap图片,然后使用OpenCV等工具去处理,如调节亮度、白平衡、图像负片效,黑白效果等,再将它们添加到一个数组集合中,一起返回给Java调用函数输出。如下图所示:
那么我们要如何去实现这个功能呢?
因为要使用到C/C++,所有对外接口需要封装成JNI接口,传入Bitmap图像使用OpenCV库等工具进行处理后,再返回给Java调用层作输出显示,如果图像数据的传递采用裸数据的形式,直接将传回图像像素值数组明显是很难实现的,这时就需要通过在JNI中利用反射技术,将Java的List、Bitmap等类反射到JNI中去实现了,具体操作如下:
核心代码:
/**
* 返回图像列表
* @param env
* @param clazz
* @param bitmap
* @return
*/
JNIEXPORT jobject JNICALL
Java_com_example_bitmaplists_Process_getBitmapLists(JNIEnv *env, jclass clazz, jobject bitmap) {
//获取ArrayList类引用
jclass list_cls = env->FindClass("java/util/ArrayList");
if (list_cls == nullptr) {
return nullptr;
}
//获取ArrayList构造函数ID
jmethodID list_init = env->GetMethodID(list_cls, "<init>", "()V");
//创建一个ArrayList对象
jobject list_obj = env->NewObject(list_cls, list_init, "");
//获取ArrayList对象的add()方法
jmethodID list_add = env->GetMethodID(list_cls, "add", "(Ljava/lang/Object;)Z");
//获取Func实体类
jclass jcls = env->FindClass("com/example/bitmaplists/Func");
//获取Func实体类属性
jfieldID bit = env->GetFieldID(jcls, "bitmap", "Landroid/graphics/Bitmap;");
jfieldID name = env->GetFieldID(jcls, "funcName", "Ljava/lang/String;");
std::string str[] = {"负像效果", "连环画", "白平衡", "亮度调节"};
cv::Mat image;
BitmapToMatrix(env, bitmap, image);
std::vector<cv::Mat> data;
Mat a1 = Invert(image);
data.push_back(a1);
Mat a2 = ComicStrips(image);
data.push_back(a2);
Mat a3;
AutoWhiteBalance(image, a3);
data.push_back(a3);
Mat a4;
Brightness(image, a4, 1.2, 0);
data.push_back(a4);
for (int i = 0; i < data.size(); i++) {
jobject jobj = env->AllocObject(jcls);
cv::Mat img = data[i];
jobject out = BitmapConfigure(env, img);
MatrixToBitmap(env, img, out);
//根据Func实体类属性设置字段值
env->SetObjectField(jobj, bit, out);
env->SetObjectField(jobj, name, env->NewStringUTF(str[i].c_str()));
//调用ArrayList中的add()方法
env->CallBooleanMethod(list_obj, list_add, jobj);
//销毁目示对象
env->DeleteLocalRef(jobj);
}
return list_obj;
}