Image Decoding (C/C++)
Image decoding refers to the process of decoding an archived image in a supported format into a pixel map for image display or processing. Currently, the following image formats are supported: JPEG, PNG, GIF, WebP, BMP, SVG, and ICO.
How to Develop
Read Image for APIs related to image decoding.
Adding Dependencies
Open the src/main/cpp/CMakeLists.txt file of the native project, add libpixelmap_ndk.z.so, libimage_source_ndk.z.so, librawfile.z.so, and libhilog_ndk.z.so (on which the native log APIs depend) to the target_link_libraries dependency.
target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libpixelmap_ndk.z.so libimage_source_ndk.z.so librawfile.z.so)
Adding API Mappings
Open the src/main/cpp/hello.cpp file and add the following API mappings to the Init function:
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
napi_property_descriptor desc[] = {
{ "getSyncPixelMap", nullptr, getSyncPixelMap, nullptr, nullptr, nullptr, napi_default, nullptr },
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
Calling APIs on the JS Side
-
Open src\main\cpp\types*libentry\index.d.ts* (where libentry varies according to the project name), and import the following files:
import image from '@ohos.multimedia.image' import resourceManager from '@ohos.resourceManager' export const getSyncPixelMap: (resMgr: resourceManager.ResourceManager, src: string) => image.PixelMap;
-
Prepare an image resource file, named example.jpg in this example, and import it to **src\main\resources\rawfile**.
-
Open src\main\ets\pages\index.ets, import libentry.so (where libentry varies according to the project name), call the native APIs, and pass in the JS resource object. The following is an example:
import testNapi from 'libentry.so' import image from '@ohos.multimedia.image' @Entry @Component struct Index { @State pixelMap : PixelMap | undefined = undefined; aboutToAppear() { this.pixelMap = testNapi.getSyncPixelMap(getContext(this).resourceManager, "example.jpg") } build() { Row() { Column() { Image(this.pixelMap) .width(100) .height(100) } .width('100%') } .height('100%') } }
Calling the Native APIs
For details about the APIs, see Image API Reference.
Obtain the JS resource object from the hello.cpp file and convert it to a native resource object. Then you can call native APIs.
Adding Reference Files
#include <multimedia/image_framework/image_source_mdk.h>
#include <multimedia/image_framework/image_pixel_map_mdk.h>
#include <rawfile/raw_file.h>
#include <rawfile/raw_file_manager.h>
#include <hilog/log.h>
static napi_value getSyncPixelMap(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_valuetype srcType;
napi_typeof(env, args[0], &srcType);
NativeResourceManager * mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, args[0]);
size_t strSize;
char srcBuf[2048];
napi_get_value_string_utf8(env, args[1], srcBuf, sizeof(srcBuf), &strSize);
RawFile * rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, srcBuf);
if (rawFile != NULL) {
long len = OH_ResourceManager_GetRawFileSize(rawFile);
uint8_t * data = static_cast<uint8_t *>(malloc(len));
int res = OH_ResourceManager_ReadRawFile(rawFile, data, len);
OhosImageSource imageSource_c;
imageSource_c.buffer = data;
imageSource_c.bufferSize = len;
OhosImageSourceOps ops{};
napi_value imageSource;
napi_value pixelMap;
int32_t ret = OH_ImageSource_Create(env, &imageSource_c, &ops, &imageSource);
ImageSourceNative * imageSourceNative_c = OH_ImageSource_InitNative(env, imageSource);
OhosImageDecodingOps decodingOps{};
OH_ImageSource_CreatePixelMap(imageSourceNative_c, &decodingOps, &pixelMap);
// The following APIs are used for the GIF format.
// napi_value pixelMapList;
// OH_ImageSource_CreatePixelMapList(imageSourceNative_c, &decodingOps, &pixelMapList);
// OhosImageSourceDelayTimeList list{};
// OH_ImageSource_GetDelayTime(imageSourceNative_c, &list);
// uint32_t count;
// OH_ImageSource_GetFrameCount(imageSourceNative_c, &count);
OhosImageSourceInfo info{};
OH_ImageSource_GetImageInfo(imageSourceNative_c, 0, &info);
OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "[decode]", "imageInfo width:%{public}d , height:%{public}d", info.size.width, info.size.height);
OhosImageSourceProperty target;
char exifKey_c[] = "ImageWidth";
target.size = strlen(exifKey_c);
target.value = exifKey_c;
OhosImageSourceProperty dstValue;
char dstValue_c[] = "2000";
dstValue.size = strlen(dstValue_c);
dstValue.value = dstValue_c;
OH_ImageSource_ModifyImageProperty(imageSourceNative_c, &target, &dstValue);
OhosImageSourceProperty response{};
response.size = 20;
response.value = static_cast<char *>(malloc(20));
OH_ImageSource_GetImageProperty(imageSourceNative_c, &target, &response);
OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "[decode]", "ImageProperty width after modify:%{public}s", response.value);
OH_ImageSource_Release(imageSourceNative_c);
OH_ResourceManager_CloseRawFile(rawFile);
return pixelMap;
}
OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr);
return nullptr;
}
The image framework supports incremental decoding. The method is as follows:
#include <multimedia/image_framework/image_source_mdk.h>
#include <multimedia/image_framework/image_pixel_map_mdk.h>
#include <rawfile/raw_file.h>
#include <rawfile/raw_file_manager.h>
#include <hilog/log.h>
static napi_value getSyncPixelMap(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_valuetype srcType;
napi_typeof(env, args[0], &srcType);
NativeResourceManager * mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, args[0]);
size_t strSize;
char srcBuf[2048];
napi_get_value_string_utf8(env, args[1], srcBuf, sizeof(srcBuf), &strSize);
RawFile * rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, srcBuf);
if (rawFile != NULL) {
long len = OH_ResourceManager_GetRawFileSize(rawFile);
if (len > 2048) {
uint8_t * data = static_cast<uint8_t *>(malloc(len));
int res = OH_ResourceManager_ReadRawFile(rawFile, data, len);
uint8_t * holderdata = static_cast<uint8_t *>(malloc(len));
OhosImageSource imageSource_c;
imageSource_c.buffer = holderdata;
imageSource_c.bufferSize = len;
OhosImageSourceOps ops{};
napi_value imageSource;
OH_ImageSource_CreateIncremental(env, &imageSource_c, &ops, &imageSource);
ImageSourceNative * imageSourceNative_c = OH_ImageSource_InitNative(env, imageSource);
// The following simulates the segment loading scenario.
OhosImageSourceUpdateData firstData{};
firstData.buffer = data;
firstData.bufferSize = len;
firstData.isCompleted = false;
firstData.offset = 0;
firstData.updateLength = 2048;
OH_ImageSource_UpdateData(imageSourceNative_c, &firstData);
OhosImageSourceUpdateData secondData{};
secondData.buffer = data;
secondData.bufferSize = len;
secondData.isCompleted = true;
secondData.offset = 2048;
secondData.updateLength = len - 2048;
OH_ImageSource_UpdateData(imageSourceNative_c, &secondData);
napi_value pixelMap;
OhosImageDecodingOps decodingOps{};
decodingOps.index = 0;
OH_ImageSource_CreatePixelMap(imageSourceNative_c, &decodingOps, &pixelMap);
OH_ImageSource_Release(imageSourceNative_c);
OH_ResourceManager_CloseRawFile(rawFile);
return pixelMap;
}
uint8_t * data = static_cast<uint8_t *>(malloc(len));
int res = OH_ResourceManager_ReadRawFile(rawFile, data, len);
OhosImageSource imageSource_c;
imageSource_c.buffer = data;
imageSource_c.bufferSize = len;
OhosImageSourceOps ops{};
napi_value imageSource;
napi_value pixelMap;
int32_t ret = OH_ImageSource_Create(env, &imageSource_c, &ops, &imageSource);
ImageSourceNative * imageSourceNative_c = OH_ImageSource_InitNative(env, imageSource);
OhosImageDecodingOps decodingOps{};
OH_ImageSource_CreatePixelMap(imageSourceNative_c, &decodingOps, &pixelMap);
OH_ImageSource_Release(imageSourceNative_c);
OH_ResourceManager_CloseRawFile(rawFile);
return pixelMap;
}
OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr);
return nullptr;
}