1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cstdio>
17 #include <climits>
18 #include <memory>
19 #include <string>
20 #include "rawfile/raw_file.h"
21 #include "napi/native_api.h"
22 #include "multimedia/image_framework/image/image_packer_native.h"
23
24 #define MIMETYPE_JPEG_STRING "image/jpeg"
25 #define MIMETYPE_PNG_STRING "image/png"
26 #define MIMETYPE_WEBP_STRING "image/webp"
27
28 constexpr int32_t NUM_0 = 0;
29 constexpr int32_t NUM_1 = 1;
30 constexpr int32_t NUM_2 = 2;
31 constexpr int32_t NUM_3 = 3;
32 constexpr int32_t NUM_4 = 4;
33
34 constexpr uint32_t QUALITY = 100;
35 constexpr uint64_t DEFAULT_BUFFER_SIZE = 25 * 1024 * 1024;
36
CreatePacker()37 static std::shared_ptr<OH_ImagePackerNative> CreatePacker()
38 {
39 OH_ImagePackerNative *packer = nullptr;
40 if (OH_ImagePackerNative_Create(&packer) != IMAGE_SUCCESS) {
41 return nullptr;
42 }
43 std::shared_ptr<OH_ImagePackerNative> ptr(packer, OH_ImagePackerNative_Release);
44 return ptr;
45 }
46
CreatePackingOpts(const char * mimeTypeStr)47 static std::shared_ptr<OH_PackingOptions> CreatePackingOpts(const char* mimeTypeStr)
48 {
49 OH_PackingOptions *opts = nullptr;
50 if (OH_PackingOptions_Create(&opts) != IMAGE_SUCCESS) {
51 return nullptr;
52 }
53
54 Image_MimeType mimeType;
55 mimeType.size = strlen(mimeTypeStr);
56 mimeType.data = (char*)mimeTypeStr;
57 if (OH_PackingOptions_SetMimeType(opts, &mimeType) != IMAGE_SUCCESS) {
58 OH_PackingOptions_Release(opts);
59 return nullptr;
60 }
61
62 if (OH_PackingOptions_SetQuality(opts, QUALITY) != IMAGE_SUCCESS) {
63 OH_PackingOptions_Release(opts);
64 return nullptr;
65 }
66
67 std::shared_ptr<OH_PackingOptions> ptr(opts, OH_PackingOptions_Release);
68 return ptr;
69 }
70
CreatePixelMap(OH_ImageSourceNative * imgSource)71 static std::shared_ptr<OH_PixelmapNative> CreatePixelMap(OH_ImageSourceNative* imgSource)
72 {
73 OH_DecodingOptions *decOpts = nullptr;
74 if (OH_DecodingOptions_Create(&decOpts) != IMAGE_SUCCESS) {
75 return nullptr;
76 }
77
78 OH_PixelmapNative *pixelMap = nullptr;
79 if (OH_ImageSourceNative_CreatePixelmap(imgSource, decOpts, &pixelMap) != IMAGE_SUCCESS) {
80 OH_DecodingOptions_Release(decOpts);
81 return nullptr;
82 }
83
84 OH_DecodingOptions_Release(decOpts);
85 std::shared_ptr<OH_PixelmapNative> ptr(pixelMap, OH_PixelmapNative_Release);
86 return ptr;
87 }
88
WriteFile(const char * outPath,uint8_t * outBuffer,size_t outBufferSize)89 static bool WriteFile(const char* outPath, uint8_t* outBuffer, size_t outBufferSize)
90 {
91 FILE* file = fopen(outPath, "w");
92 if (file == nullptr) {
93 return false;
94 }
95
96 if (fwrite(outBuffer, sizeof(uint8_t), outBufferSize, file) <= 0) {
97 return false;
98 }
99
100 if (fclose(file) != 0) {
101 return false;
102 }
103 return true;
104 }
105
106 // PixelMap转为data
packToDataPixelMap(napi_env env,napi_callback_info info)107 static napi_value packToDataPixelMap(napi_env env, napi_callback_info info)
108 {
109 napi_value retSucess = nullptr;
110 napi_create_int32(env, 0, &retSucess);
111 napi_value retFailed = nullptr;
112 napi_create_int32(env, -1, &retFailed);
113 size_t argCount = NUM_2;
114 napi_value argValue[NUM_2] = {0};
115 size_t dataSize;
116 void* inBuffer;
117 char outPath[PATH_MAX];
118 size_t outPathLen = 0;
119 if (napi_get_cb_info(env, info, &argCount, argValue, nullptr, nullptr) != napi_ok || argCount < NUM_2) {
120 return retFailed;
121 }
122 napi_get_arraybuffer_info(env, argValue[NUM_0], &inBuffer, &dataSize);
123 napi_get_value_string_utf8(env, argValue[NUM_1], outPath, PATH_MAX, &outPathLen);
124 auto ptrPacker = CreatePacker();
125 if (!ptrPacker) {
126 return retFailed;
127 }
128 auto ptrOpts = CreatePackingOpts(MIMETYPE_JPEG_STRING);
129 if (!ptrOpts) {
130 return retFailed;
131 }
132 OH_ImageSourceNative *imgSource = nullptr;
133 Image_ErrorCode errCode = OH_ImageSourceNative_CreateFromData(
134 (uint8_t*)inBuffer, dataSize, &imgSource);
135 if (errCode != IMAGE_SUCCESS) {
136 return retFailed;
137 }
138 std::shared_ptr<OH_ImageSourceNative> ptrImgSource(imgSource, OH_ImageSourceNative_Release);
139 auto ptrPixelMap = CreatePixelMap(ptrImgSource.get());
140 if (!ptrPixelMap) {
141 return retFailed;
142 }
143 uint8_t* outBuffer = new uint8_t[DEFAULT_BUFFER_SIZE];
144 size_t outBufferSize = 0;
145 errCode = OH_ImagePackerNative_PackToDataFromPixelmap(
146 ptrPacker.get(), ptrOpts.get(), ptrPixelMap.get(), outBuffer, &outBufferSize);
147 if (errCode != IMAGE_SUCCESS) {
148 delete [] outBuffer;
149 return retFailed;
150 }
151 if (!WriteFile(outPath, outBuffer, outBufferSize)) {
152 delete [] outBuffer;
153 return retFailed;
154 }
155 delete [] outBuffer;
156 return retSucess;
157 }
158
159 // PixelMap转为file
packPixelMapToFile(napi_env env,napi_callback_info info)160 static napi_value packPixelMapToFile(napi_env env, napi_callback_info info)
161 {
162 napi_value retSucess = nullptr;
163 napi_create_int32(env, 0, &retSucess);
164 napi_value retFailed = nullptr;
165 napi_create_int32(env, -1, &retFailed);
166
167 size_t argCount = NUM_2;
168 napi_value argValue[NUM_2] = {0};
169 char inPath[PATH_MAX];
170 size_t inPathLen = 0;
171 int32_t outFD;
172
173 if (napi_get_cb_info(env, info, &argCount, argValue, nullptr, nullptr) != napi_ok || argCount < NUM_2) {
174 return retFailed;
175 }
176 napi_get_value_string_utf8(env, argValue[NUM_0], inPath, PATH_MAX, &inPathLen);
177 napi_get_value_int32(env, argValue[NUM_1], &outFD);
178
179 auto ptrPacker = CreatePacker();
180 if (!ptrPacker) {
181 return retFailed;
182 }
183
184 auto ptrOpts = CreatePackingOpts(MIMETYPE_PNG_STRING);
185 if (!ptrOpts) {
186 return retFailed;
187 }
188
189 OH_ImageSourceNative *imgSource = nullptr;
190 Image_ErrorCode errCode = OH_ImageSourceNative_CreateFromUri(inPath, inPathLen, &imgSource);
191 if (errCode != IMAGE_SUCCESS) {
192 return retFailed;
193 }
194 std::shared_ptr<OH_ImageSourceNative> ptrImgSource(imgSource, OH_ImageSourceNative_Release);
195
196 auto ptrPixelMap = CreatePixelMap(ptrImgSource.get());
197 if (!ptrPixelMap) {
198 return retFailed;
199 }
200
201 errCode = OH_ImagePackerNative_PackToFileFromPixelmap(
202 ptrPacker.get(), ptrOpts.get(), ptrPixelMap.get(), outFD);
203 if (errCode != IMAGE_SUCCESS) {
204 return retFailed;
205 }
206 return retSucess;
207 }
208
209 // ImageSource转为file
packToFileImageSource(napi_env env,napi_callback_info info)210 static napi_value packToFileImageSource(napi_env env, napi_callback_info info)
211 {
212 napi_value retSucess = nullptr;
213 napi_create_int32(env, 0, &retSucess);
214 napi_value retFailed = nullptr;
215 napi_create_int32(env, -1, &retFailed);
216
217 size_t argCount = NUM_2;
218 napi_value argValue[NUM_2] = {0};
219 int32_t inFD;
220 int32_t outFD;
221
222 if (napi_get_cb_info(env, info, &argCount, argValue, nullptr, nullptr) != napi_ok || argCount < NUM_2) {
223 return retFailed;
224 }
225 napi_get_value_int32(env, argValue[NUM_0], &inFD);
226 napi_get_value_int32(env, argValue[NUM_1], &outFD);
227
228 auto ptrPacker = CreatePacker();
229 if (!ptrPacker) {
230 return retFailed;
231 }
232
233 auto ptrOpts = CreatePackingOpts(MIMETYPE_JPEG_STRING);
234 if (!ptrOpts) {
235 return retFailed;
236 }
237
238 OH_ImageSourceNative *imgSource = nullptr;
239 Image_ErrorCode errCode = OH_ImageSourceNative_CreateFromFd(inFD, &imgSource);
240 if (errCode != IMAGE_SUCCESS) {
241 return retFailed;
242 }
243 std::shared_ptr<OH_ImageSourceNative> ptrImgSource(imgSource, OH_ImageSourceNative_Release);
244
245 errCode = OH_ImagePackerNative_PackToFileFromImageSource(
246 ptrPacker.get(), ptrOpts.get(), imgSource, outFD);
247 if (errCode != IMAGE_SUCCESS) {
248 return retFailed;
249 }
250 return retSucess;
251 }
252
253 // ImageSource转为data
packToDataImageSource(napi_env env,napi_callback_info info)254 static napi_value packToDataImageSource(napi_env env, napi_callback_info info)
255 {
256 napi_value retSucess = nullptr;
257 napi_create_int32(env, 0, &retSucess);
258 napi_value retFailed = nullptr;
259 napi_create_int32(env, -1, &retFailed);
260 size_t argCount = NUM_4;
261 napi_value argValue[NUM_4] = {0};
262 RawFileDescriptor rawSrc;
263 int64_t tmp;
264 char outPath[PATH_MAX];
265 size_t outPathLen = 0;
266 if (napi_get_cb_info(env, info, &argCount, argValue, nullptr, nullptr) != napi_ok || argCount < NUM_4) {
267 return retFailed;
268 }
269 napi_get_value_int32(env, argValue[NUM_0], &rawSrc.fd);
270 napi_get_value_int64(env, argValue[NUM_1], &tmp);
271 rawSrc.start = static_cast<long>(tmp);
272 napi_get_value_int64(env, argValue[NUM_2], &tmp);
273 rawSrc.length = static_cast<long>(tmp);
274 napi_get_value_string_utf8(env, argValue[NUM_3], outPath, PATH_MAX, &outPathLen);
275 auto ptrPacker = CreatePacker();
276 auto ptrOpts = CreatePackingOpts(MIMETYPE_WEBP_STRING);
277 if (!ptrPacker || !ptrOpts) {
278 return retFailed;
279 }
280 OH_ImageSourceNative *imgSource = nullptr;
281 Image_ErrorCode errCode = OH_ImageSourceNative_CreateFromRawFile(&rawSrc, &imgSource);
282 if (errCode != IMAGE_SUCCESS) {
283 return retFailed;
284 }
285 std::shared_ptr<OH_ImageSourceNative> ptrImgSource(imgSource, OH_ImageSourceNative_Release);
286
287 uint8_t* outBuffer = new uint8_t[DEFAULT_BUFFER_SIZE];
288 size_t outBufferSize = 0;
289 errCode = OH_ImagePackerNative_PackToDataFromImageSource(
290 ptrPacker.get(), ptrOpts.get(), imgSource, outBuffer, &outBufferSize);
291 if (errCode != IMAGE_SUCCESS) {
292 delete [] outBuffer;
293 return retFailed;
294 }
295 if (!WriteFile(outPath, outBuffer, outBufferSize)) {
296 delete [] outBuffer;
297 return retFailed;
298 }
299 delete [] outBuffer;
300 return retSucess;
301 }
302
Init(napi_env env,napi_value exports)303 EXTERN_C_START static napi_value Init(napi_env env, napi_value exports)
304 {
305 napi_property_descriptor desc[] = {
306 {"packToDataPixelMap", nullptr, packToDataPixelMap, nullptr, nullptr, nullptr, napi_default, nullptr},
307 {"packPixelMapToFile", nullptr, packPixelMapToFile, nullptr, nullptr, nullptr, napi_default, nullptr},
308 {"packToFileImageSource", nullptr, packToFileImageSource, nullptr, nullptr, nullptr, napi_default, nullptr},
309 {"packToDataImageSource", nullptr, packToDataImageSource, nullptr, nullptr, nullptr, napi_default, nullptr},
310 };
311
312 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[NUM_0]), desc);
313 return exports;
314 }
315 EXTERN_C_END
316
317 static napi_module demoModule = {
318 .nm_version = 1,
319 .nm_flags = 0,
320 .nm_filename = nullptr,
321 .nm_register_func = Init,
322 .nm_modname = "entry",
323 .nm_priv = ((void *)0),
324 .reserved = {0},
325 };
326
RegisterEntryModule(void)327 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
328