bool BitmapToMatrix(JNIEnv *env, jobject obj_bitmap, cv::Mat &matrix) {
void *bitmapPixels; // Save picture pixel data
AndroidBitmapInfo bitmapInfo; // Save picture parameters
CV_Assert(AndroidBitmap_getInfo(env, obj_bitmap, &bitmapInfo) >=
0); // Get picture parameters
CV_Assert(bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888
|| bitmapInfo.format ==
ANDROID_BITMAP_FORMAT_RGB_565); // Only ARGB? 8888 and RGB? 565 are supported
CV_Assert(AndroidBitmap_lockPixels(env, obj_bitmap, &bitmapPixels) >=
0); // Get picture pixels (lock memory block)
CV_Assert(bitmapPixels);
if (bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
cv::Mat tmp(bitmapInfo.height, bitmapInfo.width, CV_8UC4,
bitmapPixels); // Establish temporary mat
tmp.copyTo(
matrix); // Copy to target matrix
} else {
cv::Mat tmp(bitmapInfo.height, bitmapInfo.width, CV_8UC2, bitmapPixels);
cv::cvtColor(tmp, matrix, cv::COLOR_BGR5652RGB);
}
//convert RGB to BGR
cv::cvtColor(matrix, matrix, cv::COLOR_RGB2BGR);
AndroidBitmap_unlockPixels(env, obj_bitmap); // Unlock
return true;
}
2. Mat 转 Bitmap 返回给 Java 层
jobject mat_to_bitmap(JNIEnv *env, Mat &src, bool needPremultiplyAlpha, jobject bitmap_config) {
jclass java_bitmap_class = (jclass) env->FindClass("android/graphics/Bitmap");
jmethodID mid = env->GetStaticMethodID(java_bitmap_class,
"createBitmap",
"(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
jobject bitmap = env->CallStaticObjectMethod(java_bitmap_class,
mid, src.size().width, src.size().height,
bitmap_config);
AndroidBitmapInfo info;
void *pixels = 0;
try {
CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4);
CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
CV_Assert(pixels);
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
Mat tmp(info.height, info.width, CV_8UC4, pixels);
if (src.type() == CV_8UC1) {
cvtColor(src, tmp, CV_GRAY2RGBA);
} else if (src.type() == CV_8UC3) {
cvtColor(src, tmp, CV_RGB2RGBA);
} else if (src.type() == CV_8UC4) {
if (needPremultiplyAlpha) {
cvtColor(src, tmp, COLOR_RGBA2mRGBA);
} else {
src.copyTo(tmp);
}
}
} else {
// info.format == ANDROID_BITMAP_FORMAT_RGB_565
Mat tmp(info.height, info.width, CV_8UC2, pixels);
if (src.type() == CV_8UC1) {
cvtColor(src, tmp, CV_GRAY2BGR565);
} else if (src.type() == CV_8UC3) {
cvtColor(src, tmp, CV_RGB2BGR565);
} else if (src.type() == CV_8UC4) {
cvtColor(src, tmp, CV_RGBA2BGR565);
}
}
AndroidBitmap_unlockPixels(env, bitmap);
return bitmap;
} catch (cv::Exception e) {
AndroidBitmap_unlockPixels(env, bitmap);
jclass je = env->FindClass("org/opencv/core/CvException");
if (!je) je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, e.what());
return bitmap;
} catch (...) {
AndroidBitmap_unlockPixels(env, bitmap);
jclass je = env->FindClass("java/lang/Exception");
env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}");
return bitmap;
}
}
3. Android Mat 操作像素 实现底片效果
extern "C"
JNIEXPORT jobject JNICALL
Java_com_cailei_opencvndk_MainActivity_filmEffect(JNIEnv *env, jobject thiz,
jobject origin_bitmap) {
// 底片效果 利用 opencv 的 Mat
AndroidBitmapInfo bitmapInfo;
int ret = AndroidBitmap_getInfo(env, origin_bitmap, &bitmapInfo);
if (ret != 0) {
return NULL;
}
void *pixel;
AndroidBitmap_lockPixels(env, origin_bitmap, &pixel);
Mat src;
BitmapToMatrix(env, origin_bitmap, src);
// 区域截取
// Mat srcROI = src(Rect(0, 0, bitmapInfo.width, bitmapInfo.height));
int rows = src.rows;
int cols = src.cols;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// 获取像素
int b = src.at(i, j)[0];
int g = src.at(i, j)[1];
int r = src.at(i, j)[2];
// 修改像素
src.at(i, j)[0] = 255 - b;
src.at(i, j)[1] = 255 - g;
src.at(i, j)[2] = 255 - r;
}
}
//get source bitmap's config
jclass java_bitmap_class = (jclass) env->FindClass("android/graphics/Bitmap");
jmethodID mid = env->GetMethodID(java_bitmap_class, "getConfig",
"()Landroid/graphics/Bitmap$Config;");
jobject bitmap_config = env->CallObjectMethod(origin_bitmap, mid);
jobject _bitmap = mat_to_bitmap(env, src, false, bitmap_config);
AndroidBitmap_unlockPixels(env, origin_bitmap);
return _bitmap;
}
Mat 的初始化和我们平时写java代码的习惯不一样,它是先写height 再写 Width。这个位置一开始把我搞死了。我说为啥出不来效果



