美文网首页
CV::Mat 互转 Bitmap (Android/JNI)

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

作者: 三越 | 来源:发表于2020-07-11 17:19 被阅读0次

    在 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)

          本文链接:https://www.haomeiwen.com/subject/zqmicktx.html