android jni返回bitmap,JNI 层 Bitmap 转 OpenCV Mat

JNI 层 Bitmap 转 OpenCV Mat

Java 提供的图片类型大多是 Bitmap 类型(ARGB_8888 或 RGB_565)

那么如果需要使用 OpenCV 进行处理,需要对 Bitmap 转 cv::Mat。

假设输入的图片为:jobject obj_bitmap

输出的图片为:jobject obj_bitmapOut

#include

#include

#include

#include

#define ASSERT(status, ret) if (!(status)) { return ret; }

#define ASSERT_FALSE(status) ASSERT(status, false)

bool BitmapToMatrix(JNIEnv * env, jobject obj_bitmap, cv::Mat & matrix) {

void * bitmapPixels; // 保存图片像素数据

AndroidBitmapInfo bitmapInfo; // 保存图片参数

ASSERT_FALSE( AndroidBitmap_getInfo(env, obj_bitmap, &bitmapInfo) >= 0); // 获取图片参数

ASSERT_FALSE( bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888

|| bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGB_565 ); // 只支持 ARGB_8888 和 RGB_565

ASSERT_FALSE( AndroidBitmap_lockPixels(env, obj_bitmap, &bitmapPixels) >= 0 ); // 获取图片像素(锁定内存块)

ASSERT_FALSE( bitmapPixels );

if (bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {

cv::Mat tmp(bitmapInfo.height, bitmapInfo.width, CV_8UC4, bitmapPixels); // 建立临时 mat

tmp.copyTo(matrix); // 拷贝到目标 matrix

} else {

cv::Mat tmp(bitmapInfo.height, bitmapInfo.width, CV_8UC2, bitmapPixels);

cv::cvtColor(tmp, matrix, cv::COLOR_BGR5652RGB);

}

AndroidBitmap_unlockPixels(env, obj_bitmap); // 解锁

return true;

}

bool MatrixToBitmap(JNIEnv * env, cv::Mat & matrix, jobject obj_bitmap) {

void * bitmapPixels; // 保存图片像素数据

AndroidBitmapInfo bitmapInfo; // 保存图片参数

ASSERT_FALSE( AndroidBitmap_getInfo(env, obj_bitmap, &bitmapInfo) >= 0); // 获取图片参数

ASSERT_FALSE( bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888

|| bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGB_565 ); // 只支持 ARGB_8888 和 RGB_565

ASSERT_FALSE( matrix.dims == 2

&& bitmapInfo.height == (uint32_t)matrix.rows

&& bitmapInfo.width == (uint32_t)matrix.cols ); // 必须是 2 维矩阵,长宽一致

ASSERT_FALSE( matrix.type() == CV_8UC1 || matrix.type() == CV_8UC3 || matrix.type() == CV_8UC4 );

ASSERT_FALSE( AndroidBitmap_lockPixels(env, obj_bitmap, &bitmapPixels) >= 0 ); // 获取图片像素(锁定内存块)

ASSERT_FALSE( bitmapPixels );

if (bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {

cv::Mat tmp(bitmapInfo.height, bitmapInfo.width, CV_8UC4, bitmapPixels);

switch (matrix.type()) {

case CV_8UC1: cv::cvtColor(matrix, tmp, cv::COLOR_GRAY2RGBA); break;

case CV_8UC3: cv::cvtColor(matrix, tmp, cv::COLOR_RGB2RGBA); break;

case CV_8UC4: matrix.copyTo(tmp); break;

default: AndroidBitmap_unlockPixels(env, obj_bitmap); return false;

}

} else {

cv::Mat tmp(bitmapInfo.height, bitmapInfo.width, CV_8UC2, bitmapPixels);

switch (matrix.type()) {

case CV_8UC1: cv::cvtColor(matrix, tmp, cv::COLOR_GRAY2BGR565); break;

case CV_8UC3: cv::cvtColor(matrix, tmp, cv::COLOR_RGB2BGR565); break;

case CV_8UC4: cv::cvtColor(matrix, tmp, cv::COLOR_RGBA2BGR565); break;

default: AndroidBitmap_unlockPixels(env, obj_bitmap); return false;

}

}

AndroidBitmap_unlockPixels(env, obj_bitmap); // 解锁

return true;

}

JNIEXPORT void JNICALL

Java_com_example_MainActivity_JniBitmapExec(JNIEnv * env, jobject /* this */,

jobject obj_bitmap, jobject obj_bitmapOut)

{

cv::Mat matBitmap;

bool ret = BitmapToMatrix(env, obj_bitmap, matBitmap); // Bitmap 转 cv::Mat

if (ret == false) {

return;

}

// 对 mat 进行 opencv 处理

ret = MatrixToBitmap(env, matBitmap, obj_bitmapOut); // Bitmap 转 cv::Mat

if (ret == false) {

return;

}

}

在建立临时 cv::Mat 时,可以通过传递的地址,访问地址进行读取,或者访问地址进行覆写。

如此可以实现建立 cv::Mat 或者保存到 bitmap 中。

只是注意不同图片下的,格式转换问题。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值