1# Image Decoding 2<!--Kit: Image Kit--> 3<!--Subsystem: Multimedia--> 4<!--Owner: @aulight02--> 5<!--SE: @liyang_bryan--> 6<!--TSE: @xchaosioda--> 7 8Image decoding refers to the process of decoding an image in a supported format into a PixelMap for image display or [processing](image-transformation.md). Currently, the following image formats are supported: JPEG, PNG, GIF, WebP, BMP, SVG, ICO, DNG, and HEIF (depending on the hardware). 9 10## How to Develop 11 12Read the [API reference](../../reference/apis-image-kit/arkts-apis-image-PixelMap.md) for APIs related to image decoding. 13 14### Adding Dependencies 15 16Open the **src/main/cpp/CMakeLists.txt** file of the native project, add **libace_napi.z.so**, **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. 17 18```txt 19target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libpixelmap_ndk.z.so libimage_source_ndk.z.so librawfile.z.so) 20``` 21 22### Adding API Mappings 23 24Open the **src/main/cpp/hello.cpp** file, and add the mapping of the **getSyncPixelMap** function to the **Init** function. The **getSyncPixelMap** function is used to generate a PixelMap in synchronous mode. The code is as follows: 25 26```c++ 27EXTERN_C_START 28static napi_value Init(napi_env env, napi_value exports) 29{ 30 napi_property_descriptor desc[] = { 31 { "getSyncPixelMap", nullptr, getSyncPixelMap, nullptr, nullptr, nullptr, napi_default, nullptr }, 32 }; 33 34 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 35 return exports; 36} 37EXTERN_C_END 38``` 39 40### Calling APIs on the JS Side 41 421. Open **src\main\cpp\types\*libentry*\index.d.ts** (where **libentry** varies according to the project name), and import the following files: 43 44 ```js 45 import { image } from '@kit.ImageKit'; 46 import { resourceManager } from '@kit.LocalizationKit'; 47 48 // Synchronous call. The input parameters are the resource manager and image resource name, and a PixelMap is returned. 49 export const getSyncPixelMap: (resMgr: resourceManager.ResourceManager, src: string) => image.PixelMap; 50 ``` 51 522. Prepare an image resource file, named **example.jpg** in this example, and import it to **src\main\resources\rawfile\**. 53 543. 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: 55 56 ```js 57 import testNapi from 'libentry.so'; 58 import { image } from '@kit.ImageKit'; 59 import { common } from '@kit.AbilityKit'; 60 @Entry 61 @Component 62 struct Index { 63 @State pixelMap : PixelMap | undefined = undefined; 64 aboutToAppear() { 65 // Obtain the context from the component and ensure that the return value of this.getUIContext().getHostContext() is UIAbilityContext. 66 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; 67 // Call the custom getSyncPixelMap function to obtain a PixelMap. 68 this.pixelMap = testNapi.getSyncPixelMap(context.resourceManager, "example.jpg"); 69 } 70 71 build() { 72 Row() { 73 Column() { 74 Image(this.pixelMap) 75 .width(100) 76 .height(100) 77 } 78 .width('100%') 79 } 80 .height('100%') 81 } 82 } 83 ``` 84 85### Calling the Native APIs 86 87For details about the APIs, see [Image](../../reference/apis-image-kit/capi-image.md). 88 89Obtain the JS resource object from the **hello.cpp** file and convert it to a native resource object. Then you can call native APIs. 90 91**Adding Reference Files** 92 93```c++ 94// Include the image framework, raw file, raw file management, and log print header files. 95#include <cstdlib> 96#include <cstring> 97#include <multimedia/image_framework/image_source_mdk.h> 98#include <multimedia/image_framework/image_pixel_map_mdk.h> 99#include <rawfile/raw_file.h> 100#include <rawfile/raw_file_manager.h> 101#include <hilog/log.h> 102 103static napi_value getSyncPixelMap(napi_env env, napi_callback_info info) 104{ 105 size_t argc = 2; 106 napi_value args[2] = {nullptr}; 107 108 napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); 109 110 napi_valuetype srcType; 111 napi_typeof(env, args[0], &srcType); 112 113 // The input parameter args[0] indicates the resource manager, which is used to initialize the resource manager at the native layer. 114 NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, args[0]); 115 116 size_t strSize; 117 char srcBuf[2048]; 118 // The input parameter args[1] indicates the file name. 119 napi_get_value_string_utf8(env, args[1], srcBuf, sizeof(srcBuf), &strSize); 120 121 // Use the resource manager to open the raw file. 122 RawFile * rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, srcBuf); 123 if (rawFile != NULL) { 124 // Obtain the file size and read data. 125 long len = OH_ResourceManager_GetRawFileSize(rawFile); 126 uint8_t * data = static_cast<uint8_t *>(malloc(len)); 127 int res = OH_ResourceManager_ReadRawFile(rawFile, data, len); 128 129 OhosImageSource imageSource_c; 130 imageSource_c.buffer = data; 131 imageSource_c.bufferSize = len; 132 133 OhosImageSourceOps ops{}; 134 napi_value imageSource; 135 napi_value pixelMap; 136 137 // Create an ImageSource object using the read raw data. 138 int32_t ret = OH_ImageSource_Create(env, &imageSource_c, &ops, &imageSource); 139 140 // Initialize the ImageSource object at the native layer. 141 ImageSourceNative * imageSourceNative_c = OH_ImageSource_InitNative(env, imageSource); 142 OhosImageDecodingOps decodingOps{}; 143 // Create a PixelMap. 144 OH_ImageSource_CreatePixelMap(imageSourceNative_c, &decodingOps, &pixelMap); 145 146 // The following APIs are used for the GIF format. 147 // napi_value pixelMapList; 148 // OH_ImageSource_CreatePixelMapList(imageSourceNative_c, &decodingOps, &pixelMapList); 149 // OhosImageSourceDelayTimeList list{}; 150 // OH_ImageSource_GetDelayTime(imageSourceNative_c, &list); 151 // uint32_t count; 152 // OH_ImageSource_GetFrameCount(imageSourceNative_c, &count); 153 154 OhosImageSourceInfo info{}; 155 // Read the image width and height. 156 OH_ImageSource_GetImageInfo(imageSourceNative_c, 0, &info); 157 OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "[decode]", "imageInfo width:%{public}d , height:%{public}d", info.size.width, info.size.height); 158 159 // Read the ImageWidth configuration of the image source and print logs. 160 OhosImageSourceProperty target; 161 char exifKey_c[] = "ImageWidth"; 162 target.size = strlen(exifKey_c); 163 target.value = exifKey_c; 164 165 OhosImageSourceProperty response{}; 166 response.size = 20; 167 response.value = static_cast<char *>(malloc(20)); 168 OH_ImageSource_GetImageProperty(imageSourceNative_c, &target, &response); 169 OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "[decode]", "ImageProperty width after modify:%{public}s", response.value); 170 171 // After the processing is complete, release resources at the native layer. 172 OH_ImageSource_Release(imageSourceNative_c); 173 OH_ResourceManager_CloseRawFile(rawFile); 174 return pixelMap; 175 } 176 OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr); 177 return nullptr; 178} 179``` 180 181The image framework supports incremental decoding. The method is as follows: 182 183```c++ 184// Include the image framework, raw file, raw file management, and log print header files. 185#include <cstdlib> 186#include <cstring> 187#include <multimedia/image_framework/image_source_mdk.h> 188#include <multimedia/image_framework/image_pixel_map_mdk.h> 189#include <rawfile/raw_file.h> 190#include <rawfile/raw_file_manager.h> 191#include <hilog/log.h> 192 193static napi_value getSyncPixelMap(napi_env env, napi_callback_info info) 194{ 195 size_t argc = 2; 196 napi_value args[2] = {nullptr}; 197 198 napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); 199 200 napi_valuetype srcType; 201 napi_typeof(env, args[0], &srcType); 202 203 // The input parameter args[0] indicates the resource manager, which is used to initialize the resource manager at the native layer. 204 NativeResourceManager * mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, args[0]); 205 206 size_t strSize; 207 char srcBuf[2048]; 208 // The input parameter args[1] indicates the file name. 209 napi_get_value_string_utf8(env, args[1], srcBuf, sizeof(srcBuf), &strSize); 210 211 // Use the resource manager to open the raw file. 212 RawFile * rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, srcBuf); 213 if (rawFile != NULL) { 214 // Obtain the file size. If the file size is greater than 2048 bytes, incremental decoding is performed. Otherwise, full decoding is performed. 215 long len = OH_ResourceManager_GetRawFileSize(rawFile); 216 if (len > 2048) { 217 uint8_t * data = static_cast<uint8_t *>(malloc(len)); 218 // Read all data in the file. 219 int res = OH_ResourceManager_ReadRawFile(rawFile, data, len); 220 221 uint8_t * holderdata = static_cast<uint8_t *>(malloc(len)); 222 223 OhosImageSource imageSource_c; 224 // A buffer of imageSource_c is allocated, but no data is filled in. 225 imageSource_c.buffer = holderdata; 226 imageSource_c.bufferSize = len; 227 OhosImageSourceOps ops{}; 228 napi_value imageSource; 229 // Initialize the incremental ImageSource object. 230 OH_ImageSource_CreateIncremental(env, &imageSource_c, &ops, &imageSource); 231 232 // Initialize the ImageSource object at the native layer. 233 ImageSourceNative * imageSourceNative_c = OH_ImageSource_InitNative(env, imageSource); 234 235 // The following simulates segment loading. Segments are loaded twice. 2048 bytes of data are loaded for the first time, and the remaining data is loaded for the second time. 236 OhosImageSourceUpdateData firstData{}; 237 firstData.buffer = data; // Image data. 238 firstData.bufferSize = len; // Total size of the image data. 239 firstData.isCompleted = false; 240 firstData.offset = 0; // The first loading starts from the very beginning. 241 firstData.updateLength = 2048; // 2048 bytes are loaded for the first time. 242 OH_ImageSource_UpdateData(imageSourceNative_c, &firstData); 243 244 OhosImageSourceUpdateData secondData{}; 245 secondData.buffer = data; 246 secondData.bufferSize = len; 247 secondData.isCompleted = true; // Last loading, to indicating that loading is complete. 248 secondData.offset = 2048; // 2048 bytes of data have been loaded. Offset the data to load for the second time. 249 secondData.updateLength = len - 2048; // Load the remaining data for the second time. 250 OH_ImageSource_UpdateData(imageSourceNative_c, &secondData); 251 252 napi_value pixelMap; 253 OhosImageDecodingOps decodingOps{}; 254 decodingOps.index = 0; 255 // Create a PixelMap. 256 OH_ImageSource_CreatePixelMap(imageSourceNative_c, &decodingOps, &pixelMap); 257 258 // After the processing is complete, release resources at the native layer. 259 OH_ImageSource_Release(imageSourceNative_c); 260 OH_ResourceManager_CloseRawFile(rawFile); 261 return pixelMap; 262 } 263 // Read all data in the raw file. 264 uint8_t * data = static_cast<uint8_t *>(malloc(len)); 265 int res = OH_ResourceManager_ReadRawFile(rawFile, data, len); 266 267 OhosImageSource imageSource_c; 268 imageSource_c.buffer = data; 269 imageSource_c.bufferSize = len; 270 271 OhosImageSourceOps ops{}; 272 napi_value imageSource; 273 napi_value pixelMap; 274 275 // Create an ImageSource object using the read raw data. 276 int32_t ret = OH_ImageSource_Create(env, &imageSource_c, &ops, &imageSource); 277 278 // Initialize the ImageSource object at the native layer. 279 ImageSourceNative * imageSourceNative_c = OH_ImageSource_InitNative(env, imageSource); 280 OhosImageDecodingOps decodingOps{}; 281 282 // Create a PixelMap. 283 OH_ImageSource_CreatePixelMap(imageSourceNative_c, &decodingOps, &pixelMap); 284 285 // After the processing is complete, release resources at the native layer. 286 OH_ImageSource_Release(imageSourceNative_c); 287 OH_ResourceManager_CloseRawFile(rawFile); 288 return pixelMap; 289 } 290 OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr); 291 return nullptr; 292} 293``` 294