CV::Mat 互轉(zhuǎn) Bitmap (Android/JNI)

在 JNI 環(huán)境下 使用 Opencv 處理圖片 第一步,CV::Mat 互轉(zhuǎn) Bitmap。

  • 調(diào)用演示
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; //保存圖像參數(shù)
    void *pixels = 0;       //保存圖像數(shù)據(jù)
    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__)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末宁舰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌矢否,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脑溢,死亡現(xiàn)場離奇詭異僵朗,居然都是意外死亡赖欣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門验庙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來顶吮,“玉大人,你說我怎么就攤上這事粪薛°擦耍” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵违寿,是天一觀的道長湃交。 經(jīng)常有香客問我,道長藤巢,這世上最難降的妖魔是什么搞莺? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮掂咒,結(jié)果婚禮上才沧,老公的妹妹穿的比我還像新娘。我一直安慰自己俏扩,他們只是感情好糜工,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著录淡,像睡著了一般捌木。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嫉戚,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天刨裆,我揣著相機(jī)與錄音,去河邊找鬼彬檀。 笑死帆啃,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的窍帝。 我是一名探鬼主播努潘,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼坤学!你這毒婦竟也來了疯坤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤深浮,失蹤者是張志新(化名)和其女友劉穎压怠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體飞苇,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡菌瘫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年蜗顽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雨让。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡雇盖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宫患,到底是詐尸還是另有隱情刊懈,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布娃闲,位于F島的核電站虚汛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏皇帮。R本人自食惡果不足惜卷哩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望属拾。 院中可真熱鬧将谊,春花似錦、人聲如沸渐白。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纯衍。三九已至栋齿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間襟诸,已是汗流浹背瓦堵。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歌亲,地道東北人菇用。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像陷揪,于是被迫代替她去往敵國和親惋鸥。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348