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