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.solibpixelmap_ndk.z.solibimage_source_ndk.z.solibrawfile.z.so以及日志依赖libhilog_ndk.z.so12
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
82hello.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