CV::Mat 互转 Bitmap (Android/JNI)

在 JNI 环境下 使用 Opencv 处理图片 第一步,CV::Mat 互转 Bitmap。

  • 调用演示
JNIEXPORT void imageGrayscale(JNIEnv *env, jclass thiz, jobject bitmap) {
    cv::Mat srcMat, dstMat;
    BitmapToMat(env, bitmap, srcMat);
    dstMat = image_grayscale(srcMat);
    MatToBitmap(env, dstMat, bitmap);
}
  • Bitmap -> CV::Mat (GRAY/RGB/RGBA)
void BitmapToMat2(JNIEnv *env, jobject& bitmap, cv::Mat& mat, jboolean needUnPremultiplyAlpha) {
    AndroidBitmapInfo info; //保存图像参数
    void *pixels = 0;       //保存图像数据
    cv::Mat &dst = mat;

    try {
        //LOGD("nBitmapToMat");
        CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
        CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
                  info.format == ANDROID_BITMAP_FORMAT_RGB_565);
        CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
        CV_Assert(pixels);

        dst.create(info.height, info.width, CV_8UC4);
        if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
            //LOGD("nBitmapToMat: RGBA_8888 -> CV_8UC4");
            cv::Mat tmp(info.height, info.width, CV_8UC4, pixels);
            if (needUnPremultiplyAlpha) {
                cv::cvtColor(tmp, dst, cv::COLOR_mRGBA2RGBA);
            }
            else {
                tmp.copyTo(dst);
            }
        }
        else {
            // info.format == ANDROID_BITMAP_FORMAT_RGB_565
            //LOGD("nBitmapToMat: RGB_565 -> CV_8UC4");
            cv::Mat tmp(info.height, info.width, CV_8UC2, pixels);
            cv::cvtColor(tmp, dst, cv::COLOR_BGR5652RGBA);
        }
        AndroidBitmap_unlockPixels(env, bitmap);
        return;
    }
    catch (const cv::Exception &e) {
        AndroidBitmap_unlockPixels(env, bitmap);
        LOGE("nBitmapToMat catched cv::Exception: %s", e.what());
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, e.what());
        env->DeleteLocalRef(je);
        return;
    }
    catch (...) {
        AndroidBitmap_unlockPixels(env, bitmap);
        LOGE("nBitmapToMat catched unknown exception (...)");
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "Unknown exception in JNI code {nBitmapToMat}");
        env->DeleteLocalRef(je);
        return;
    }
}

void BitmapToMat(JNIEnv *env, jobject& bitmap, cv::Mat& mat) {
    BitmapToMat2(env, bitmap, mat, false);
}
  • CV::Mat -> Bitmap
void MatToBitmap2(JNIEnv *env, cv::Mat& mat, jobject& bitmap, jboolean needPremultiplyAlpha) {
    AndroidBitmapInfo info;
    void *pixels = 0;
    cv::Mat &src = mat;

    try {
        //LOGD("nMatToBitmap");
        CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
        CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
                  info.format == ANDROID_BITMAP_FORMAT_RGB_565);
        CV_Assert(src.dims == 2 && info.height == (uint32_t) src.rows &&
                  info.width == (uint32_t) src.cols);
        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) {
            cv::Mat tmp(info.height, info.width, CV_8UC4, pixels);
            if (src.type() == CV_8UC1) {
                //LOGD("nMatToBitmap: CV_8UC1 -> RGBA_8888");
                cv::cvtColor(src, tmp, cv::COLOR_GRAY2RGBA);
            }
            else if (src.type() == CV_8UC3) {
                //LOGD("nMatToBitmap: CV_8UC3 -> RGBA_8888");
                cv::cvtColor(src, tmp, cv::COLOR_RGB2RGBA);
            }
            else if (src.type() == CV_8UC4) {
                //LOGD("nMatToBitmap: CV_8UC4 -> RGBA_8888");
                if (needPremultiplyAlpha) {
                    cv::cvtColor(src, tmp, cv::COLOR_RGBA2mRGBA);
                }
                else {
                    src.copyTo(tmp);
                }
            }
        }
        else {
            // info.format == ANDROID_BITMAP_FORMAT_RGB_565
            cv::Mat tmp(info.height, info.width, CV_8UC2, pixels);
            if (src.type() == CV_8UC1) {
                //LOGD("nMatToBitmap: CV_8UC1 -> RGB_565");
                cv::cvtColor(src, tmp, cv::COLOR_GRAY2BGR565);
            }
            else if (src.type() == CV_8UC3) {
                //LOGD("nMatToBitmap: CV_8UC3 -> RGB_565");
                cv::cvtColor(src, tmp, cv::COLOR_RGB2BGR565);
            }
            else if (src.type() == CV_8UC4) {
                //LOGD("nMatToBitmap: CV_8UC4 -> RGB_565");
                cv::cvtColor(src, tmp, cv::COLOR_RGBA2BGR565);
            }
        }
        AndroidBitmap_unlockPixels(env, bitmap);
        return;
    }
    catch (const cv::Exception &e) {
        AndroidBitmap_unlockPixels(env, bitmap);
        LOGE("nMatToBitmap catched cv::Exception: %s", e.what());
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, e.what());
        env->DeleteLocalRef(je);
        return;
    }
    catch (...) {
        AndroidBitmap_unlockPixels(env, bitmap);
        LOGE("nMatToBitmap catched unknown exception (...)");
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}");
        env->DeleteLocalRef(je);
        return;
    }
}

void MatToBitmap(JNIEnv *env, cv::Mat& mat, jobject& bitmap) {
    MatToBitmap2(env, mat, bitmap, false);
}
  • Log 打印
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "ImageProc-error", __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "ImageProc-debug", __VA_ARGS__)

你可能感兴趣的:(CV::Mat 互转 Bitmap (Android/JNI))