1# 使用Image完成图片解码 2 3图片解码指将所支持格式的存档图片解码成统一的[PixelMap](image-overview.md),以便在应用或系统中进行图片显示或[图片处理](image-transformation.md)。当前支持的存档图片格式包括JPEG、PNG、GIF、WebP、BMP、SVG、ICO、DNG、HEIF(不同硬件设备支持情况不同)。 4 5## 开发步骤 6 7图片解码相关API的详细介绍请参见:[图片解码接口文档](../../reference/apis-image-kit/js-apis-image.md)。 8 9### 添加依赖 10 11在进行应用开发之前,开发者需要打开native工程的src/main/cpp/CMakeLists.txt,在target_link_libraries依赖中添加libace_napi.z.so、libpixelmap_ndk.z.so、libimage_source_ndk.z.so、librawfile.z.so以及日志依赖libhilog_ndk.z.so。 12 13```txt 14target_link_libraries(entry PUBLIC libace_napi.z.so libhilog_ndk.z.so libpixelmap_ndk.z.so libimage_source_ndk.z.so librawfile.z.so) 15``` 16 17### 添加接口映射 18 19打开src/main/cpp/hello.cpp文件,在Init函数中添加getSyncPixelMap函数接口映射,作用是以同步的方式生成PixelMap,具体代码如下: 20 21```c++ 22EXTERN_C_START 23static napi_value Init(napi_env env, napi_value exports) 24{ 25 napi_property_descriptor desc[] = { 26 { "getSyncPixelMap", nullptr, getSyncPixelMap, nullptr, nullptr, nullptr, napi_default, nullptr }, 27 }; 28 29 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); 30 return exports; 31} 32EXTERN_C_END 33``` 34 35### JS侧调用 36 371. 打开src\main\cpp\types\libentry\index.d.ts(其中libentry根据工程名生成),导入如下引用文件: 38 39 ```js 40 import { image } from '@kit.ImageKit'; 41 import { resourceManager } from '@kit.LocalizationKit'; 42 43 // 同步调用,入参为资源管理器和图片资源名称,返回PixelMap 44 export const getSyncPixelMap: (resMgr: resourceManager.ResourceManager, src: string) => image.PixelMap; 45 ``` 46 472. 准备图片资源文件,本示例文件名为example.jpg,导入到src\main\resources\rawfile\ 路径下。 48 493. 打开src\main\ets\pages\index.ets,导入"libentry.so(根据工程名生成)",调用Native接口,传入JS的资源对象。示例如下: 50 51 ```js 52 import testNapi from 'libentry.so' 53 import { image } from '@kit.ImageKit'; 54 55 @Entry 56 @Component 57 struct Index { 58 @State pixelMap : PixelMap | undefined = undefined; 59 aboutToAppear() { 60 // 调用自定义的getSyncPixelMap接口,获取pixelMap 61 this.pixelMap = testNapi.getSyncPixelMap(getContext(this).resourceManager, "example.jpg") 62 } 63 64 build() { 65 Row() { 66 Column() { 67 Image(this.pixelMap) 68 .width(100) 69 .height(100) 70 } 71 .width('100%') 72 } 73 .height('100%') 74 } 75 } 76 ``` 77 78### Native接口调用 79 80具体接口说明请参考[API文档](../../reference/apis-image-kit/image.md)。 81 82在hello.cpp文件中获取JS的资源对象,并转为Native的资源对象,即可调用Native接口,调用方式示例代码如下: 83 84**添加引用文件** 85 86 ```c++ 87 // 引入图片框架、raw文件、raw文件管理和日志打印头文件 88 #include <cstdlib> 89 #include <cstring> 90 #include <multimedia/image_framework/image_source_mdk.h> 91 #include <multimedia/image_framework/image_pixel_map_mdk.h> 92 #include <rawfile/raw_file.h> 93 #include <rawfile/raw_file_manager.h> 94 #include <hilog/log.h> 95 96 static napi_value getSyncPixelMap(napi_env env, napi_callback_info info) 97 { 98 size_t argc = 2; 99 napi_value args[2] = {nullptr}; 100 101 napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); 102 103 napi_valuetype srcType; 104 napi_typeof(env, args[0], &srcType); 105 106 // 入参args[0]是资源管理器,用来初始化native层的资源管理器 107 NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, args[0]); 108 109 size_t strSize; 110 char srcBuf[2048]; 111 // 入参args[1]是文件名称 112 napi_get_value_string_utf8(env, args[1], srcBuf, sizeof(srcBuf), &strSize); 113 114 // 用资源管理器打开Raw文件 115 RawFile * rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, srcBuf); 116 if (rawFile != NULL) { 117 // 获取文件大小,并读取数据 118 long len = OH_ResourceManager_GetRawFileSize(rawFile); 119 uint8_t * data = static_cast<uint8_t *>(malloc(len)); 120 int res = OH_ResourceManager_ReadRawFile(rawFile, data, len); 121 122 OhosImageSource imageSource_c; 123 imageSource_c.buffer = data; 124 imageSource_c.bufferSize = len; 125 126 OhosImageSourceOps ops{}; 127 napi_value imageSource; 128 napi_value pixelMap; 129 130 // 用读取到的Raw数据创建ImageSource 131 int32_t ret = OH_ImageSource_Create(env, &imageSource_c, &ops, &imageSource); 132 133 // 初始化native层的ImageSource 134 ImageSourceNative * imageSourceNative_c = OH_ImageSource_InitNative(env, imageSource); 135 OhosImageDecodingOps decodingOps{}; 136 // 创建pixelMap 137 OH_ImageSource_CreatePixelMap(imageSourceNative_c, &decodingOps, &pixelMap); 138 139 // 下列方法,为gif等动图格式提供。 140 // napi_value pixelMapList; 141 // OH_ImageSource_CreatePixelMapList(imageSourceNative_c, &decodingOps, &pixelMapList); 142 // OhosImageSourceDelayTimeList list{}; 143 // OH_ImageSource_GetDelayTime(imageSourceNative_c, &list); 144 // uint32_t count; 145 // OH_ImageSource_GetFrameCount(imageSourceNative_c, &count); 146 147 OhosImageSourceInfo info{}; 148 // 读取图片宽高 149 OH_ImageSource_GetImageInfo(imageSourceNative_c, 0, &info); 150 OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "[decode]", "imageInfo width:%{public}d , height:%{public}d", info.size.width, info.size.height); 151 152 // 读取图片源的ImageWidth配置参数并打印日志 153 OhosImageSourceProperty target; 154 char exifKey_c[] = "ImageWidth"; 155 target.size = strlen(exifKey_c); 156 target.value = exifKey_c; 157 158 OhosImageSourceProperty response{}; 159 response.size = 20; 160 response.value = static_cast<char *>(malloc(20)); 161 OH_ImageSource_GetImageProperty(imageSourceNative_c, &target, &response); 162 OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, "[decode]", "ImageProperty width after modify:%{public}s", response.value); 163 164 // 处理完毕,释放native层资源 165 OH_ImageSource_Release(imageSourceNative_c); 166 OH_ResourceManager_CloseRawFile(rawFile); 167 return pixelMap; 168 } 169 OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr); 170 return nullptr; 171 } 172 ``` 173 174图片框架支持增量式解码,使用方法如下: 175 176 ```c++ 177 // 引入图片框架、raw文件、raw文件管理和日志打印头文件 178 #include <cstdlib> 179 #include <cstring> 180 #include <multimedia/image_framework/image_source_mdk.h> 181 #include <multimedia/image_framework/image_pixel_map_mdk.h> 182 #include <rawfile/raw_file.h> 183 #include <rawfile/raw_file_manager.h> 184 #include <hilog/log.h> 185 186 static napi_value getSyncPixelMap(napi_env env, napi_callback_info info) 187 { 188 size_t argc = 2; 189 napi_value args[2] = {nullptr}; 190 191 napi_get_cb_info(env, info, &argc, args , nullptr, nullptr); 192 193 napi_valuetype srcType; 194 napi_typeof(env, args[0], &srcType); 195 196 // 入参args[0]是资源管理器,用来初始化native层的资源管理器 197 NativeResourceManager * mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, args[0]); 198 199 size_t strSize; 200 char srcBuf[2048]; 201 // 入参args[1]是文件名称 202 napi_get_value_string_utf8(env, args[1], srcBuf, sizeof(srcBuf), &strSize); 203 204 // 用资源管理器打开Raw文件 205 RawFile * rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, srcBuf); 206 if (rawFile != NULL) { 207 // 获取文件大小,若大于2048字节,则增量式解码,否则直接全部解码 208 long len = OH_ResourceManager_GetRawFileSize(rawFile); 209 if (len > 2048) { 210 uint8_t * data = static_cast<uint8_t *>(malloc(len)); 211 // 读取文件全部数据 212 int res = OH_ResourceManager_ReadRawFile(rawFile, data, len); 213 214 uint8_t * holderdata = static_cast<uint8_t *>(malloc(len)); 215 216 OhosImageSource imageSource_c; 217 // imageSource_c的buffer分配了空间,但是数据是空的 218 imageSource_c.buffer = holderdata; 219 imageSource_c.bufferSize = len; 220 OhosImageSourceOps ops{}; 221 napi_value imageSource; 222 // 初始化增量ImageSource 223 OH_ImageSource_CreateIncremental(env, &imageSource_c, &ops, &imageSource); 224 225 // 初始化native层的ImageSource 226 ImageSourceNative * imageSourceNative_c = OH_ImageSource_InitNative(env, imageSource); 227 228 // 以下模拟分片加载场景,分两次加载分片。第一次加载2048字节,第二次加载剩余的数据。 229 OhosImageSourceUpdateData firstData{}; 230 firstData.buffer = data; // 图片数据 231 firstData.bufferSize = len; // 图片数据总大小 232 firstData.isCompleted = false; 233 firstData.offset = 0; // 第一次重头开始加载 234 firstData.updateLength = 2048; // 第一次加载了2048字节 235 OH_ImageSource_UpdateData(imageSourceNative_c, &firstData); 236 237 OhosImageSourceUpdateData secondData{}; 238 secondData.buffer = data; 239 secondData.bufferSize = len; 240 secondData.isCompleted = true; // 最后一次加载,要标记加载完成 241 secondData.offset = 2048; // 已经加载过2048字节了,第二次偏移已经加载的量 242 secondData.updateLength = len - 2048; // 第二次加载剩余的数据 243 OH_ImageSource_UpdateData(imageSourceNative_c, &secondData); 244 245 napi_value pixelMap; 246 OhosImageDecodingOps decodingOps{}; 247 decodingOps.index = 0; 248 // 创建pixelMap 249 OH_ImageSource_CreatePixelMap(imageSourceNative_c, &decodingOps, &pixelMap); 250 251 // 处理完毕,释放native层资源 252 OH_ImageSource_Release(imageSourceNative_c); 253 OH_ResourceManager_CloseRawFile(rawFile); 254 return pixelMap; 255 } 256 // 读取Raw文件全部数据 257 uint8_t * data = static_cast<uint8_t *>(malloc(len)); 258 int res = OH_ResourceManager_ReadRawFile(rawFile, data, len); 259 260 OhosImageSource imageSource_c; 261 imageSource_c.buffer = data; 262 imageSource_c.bufferSize = len; 263 264 OhosImageSourceOps ops{}; 265 napi_value imageSource; 266 napi_value pixelMap; 267 268 // 用读取到的Raw数据创建ImageSource 269 int32_t ret = OH_ImageSource_Create(env, &imageSource_c, &ops, &imageSource); 270 271 // 初始化native层的ImageSource 272 ImageSourceNative * imageSourceNative_c = OH_ImageSource_InitNative(env, imageSource); 273 OhosImageDecodingOps decodingOps{}; 274 275 // 创建pixelMap 276 OH_ImageSource_CreatePixelMap(imageSourceNative_c, &decodingOps, &pixelMap); 277 278 // 处理完毕,释放native层资源 279 OH_ImageSource_Release(imageSourceNative_c); 280 OH_ResourceManager_CloseRawFile(rawFile); 281 return pixelMap; 282 } 283 OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr); 284 return nullptr; 285 } 286 ``` 287