[Android jni] Bitmap与Mat对象的相互转换

简介: [Android jni] Bitmap与Mat对象的相互转换

1.JNI实现Bitmap到Mat的转换

void bitmap2mat(JNIEnv *env, jobject bitmap,Mat &mat){
    //锁定画布
    void *pixels;
    AndroidBitmap_lockPixels(env,bitmap,&pixels);
    //获取Bitmap的信息
    AndroidBitmapInfo bitmapInfo;
    AndroidBitmap_getInfo(env,bitmap,&bitmapInfo);
    //判断图像通道数
    if(bitmapInfo.format==AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_RGBA_8888){//mat的四通道
        LOGD("图像4通道");
        Mat image(bitmapInfo.height,bitmapInfo.width,CV_8UC4,pixels);
        image.copyTo(mat);//深拷贝
    }else if(bitmapInfo.format==AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_RGB_565){//mat的二通道CV_8UC2
        LOGD("图像2通道");
        Mat image(bitmapInfo.height,bitmapInfo.width,CV_8UC2,pixels);
        image.copyTo(mat);
    }else{
       
    }
    //解锁画布
    AndroidBitmap_unlockPixels(env,bitmap);
}

调用示例:

extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_opencv_1test(JNIEnv *env, jclass clazz,
                                                         jobject bitmap) {
    Mat mat;
    bitmap2mat(env, bitmap, mat);
    imwrite("/sdcard/DCIM/bitmap2img.png",mat);
}

2.JNI实现Mat到Bitmap的转换

void mat2bitmap(JNIEnv *env, jobject bitmap,Mat &mat){
    //锁定画布
    void *pixels;
    AndroidBitmap_lockPixels(env,bitmap,&pixels);
    //获取Bitmap的信息
    AndroidBitmapInfo bitmapInfo;
    AndroidBitmap_getInfo(env,bitmap,&bitmapInfo);
    int ret;
    // 将Mat数据复制到Bitmap
    cv::Mat bitmapMat(bitmapInfo.height, bitmapInfo.width, CV_8UC4, pixels);
    mat.copyTo(bitmapMat);//深拷贝
    AndroidBitmap_unlockPixels(env, bitmap);//解锁画布
}

调用示例:

extern "C"
JNIEXPORT void JNICALL
Java_com_example_myapplication_MainActivity_opencv_1test(JNIEnv *env, jclass clazz,
                                                         jobject bitmap) {
  
    //获取Bitmap的信息
    AndroidBitmapInfo bitmapInfo;
    AndroidBitmap_getInfo(env,bitmap,&bitmapInfo);
    //创建和Bitmap尺寸相同的Mat对象
    Mat mat1(bitmapInfo.height ,bitmapInfo.width,CV_8UC4,Scalar(0,0,255,255));
    //把mat对象的像素数据复制到bitmap中
    mat2bitmap(env,bitmap,mat1);
}

完整代码:

#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <jni.h>
#include <android/bitmap.h>
#include <opencv2/opencv.hpp>
#include <android/log.h>
#define LOG_TAG "xxx"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
using namespace cv;
using namespace std;
void bitmap2mat(JNIEnv *env, jobject bitmap,Mat &mat);
void mat2bitmap(JNIEnv *env, jobject bitmap,Mat &mat);
void bitmap2mat(JNIEnv *env, jobject bitmap,Mat &mat){
    //锁定画布
    void *pixels;
    AndroidBitmap_lockPixels(env,bitmap,&pixels);
    //获取Bitmap的信息
    AndroidBitmapInfo bitmapInfo;
    AndroidBitmap_getInfo(env,bitmap,&bitmapInfo);
    //判断图像通道数
    if(bitmapInfo.format==AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_RGBA_8888){//mat的四通道
        LOGD("图像4通道");
        Mat image(bitmapInfo.height,bitmapInfo.width,CV_8UC4,pixels);
        image.copyTo(mat);//深拷贝
    }else if(bitmapInfo.format==AndroidBitmapFormat::ANDROID_BITMAP_FORMAT_RGB_565){//mat的二通道CV_8UC2
        LOGD("图像2通道");
        Mat image(bitmapInfo.height,bitmapInfo.width,CV_8UC2,pixels);
        image.copyTo(mat);
    }else{
        LOGD("图像3通道");
        Mat image(bitmapInfo.height,bitmapInfo.width,CV_8UC3,pixels);
        image.copyTo(mat);
    }
    //解锁画布
    AndroidBitmap_unlockPixels(env,bitmap);
}
void mat2bitmap(JNIEnv *env, jobject bitmap,Mat &mat){
    //锁定画布
    void *pixels;
    AndroidBitmap_lockPixels(env,bitmap,&pixels);
    //获取Bitmap的信息
    AndroidBitmapInfo bitmapInfo;
    AndroidBitmap_getInfo(env,bitmap,&bitmapInfo);
    int ret;
    // 将Mat数据复制到Bitmap
    cv::Mat bitmapMat(bitmapInfo.height, bitmapInfo.width, CV_8UC4, pixels);
    mat.copyTo(bitmapMat);
    AndroidBitmap_unlockPixels(env, bitmap);
}

在 Android 通过 JNI 去调用 Bitmap,通过 CMake 去编 so 动态链接库的话,需要添加 jnigraphics 图像库。

target_link_libraries(

       #在target_link_libraries中添加下面的依赖项

       jnigraphics

       )

 

目录
相关文章
|
4天前
|
Android开发
Android JNI与CAN通信遇到的问题总结
Android JNI与CAN通信遇到的问题总结
26 1
|
5天前
|
Android开发
Android JNI 报错(signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr )
Android JNI 报错(signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr )
26 1
|
4月前
|
Java 开发工具 Android开发
OpenCV(一):Android studio jni配置OpenCV(亲测有效,保姆级)
OpenCV(一):Android studio jni配置OpenCV(亲测有效,保姆级)
164 0
|
1月前
|
JSON Android开发 数据格式
android 使用GSON 序列化对象出现字段被优化问题解决方案
android 使用GSON 序列化对象出现字段被优化问题解决方案
|
1月前
|
Android开发 对象存储
OSS对象储存android开发进行下载到本地文件时异步操作失效
android vivo80使用官方示例代码进行文件下载,但是使用oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>()时onSuccess和onFailure不执行
|
3月前
|
存储 缓存 编解码
Android 性能优化: 解释Bitmap的优化策略。
Android 性能优化: 解释Bitmap的优化策略。
41 1
|
Android开发 Java
《Android游戏开发详解》——第2章,第2.11节创建新的对象变量
本节书摘来自异步社区《Android游戏开发详解》一书中的第2章,第2.11节创建新的对象变量,作者 【美】Jonathan S. Harbour,更多章节内容可以访问云栖社区“异步社区”公众号查看 2.11 创建新的对象变量 Android游戏开发详解 我们想要使用Phone类作为蓝图,创建一个新的Phone对象。
1397 0
|
JavaScript Android开发
《Android游戏开发详解》一2.11 创建新的对象变量
语法的不同之处在于最后一步。要创建一个新的Phone对象,我们必须使用Java的内建关键字new,并且声明我们想要用来创建Phone对象的蓝图,即Phone类。让我们将上面的代码添加到main方法中,如程序清单2.10的第5行所示。
1406 0
|
6天前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
24 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库