如何将C++侧传入的PixelMap转换成cv::mat格式

 如何将C++侧传入的PixelMap转换成cv::mat格式


HarmonyOS
2024-05-21 22:30:46
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
towerwan

将arkts侧穿到native侧的PixelMap转换成cv::mat有两种方法:

1、将PixelMap的arraybuffer转换成cv::mat

2、使用OH_PixelMap_AccessPixels获取PixelMap的内存地址,将这个内存地址中的数据转换为cv::mat

上述两种方法都必意保证PixelMap的格式与opencv中mat的格式一致,否则会出现色彩的偏差。

参考代码:

将arraybuffer转换成cv::mat代码如下:

static napi_value ArrayBufferToMat(napi_env env, napi_callback_info info) 
{ 
    size_t argc = 3; 
    napi_value args[3] = { nullptr }; 
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 
     
    napi_value error; 
    napi_create_int32(env, -1, &error); 
     
    NativePixelMap *native = OH_PixelMap_InitNativePixelMap(env, args[0]); 
    if (native == nullptr){ 
        return error; 
    } 
    struct OhosPixelMapInfos pixelMapInfos; 
    if (OH_PixelMap_GetImageInfo(native, &pixelMapInfos) != IMAGE_RESULT_SUCCESS){ 
        OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "Test", "hhhhh%{public}d", -1); 
        return error; 
    } 
     
    napi_value buffer = args[1]; 
    napi_valuetype valueType; 
    napi_typeof(env, buffer, &valueType); 
    if (valueType == napi_object){ 
        bool isArrayBuffer = false; 
        napi_is_arraybuffer(env, buffer, &isArrayBuffer); 
        if (!isArrayBuffer) { 
            napi_throw_error(env, "EINVAL", "Error"); 
        } 
    } 
     
    void *data = nullptr; 
    size_t byteLength = 0; 
    napi_get_arraybuffer_info(env, buffer, &data, &byteLength); 
    int32_t *saveBuffer = (int32_t *)(data); 
     
    // 转换成Mat 
    cv::Mat originMat(pixelMapInfos.height, pixelMapInfos.width, CV_8UC4, saveBuffer); 
    if (!originMat.data) { 
        OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "Read Image", "hhhhh%{public}d", -1); 
        return error; 
    } 
     
    // opencv默认bgra或bgr,若pixelmap创建时未指定为这两种格式,需要进行格式转换 
    cv::Mat saveMat; 
    cv::cvtColor(originMat, saveMat, cv::COLOR_BGRA2RGBA); 
    char pathArray[1024]; 
    size_t length; 
    napi_get_value_string_utf8(env, args[2], pathArray, 1024, &length); 
    std::string path(pathArray); 
    path += "/buffer.jpg"; 
    if(!cv::imwrite(path, saveMat)){ 
        OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "Write Image", "hhhhh%{public}d", -1); 
        return error; 
    } 
  
    napi_value res; 
    napi_create_int32(env, 1, &res); 
    return res; 
}

使用OH_PixelMap_AccessPixels获取PixelMap的内存地址,将这个内存地址中的数据转换为cv::mat的代码如下:

注意:针对图库支持硬解码的操作, 需要指定图像的内存空间大小,原本OH_AccessPixels(env, args[0], &imagePixels)获取到图片的内存地址并锁定该内存,但是实际图像的大小需要lineStride对齐。所以在构造成mat时,要指定lineStride对齐,lineStride即rowSize。

static napi_value AccessToMat(napi_env env, napi_callback_info info) 
{ 
    size_t argc = 2; 
    napi_value args[2] = {nullptr}; 
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); 
  
    napi_value error; 
    napi_create_int32(env, -1, &error); 
  
    NativePixelMap *native = OH_PixelMap_InitNativePixelMap(env, args[0]); 
    if (native == nullptr) { 
        return error; 
    } 
    struct OhosPixelMapInfos pixelMapInfos; 
    if (OH_PixelMap_GetImageInfo(native, &pixelMapInfos) != IMAGE_RESULT_SUCCESS) { 
        OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "Test", "hhhhh%{public}d", -1); 
        return error; 
    } 
     
    void *pixel; 
    OH_PixelMap_AccessPixels(native, &pixel); 
  
    // 转换成Mat,注意对齐,所以要传入rowSize 
    cv::Mat originMat(pixelMapInfos.height, pixelMapInfos.width, CV_8UC4, pixel, pixelMapInfos.rowSize); 
    if (!originMat.data) { 
        OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "Read Image", "hhhhh%{public}d", -1); 
        return error; 
    } 
  
    // opencv默认bgra或bgr,若pixelmap创建时未指定为这两种格式,需要进行格式转换 
    cv::Mat saveMat; 
    cv::cvtColor(originMat, saveMat, cv::COLOR_BGRA2RGBA); 
    char pathArray[1024]; 
    size_t length; 
    napi_get_value_string_utf8(env, args[1], pathArray, 1024, &length); 
    std::string path(pathArray); 
    path += "/access.jpg"; 
    if (!cv::imwrite(path, saveMat)) { 
        OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, "Write Image", "hhhhh%{public}d", -1); 
        return error; 
    } 
  
    napi_value res; 
    napi_create_int32(env, 1, &res); 
    return res; 
}
分享
微博
QQ
微信
回复
2024-05-22 21:43:17
相关问题
请问如何将openblock文件转换成exe文件
1087浏览 • 0回复 待解决
如何将时间戳转换为日期格式时间
985浏览 • 1回复 待解决
如何将app.media.app_icon,转换PixelMap
602浏览 • 1回复 待解决
如何base64转换成图片?
8343浏览 • 2回复 待解决
Map类型怎么转换成Json string
477浏览 • 1回复 待解决
如何将js传map转成c++对象
226浏览 • 1回复 待解决
json 如何转换成自定义业务类对象
346浏览 • 1回复 待解决
如何实现ArkTS与C/C++HashMap转换
338浏览 • 0回复 待解决
如何将PixelMap压缩到指定大小
455浏览 • 1回复 待解决
如何将图片PixelMap压缩到指定大小
383浏览 • 1回复 待解决
AVPlayer实现音频播放(c++
333浏览 • 1回复 待解决
如何将PixelMap数据存储到数据库中
591浏览 • 1回复 待解决
c++可以直接调用tsstatic方法吗?
577浏览 • 1回复 待解决
如何修改C++版本?C++支持情况?
298浏览 • 1回复 待解决