1 /*
2 * Copyright (C) 2022 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 "image_source_napi.h"
17 #include <fcntl.h>
18 #include "hilog/log.h"
19 #include "image_napi_utils.h"
20 #include "media_errors.h"
21 #include "string_ex.h"
22 #include "image_trace.h"
23 #include "hitrace_meter.h"
24
25 using OHOS::HiviewDFX::HiLog;
26 namespace {
27 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "ImageSourceNapi"};
28 constexpr int INVALID_FD = -1;
29 constexpr uint32_t NUM_0 = 0;
30 constexpr uint32_t NUM_1 = 1;
31 constexpr uint32_t NUM_2 = 2;
32 constexpr uint32_t NUM_3 = 3;
33 constexpr uint32_t NUM_4 = 4;
34 constexpr uint32_t NUM_5 = 5;
35 constexpr uint32_t NUM_8 = 8;
36 }
37
38 namespace OHOS {
39 namespace Media {
40 thread_local napi_ref ImageSourceNapi::sConstructor_ = nullptr;
41 std::shared_ptr<ImageSource> ImageSourceNapi::sImgSrc_ = nullptr;
42 std::shared_ptr<IncrementalPixelMap> ImageSourceNapi::sIncPixelMap_ = nullptr;
43 static const std::string CLASS_NAME = "ImageSource";
44 static const std::string FILE_URL_PREFIX = "file://";
45 std::string ImageSourceNapi::filePath_ = "";
46 int ImageSourceNapi::fileDescriptor_ = -1;
47 void* ImageSourceNapi::fileBuffer_ = nullptr;
48 size_t ImageSourceNapi::fileBufferSize_ = 0;
49
50 napi_ref ImageSourceNapi::pixelMapFormatRef_ = nullptr;
51 napi_ref ImageSourceNapi::propertyKeyRef_ = nullptr;
52 napi_ref ImageSourceNapi::imageFormatRef_ = nullptr;
53 napi_ref ImageSourceNapi::alphaTypeRef_ = nullptr;
54 napi_ref ImageSourceNapi::scaleModeRef_ = nullptr;
55 napi_ref ImageSourceNapi::componentTypeRef_ = nullptr;
56
57 struct ImageSourceAsyncContext {
58 napi_env env;
59 napi_async_work work;
60 napi_deferred deferred;
61 napi_ref callbackRef = nullptr;
62 ImageSourceNapi *constructor_;
63 uint32_t status;
64 std::string pathName = "";
65 int fdIndex = INVALID_FD;
66 void* sourceBuffer = nullptr;
67 size_t sourceBufferSize = NUM_0;
68 std::string keyStr;
69 std::string valueStr;
70 std::string defaultValueStr;
71 int32_t valueInt;
72 int32_t deufltValueInt;
73 void *updataBuffer;
74 size_t updataBufferSize;
75 uint32_t updataBufferOffset = 0;
76 uint32_t updataLength = 0;
77 bool isCompleted = false;
78 bool isSuccess = false;
79 size_t pathNameLength;
80 SourceOptions opts;
81 uint32_t index = 0;
82 ImageInfo imageInfo;
83 DecodeOptions decodeOpts;
84 std::shared_ptr<ImageSource> rImageSource;
85 std::shared_ptr<PixelMap> rPixelMap;
86 std::string errMsg;
87 std::unique_ptr<std::vector<std::unique_ptr<PixelMap>>> pixelMaps;
88 std::unique_ptr<std::vector<int32_t>> delayTimes;
89 uint32_t frameCount = 0;
90 };
91
92 struct ImageEnum {
93 std::string name;
94 int32_t numVal;
95 std::string strVal;
96 };
97
98 static std::vector<struct ImageEnum> sPixelMapFormatMap = {
99 {"UNKNOWN", 0, ""},
100 {"ARGB_8888", 1, ""},
101 {"RGB_565", 2, ""},
102 {"RGBA_8888", 3, ""},
103 {"BGRA_8888", 4, ""},
104 {"RGB_888", 5, ""},
105 {"ALPHA_8", 6, ""},
106 {"RGBA_F16", 7, ""},
107 {"NV21", 8, ""},
108 {"NV12", 9, ""},
109 };
110 static std::vector<struct ImageEnum> sPropertyKeyMap = {
111 {"BITS_PER_SAMPLE", 0, "BitsPerSample"},
112 {"ORIENTATION", 0, "Orientation"},
113 {"IMAGE_LENGTH", 0, "ImageLength"},
114 {"IMAGE_WIDTH", 0, "ImageWidth"},
115 {"GPS_LATITUDE", 0, "GPSLatitude"},
116 {"GPS_LONGITUDE", 0, "GPSLongitude"},
117 {"GPS_LATITUDE_REF", 0, "GPSLatitudeRef"},
118 {"GPS_LONGITUDE_REF", 0, "GPSLongitudeRef"},
119 {"DATE_TIME_ORIGINAL", 0, "DateTimeOriginal"},
120 {"EXPOSURE_TIME", 0, "ExposureTime"},
121 {"SCENE_TYPE", 0, "SceneType"},
122 {"ISO_SPEED_RATINGS", 0, "ISOSpeedRatings"},
123 {"F_NUMBER", 0, "FNumber"},
124 {"COMPRESSED_BITS_PER_PIXEL", 0, "CompressedBitsPerPixel"},
125 {"DATE_TIME", 0, "DateTime"},
126 {"GPS_TIME_STAMP", 0, "GPSTimeStamp"},
127 {"GPS_DATE_STAMP", 0, "GPSDateStamp"},
128 {"IMAGE_DESCRIPTION", 0, "ImageDescription"},
129 {"MAKE", 0, "Make"},
130 {"MODEL", 0, "Model"},
131 {"PHOTO_MODE", 0, "PhotoMode"},
132 {"SENSITIVITY_TYPE", 0, "SensitivityType"},
133 {"STANDARD_OUTPUT_SENSITIVITY", 0, "StandardOutputSensitivity"},
134 {"RECOMMENDED_EXPOSURE_INDEX", 0, "RecommendedExposureIndex"},
135 {"ISO_SPEED", 0, "ISOSpeedRatings"},
136 {"APERTURE_VALUE", 0, "ApertureValue"},
137 {"EXPOSURE_BIAS_VALUE", 0, "ExposureBiasValue"},
138 {"METERING_MODE", 0, "MeteringMode"},
139 {"LIGHT_SOURCE", 0, "LightSource"},
140 {"FLASH", 0, "Flash"},
141 {"FOCAL_LENGTH", 0, "FocalLength"},
142 {"USER_COMMENT", 0, "UserComment"},
143 {"PIXEL_X_DIMENSION", 0, "PixelXDimension"},
144 {"PIXEL_Y_DIMENSION", 0, "PixelYDimension"},
145 {"WHITE_BALANCE", 0, "WhiteBalance"},
146 {"FOCAL_LENGTH_IN_35_MM_FILM", 0, "FocalLengthIn35mmFilm"},
147 {"CAPTURE_MODE", 0, "HwMnoteCaptureMode"},
148 {"PHYSICAL_APERTURE", 0, "HwMnotePhysicalAperture"},
149 };
150 static std::vector<struct ImageEnum> sImageFormatMap = {
151 {"YCBCR_422_SP", 1000, ""},
152 {"JPEG", 2000, ""},
153 };
154 static std::vector<struct ImageEnum> sAlphaTypeMap = {
155 {"UNKNOWN", 0, ""},
156 {"OPAQUE", 1, ""},
157 {"PREMUL", 2, ""},
158 {"UNPREMUL", 3, ""},
159 };
160 static std::vector<struct ImageEnum> sScaleModeMap = {
161 {"FIT_TARGET_SIZE", 0, ""},
162 {"CENTER_CROP", 1, ""},
163 };
164 static std::vector<struct ImageEnum> sComponentTypeMap = {
165 {"YUV_Y", 1, ""},
166 {"YUV_U", 2, ""},
167 {"YUV_V", 3, ""},
168 {"JPEG", 4, ""},
169 };
170
GetStringArgument(napi_env env,napi_value value)171 static std::string GetStringArgument(napi_env env, napi_value value)
172 {
173 std::string strValue = "";
174 size_t bufLength = 0;
175 napi_status status = napi_get_value_string_utf8(env, value, nullptr, NUM_0, &bufLength);
176 if (status == napi_ok && bufLength > NUM_0 && bufLength < PATH_MAX) {
177 char *buffer = reinterpret_cast<char *>(malloc((bufLength + NUM_1) * sizeof(char)));
178 if (buffer == nullptr) {
179 HiLog::Error(LABEL, "No memory");
180 return strValue;
181 }
182
183 status = napi_get_value_string_utf8(env, value, buffer, bufLength + NUM_1, &bufLength);
184 if (status == napi_ok) {
185 HiLog::Debug(LABEL, "Get Success");
186 strValue.assign(buffer, 0, bufLength + NUM_1);
187 }
188 if (buffer != nullptr) {
189 free(buffer);
190 buffer = nullptr;
191 }
192 }
193 return strValue;
194 }
195
ImageSourceCallbackRoutine(napi_env env,ImageSourceAsyncContext * & context,const napi_value & valueParam)196 static void ImageSourceCallbackRoutine(napi_env env, ImageSourceAsyncContext* &context, const napi_value &valueParam)
197 {
198 napi_value result[NUM_2] = {0};
199 napi_value retVal;
200 napi_value callback = nullptr;
201
202 napi_get_undefined(env, &result[NUM_0]);
203 napi_get_undefined(env, &result[NUM_1]);
204
205 if (context == nullptr) {
206 HiLog::Error(LABEL, "context is nullptr");
207 return;
208 }
209
210 if (context->status == SUCCESS) {
211 result[NUM_1] = valueParam;
212 } else if (context->errMsg.size() > 0) {
213 napi_create_string_utf8(env, context->errMsg.c_str(), NAPI_AUTO_LENGTH, &result[NUM_0]);
214 } else {
215 HiLog::Debug(LABEL, "error status, no message");
216 napi_create_string_utf8(env, "error status, no message", NAPI_AUTO_LENGTH, &result[NUM_0]);
217 }
218
219 if (context->deferred) {
220 if (context->status == SUCCESS) {
221 napi_resolve_deferred(env, context->deferred, result[NUM_1]);
222 } else {
223 napi_reject_deferred(env, context->deferred, result[NUM_0]);
224 }
225 } else {
226 HiLog::Debug(LABEL, "call callback function");
227 napi_get_reference_value(env, context->callbackRef, &callback);
228 napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
229 napi_delete_reference(env, context->callbackRef);
230 }
231
232 napi_delete_async_work(env, context->work);
233
234 delete context;
235 context = nullptr;
236 }
237
CreateEnumTypeObject(napi_env env,napi_valuetype type,napi_ref * ref,std::vector<struct ImageEnum> imageEnumMap)238 static napi_value CreateEnumTypeObject(napi_env env,
239 napi_valuetype type, napi_ref* ref, std::vector<struct ImageEnum> imageEnumMap)
240 {
241 napi_value result = nullptr;
242 napi_status status;
243 int32_t refCount = 1;
244 std::string propName;
245 status = napi_create_object(env, &result);
246 if (status == napi_ok) {
247 for (auto imgEnum : imageEnumMap) {
248 napi_value enumNapiValue = nullptr;
249 if (type == napi_string) {
250 status = napi_create_string_utf8(env, imgEnum.strVal.c_str(),
251 NAPI_AUTO_LENGTH, &enumNapiValue);
252 } else if (type == napi_number) {
253 status = napi_create_int32(env, imgEnum.numVal, &enumNapiValue);
254 } else {
255 HiLog::Error(LABEL, "Unsupported type %{public}d!", type);
256 }
257 if (status == napi_ok && enumNapiValue != nullptr) {
258 status = napi_set_named_property(env, result, imgEnum.name.c_str(), enumNapiValue);
259 }
260 if (status != napi_ok) {
261 HiLog::Error(LABEL, "Failed to add named prop!");
262 break;
263 }
264 }
265
266 if (status == napi_ok) {
267 status = napi_create_reference(env, result, refCount, ref);
268 if (status == napi_ok) {
269 return result;
270 }
271 }
272 }
273 HiLog::Error(LABEL, "CreateEnumTypeObject is Failed!");
274 napi_get_undefined(env, &result);
275 return result;
276 }
277
ImageSourceNapi()278 ImageSourceNapi::ImageSourceNapi():env_(nullptr)
279 { }
280
~ImageSourceNapi()281 ImageSourceNapi::~ImageSourceNapi()
282 {
283 release();
284 }
285
286 struct ImageConstructorInfo {
287 std::string className;
288 napi_ref* classRef;
289 napi_callback constructor;
290 const napi_property_descriptor* property;
291 size_t propertyCount;
292 const napi_property_descriptor* staticProperty;
293 size_t staticPropertyCount;
294 };
295
DoInit(napi_env env,napi_value exports,struct ImageConstructorInfo info)296 static napi_value DoInit(napi_env env, napi_value exports, struct ImageConstructorInfo info)
297 {
298 napi_value constructor = nullptr;
299 napi_status status = napi_define_class(env, info.className.c_str(), NAPI_AUTO_LENGTH,
300 info.constructor, nullptr, info.propertyCount, info.property, &constructor);
301 if (status != napi_ok) {
302 HiLog::Error(LABEL, "define class fail");
303 return nullptr;
304 }
305
306 status = napi_create_reference(env, constructor, NUM_1, info.classRef);
307 if (status != napi_ok) {
308 HiLog::Error(LABEL, "create reference fail");
309 return nullptr;
310 }
311
312 napi_value global = nullptr;
313 status = napi_get_global(env, &global);
314 if (status != napi_ok) {
315 HiLog::Error(LABEL, "Init:get global fail");
316 return nullptr;
317 }
318
319 status = napi_set_named_property(env, global, info.className.c_str(), constructor);
320 if (status != napi_ok) {
321 HiLog::Error(LABEL, "Init:set global named property fail");
322 return nullptr;
323 }
324
325 status = napi_set_named_property(env, exports, info.className.c_str(), constructor);
326 if (status != napi_ok) {
327 HiLog::Error(LABEL, "set named property fail");
328 return nullptr;
329 }
330
331 status = napi_define_properties(env, exports, info.staticPropertyCount, info.staticProperty);
332 if (status != napi_ok) {
333 HiLog::Error(LABEL, "define properties fail");
334 return nullptr;
335 }
336 return exports;
337 }
338
Init(napi_env env,napi_value exports)339 napi_value ImageSourceNapi::Init(napi_env env, napi_value exports)
340 {
341 napi_property_descriptor properties[] = {
342 DECLARE_NAPI_FUNCTION("getImageInfo", GetImageInfo),
343 DECLARE_NAPI_FUNCTION("modifyImageProperty", ModifyImageProperty),
344 DECLARE_NAPI_FUNCTION("getImageProperty", GetImageProperty),
345 DECLARE_NAPI_FUNCTION("getDelayTimeList", GetDelayTime),
346 DECLARE_NAPI_FUNCTION("getFrameCount", GetFrameCount),
347 DECLARE_NAPI_FUNCTION("createPixelMapList", CreatePixelMapList),
348 DECLARE_NAPI_FUNCTION("createPixelMap", CreatePixelMap),
349 DECLARE_NAPI_FUNCTION("updateData", UpdateData),
350 DECLARE_NAPI_FUNCTION("release", Release),
351 DECLARE_NAPI_GETTER("supportedFormats", GetSupportedFormats),
352 };
353
354 napi_property_descriptor static_prop[] = {
355 DECLARE_NAPI_STATIC_FUNCTION("createImageSource", CreateImageSource),
356 DECLARE_NAPI_STATIC_FUNCTION("CreateIncrementalSource", CreateIncrementalSource),
357 DECLARE_NAPI_PROPERTY("PixelMapFormat",
358 CreateEnumTypeObject(env, napi_number, &pixelMapFormatRef_, sPixelMapFormatMap)),
359 DECLARE_NAPI_PROPERTY("PropertyKey",
360 CreateEnumTypeObject(env, napi_string, &propertyKeyRef_, sPropertyKeyMap)),
361 DECLARE_NAPI_PROPERTY("ImageFormat",
362 CreateEnumTypeObject(env, napi_number, &imageFormatRef_, sImageFormatMap)),
363 DECLARE_NAPI_PROPERTY("AlphaType",
364 CreateEnumTypeObject(env, napi_number, &alphaTypeRef_, sAlphaTypeMap)),
365 DECLARE_NAPI_PROPERTY("ScaleMode",
366 CreateEnumTypeObject(env, napi_number, &scaleModeRef_, sScaleModeMap)),
367 DECLARE_NAPI_PROPERTY("ComponentType",
368 CreateEnumTypeObject(env, napi_number, &componentTypeRef_, sComponentTypeMap)),
369 };
370
371 struct ImageConstructorInfo info = {
372 .className = CLASS_NAME,
373 .classRef = &sConstructor_,
374 .constructor = Constructor,
375 .property = properties,
376 .propertyCount = sizeof(properties) / sizeof(properties[NUM_0]),
377 .staticProperty = static_prop,
378 .staticPropertyCount = sizeof(static_prop) / sizeof(static_prop[NUM_0]),
379 };
380
381 if (DoInit(env, exports, info)) {
382 return nullptr;
383 }
384
385 HiLog::Debug(LABEL, "Init success");
386 return exports;
387 }
388
Constructor(napi_env env,napi_callback_info info)389 napi_value ImageSourceNapi::Constructor(napi_env env, napi_callback_info info)
390 {
391 napi_value undefineValue = nullptr;
392 napi_get_undefined(env, &undefineValue);
393
394 napi_status status;
395 napi_value thisVar = nullptr;
396 status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
397 if (status == napi_ok && thisVar != nullptr) {
398 std::unique_ptr<ImageSourceNapi> pImgSrcNapi = std::make_unique<ImageSourceNapi>();
399 if (pImgSrcNapi != nullptr) {
400 pImgSrcNapi->env_ = env;
401 pImgSrcNapi->nativeImgSrc = sImgSrc_;
402 pImgSrcNapi->navIncPixelMap_ = sIncPixelMap_;
403 sIncPixelMap_ = nullptr;
404 sImgSrc_ = nullptr;
405 status = napi_wrap(env, thisVar, reinterpret_cast<void *>(pImgSrcNapi.get()),
406 ImageSourceNapi::Destructor, nullptr, nullptr);
407 if (status == napi_ok) {
408 pImgSrcNapi.release();
409 return thisVar;
410 } else {
411 HiLog::Error(LABEL, "Failure wrapping js to native napi");
412 }
413 }
414 }
415
416 return undefineValue;
417 }
418
Destructor(napi_env env,void * nativeObject,void * finalize)419 void ImageSourceNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
420 {
421 }
422
GetSupportedFormats(napi_env env,napi_callback_info info)423 napi_value ImageSourceNapi::GetSupportedFormats(napi_env env, napi_callback_info info)
424 {
425 napi_value result = nullptr;
426 napi_get_undefined(env, &result);
427
428 napi_status status;
429 napi_value thisVar = nullptr;
430 size_t argCount = 0;
431 HiLog::Debug(LABEL, "GetSupportedFormats IN");
432
433 IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
434
435 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
436
437 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
438 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
439
440 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_),
441 nullptr, HiLog::Error(LABEL, "fail to unwrap context"));
442 std::set<std::string> formats;
443 uint32_t ret = asyncContext->constructor_->nativeImgSrc->GetSupportedFormats(formats);
444
445 IMG_NAPI_CHECK_RET_D((ret == SUCCESS),
446 nullptr, HiLog::Error(LABEL, "fail to get supported formats"));
447
448 napi_create_array(env, &result);
449 size_t i = 0;
450 for (const std::string& formatStr: formats) {
451 napi_value format = nullptr;
452 napi_create_string_latin1(env, formatStr.c_str(), formatStr.length(), &format);
453 napi_set_element(env, result, i, format);
454 i++;
455 }
456 return result;
457 }
458
STATIC_COMPLETE_FUNC(GetImageInfo)459 STATIC_COMPLETE_FUNC(GetImageInfo)
460 {
461 napi_value result = nullptr;
462 auto context = static_cast<ImageSourceAsyncContext*>(data);
463 if (context->status == SUCCESS) {
464 napi_create_object(env, &result);
465
466 napi_value size = nullptr;
467 napi_create_object(env, &size);
468
469 napi_value sizeWith = nullptr;
470 napi_create_int32(env, context->imageInfo.size.width, &sizeWith);
471 napi_set_named_property(env, size, "width", sizeWith);
472
473 napi_value sizeHeight = nullptr;
474 napi_create_int32(env, context->imageInfo.size.height, &sizeHeight);
475 napi_set_named_property(env, size, "height", sizeHeight);
476
477 napi_set_named_property(env, result, "size", size);
478
479 napi_value pixelFormatValue = nullptr;
480 napi_create_int32(env, static_cast<int32_t>(context->imageInfo.pixelFormat), &pixelFormatValue);
481 napi_set_named_property(env, result, "pixelFormat", pixelFormatValue);
482
483 napi_value colorSpaceValue = nullptr;
484 napi_create_int32(env, static_cast<int32_t>(context->imageInfo.colorSpace), &colorSpaceValue);
485 napi_set_named_property(env, result, "colorSpace", colorSpaceValue);
486
487 napi_value alphaTypeValue = nullptr;
488 napi_create_int32(env, static_cast<int32_t>(context->imageInfo.alphaType), &alphaTypeValue);
489 napi_set_named_property(env, result, "alphaType", alphaTypeValue);
490
491 if (!IMG_IS_OK(status)) {
492 context->status = ERROR;
493 HiLog::Error(LABEL, "napi_create_int32 failed!");
494 napi_get_undefined(env, &result);
495 } else {
496 context->status = SUCCESS;
497 }
498 } else {
499 napi_get_undefined(env, &result);
500 }
501
502 ImageSourceCallbackRoutine(env, context, result);
503 }
504
ParseSize(napi_env env,napi_value root,Size * size)505 static bool ParseSize(napi_env env, napi_value root, Size* size)
506 {
507 if (size == nullptr) {
508 HiLog::Error(LABEL, "size is nullptr");
509 return false;
510 }
511 if (!GET_INT32_BY_NAME(root, "height", size->height)) {
512 return false;
513 }
514
515 if (!GET_INT32_BY_NAME(root, "width", size->width)) {
516 return false;
517 }
518
519 return true;
520 }
521
ParseRegion(napi_env env,napi_value root,Rect * region)522 static bool ParseRegion(napi_env env, napi_value root, Rect* region)
523 {
524 napi_value tmpValue = nullptr;
525
526 if (region == nullptr) {
527 HiLog::Error(LABEL, "region is nullptr");
528 return false;
529 }
530
531 if (!GET_INT32_BY_NAME(root, "x", region->left)) {
532 return false;
533 }
534
535 if (!GET_INT32_BY_NAME(root, "y", region->top)) {
536 return false;
537 }
538
539 if (!GET_NODE_BY_NAME(root, "size", tmpValue)) {
540 return false;
541 }
542
543 if (!GET_INT32_BY_NAME(tmpValue, "height", region->height)) {
544 return false;
545 }
546
547 if (!GET_INT32_BY_NAME(tmpValue, "width", region->width)) {
548 return false;
549 }
550
551 return true;
552 }
553
IsSupportPixelFormat(int32_t val)554 static bool IsSupportPixelFormat(int32_t val)
555 {
556 if (val >= static_cast<int32_t>(PixelFormat::UNKNOWN) &&
557 val <= static_cast<int32_t>(PixelFormat::RGBA_F16)) {
558 return true;
559 }
560
561 return false;
562 }
563
ParsePixlForamt(int32_t val)564 static PixelFormat ParsePixlForamt(int32_t val)
565 {
566 if (val <= static_cast<int32_t>(PixelFormat::CMYK)) {
567 return PixelFormat(val);
568 }
569
570 return PixelFormat::UNKNOWN;
571 }
572
ParseDecodeOptions2(napi_env env,napi_value root,DecodeOptions * opts,std::string & error)573 static bool ParseDecodeOptions2(napi_env env, napi_value root, DecodeOptions* opts, std::string &error)
574 {
575 uint32_t tmpNumber = 0;
576 if (!GET_UINT32_BY_NAME(root, "desiredPixelFormat", tmpNumber)) {
577 HiLog::Debug(LABEL, "no desiredPixelFormat");
578 } else {
579 if (IsSupportPixelFormat(tmpNumber)) {
580 opts->desiredPixelFormat = ParsePixlForamt(tmpNumber);
581 } else {
582 HiLog::Debug(LABEL, "Invalid desiredPixelFormat %{public}d", tmpNumber);
583 error = "DecodeOptions mismatch";
584 return false;
585 }
586 }
587
588 if (!GET_INT32_BY_NAME(root, "fitDensity", opts->fitDensity)) {
589 HiLog::Debug(LABEL, "no fitDensity");
590 }
591
592 if (GET_UINT32_BY_NAME(root, "fillColor", opts->SVGOpts.fillColor.color)) {
593 opts->SVGOpts.fillColor.isValidColor = true;
594 HiLog::Debug(LABEL, "fillColor %{public}x", opts->SVGOpts.fillColor.color);
595 } else {
596 HiLog::Debug(LABEL, "no fillColor");
597 }
598
599 if (GET_UINT32_BY_NAME(root, "SVGResize", opts->SVGOpts.SVGResize.resizePercentage)) {
600 opts->SVGOpts.SVGResize.isValidPercentage = true;
601 HiLog::Debug(LABEL, "SVGResize percentage %{public}x", opts->SVGOpts.SVGResize.resizePercentage);
602 } else {
603 HiLog::Debug(LABEL, "no SVGResize percentage");
604 }
605 return true;
606 }
607
ParseDecodeOptions(napi_env env,napi_value root,DecodeOptions * opts,uint32_t * pIndex,std::string & error)608 static bool ParseDecodeOptions(napi_env env, napi_value root, DecodeOptions* opts,
609 uint32_t* pIndex, std::string &error)
610 {
611 napi_value tmpValue = nullptr;
612
613 if (!ImageNapiUtils::GetUint32ByName(env, root, "index", pIndex)) {
614 HiLog::Debug(LABEL, "no index");
615 }
616
617 if (opts == nullptr) {
618 HiLog::Error(LABEL, "opts is nullptr");
619 return false;
620 }
621
622 if (!GET_UINT32_BY_NAME(root, "sampleSize", opts->sampleSize)) {
623 HiLog::Debug(LABEL, "no sampleSize");
624 }
625
626 if (!GET_UINT32_BY_NAME(root, "rotate", opts->rotateNewDegrees)) {
627 HiLog::Debug(LABEL, "no rotate");
628 } else {
629 if (opts->rotateNewDegrees >= 0 &&
630 opts->rotateNewDegrees <= 360) { // 360 is the maximum rotation angle.
631 opts->rotateDegrees = static_cast<float>(opts->rotateNewDegrees);
632 } else {
633 HiLog::Debug(LABEL, "Invalid rotate %{public}d", opts->rotateNewDegrees);
634 error = "DecodeOptions mismatch";
635 return false;
636 }
637 }
638
639 if (!GET_BOOL_BY_NAME(root, "editable", opts->editable)) {
640 HiLog::Debug(LABEL, "no editable");
641 }
642
643 if (!GET_NODE_BY_NAME(root, "desiredSize", tmpValue)) {
644 HiLog::Debug(LABEL, "no desiredSize");
645 } else {
646 if (!ParseSize(env, tmpValue, &(opts->desiredSize))) {
647 HiLog::Debug(LABEL, "ParseSize error");
648 }
649 }
650
651 if (!GET_NODE_BY_NAME(root, "desiredRegion", tmpValue)) {
652 HiLog::Debug(LABEL, "no desiredRegion");
653 } else {
654 if (!ParseRegion(env, tmpValue, &(opts->CropRect))) {
655 HiLog::Debug(LABEL, "ParseRegion error");
656 }
657 }
658 return ParseDecodeOptions2(env, root, opts, error);
659 }
660
FileUrlToRawPath(const std::string & path)661 static std::string FileUrlToRawPath(const std::string &path)
662 {
663 if (path.size() > FILE_URL_PREFIX.size() &&
664 (path.compare(0, FILE_URL_PREFIX.size(), FILE_URL_PREFIX) == 0)) {
665 return path.substr(FILE_URL_PREFIX.size());
666 }
667 return path;
668 }
669
parseSourceOptions(napi_env env,napi_value root,SourceOptions * opts)670 static void parseSourceOptions(napi_env env, napi_value root, SourceOptions* opts)
671 {
672 if (!ImageNapiUtils::GetInt32ByName(env, root, "sourceDensity", &(opts->baseDensity))) {
673 HiLog::Debug(LABEL, "no sourceDensity");
674 }
675
676 int32_t pixelFormat = 0;
677 if (!ImageNapiUtils::GetInt32ByName(env, root, "sourcePixelFormat", &pixelFormat)) {
678 HiLog::Debug(LABEL, "no sourcePixelFormat");
679 } else {
680 opts->pixelFormat = static_cast<PixelFormat>(pixelFormat);
681 HiLog::Info(LABEL, "sourcePixelFormat:%{public}d", static_cast<int32_t>(opts->pixelFormat));
682 }
683
684 napi_value tmpValue = nullptr;
685 if (!GET_NODE_BY_NAME(root, "sourceSize", tmpValue)) {
686 HiLog::Debug(LABEL, "no sourceSize");
687 } else {
688 if (!ParseSize(env, tmpValue, &(opts->size))) {
689 HiLog::Debug(LABEL, "ParseSize error");
690 }
691 HiLog::Info(LABEL, "sourceSize:(%{public}d, %{public}d)", opts->size.width, opts->size.height);
692 }
693 }
PrepareNapiEnv(napi_env env)694 static void PrepareNapiEnv(napi_env env)
695 {
696 napi_value globalValue;
697 napi_get_global(env, &globalValue);
698 napi_value func;
699 napi_get_named_property(env, globalValue, "requireNapi", &func);
700
701 napi_value imageInfo;
702 napi_create_string_utf8(env, "multimedia.image", NAPI_AUTO_LENGTH, &imageInfo);
703 napi_value funcArgv[1] = { imageInfo };
704 napi_value returnValue;
705 napi_call_function(env, globalValue, func, 1, funcArgv, &returnValue);
706 }
CreateNativeImageSource(napi_env env,napi_value argValue,SourceOptions & opts,ImageSourceAsyncContext * context)707 static std::unique_ptr<ImageSource> CreateNativeImageSource(napi_env env, napi_value argValue,
708 SourceOptions &opts, ImageSourceAsyncContext* context)
709 {
710 std::unique_ptr<ImageSource> imageSource = nullptr;
711 uint32_t errorCode = ERR_MEDIA_INVALID_VALUE;
712 napi_status status;
713
714 auto inputType = ImageNapiUtils::getType(env, argValue);
715 if (napi_string == inputType) { // File Path
716 if (!ImageNapiUtils::GetUtf8String(env, argValue, context->pathName)) {
717 HiLog::Error(LABEL, "fail to get pathName");
718 return imageSource;
719 }
720 context->pathName = FileUrlToRawPath(context->pathName);
721 context->pathNameLength = context->pathName.size();
722 HiLog::Debug(LABEL, "pathName is [%{public}s]", context->pathName.c_str());
723 imageSource = ImageSource::CreateImageSource(context->pathName, opts, errorCode);
724 } else if (napi_number == inputType) { // Fd
725 napi_get_value_int32(env, argValue, &context->fdIndex);
726 HiLog::Debug(LABEL, "CreateImageSource fdIndex is [%{public}d]", context->fdIndex);
727 imageSource = ImageSource::CreateImageSource(context->fdIndex, opts, errorCode);
728 } else { // Input Buffer
729 uint32_t refCount = NUM_1;
730 napi_ref arrayRef = nullptr;
731 napi_create_reference(env, argValue, refCount, &arrayRef);
732 status = napi_get_arraybuffer_info(env, argValue, &(context->sourceBuffer), &(context->sourceBufferSize));
733 if (status != napi_ok) {
734 napi_delete_reference(env, arrayRef);
735 HiLog::Error(LABEL, "fail to get arraybufferinfo");
736 return nullptr;
737 }
738 imageSource = ImageSource::CreateImageSource(static_cast<uint8_t *>(context->sourceBuffer),
739 context->sourceBufferSize, opts, errorCode);
740 napi_delete_reference(env, arrayRef);
741 }
742 return imageSource;
743 }
744
CreateImageSource(napi_env env,napi_callback_info info)745 napi_value ImageSourceNapi::CreateImageSource(napi_env env, napi_callback_info info)
746 {
747 PrepareNapiEnv(env);
748 napi_value result = nullptr;
749 napi_get_undefined(env, &result);
750
751 napi_status status;
752 napi_value thisVar = nullptr;
753 napi_value argValue[NUM_2] = {0};
754 size_t argCount = 2;
755 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
756 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
757 NAPI_ASSERT(env, argCount > 0, "No arg!");
758
759 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
760 SourceOptions opts;
761 if (argCount > NUM_1) {
762 parseSourceOptions(env, argValue[NUM_1], &opts);
763 }
764 std::unique_ptr<ImageSource> imageSource = CreateNativeImageSource(env, argValue[NUM_0],
765 opts, asyncContext.get());
766 if (imageSource == nullptr) {
767 HiLog::Error(LABEL, "CreateImageSourceExec error");
768 napi_get_undefined(env, &result);
769 return result;
770 }
771 filePath_ = asyncContext->pathName;
772 fileDescriptor_ = asyncContext->fdIndex;
773 fileBuffer_ = asyncContext->sourceBuffer;
774 fileBufferSize_ = asyncContext->sourceBufferSize;
775
776 napi_value constructor = nullptr;
777 status = napi_get_reference_value(env, sConstructor_, &constructor);
778 if (IMG_IS_OK(status)) {
779 sImgSrc_ = std::move(imageSource);
780 status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
781 }
782 if (!IMG_IS_OK(status)) {
783 HiLog::Error(LABEL, "New instance could not be obtained");
784 napi_get_undefined(env, &result);
785 }
786 return result;
787 }
788
CreateImageSourceComplete(napi_env env,napi_status status,void * data)789 napi_value ImageSourceNapi::CreateImageSourceComplete(napi_env env, napi_status status, void *data)
790 {
791 napi_value constructor = nullptr;
792 napi_value result = nullptr;
793
794 HiLog::Debug(LABEL, "CreateImageSourceComplete IN");
795 auto context = static_cast<ImageSourceAsyncContext*>(data);
796 if (context == nullptr) {
797 return result;
798 }
799 status = napi_get_reference_value(env, sConstructor_, &constructor);
800 if (IMG_IS_OK(status)) {
801 sImgSrc_ = context->rImageSource;
802 status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
803 }
804
805 if (!IMG_IS_OK(status)) {
806 context->status = ERROR;
807 HiLog::Error(LABEL, "New instance could not be obtained");
808 napi_get_undefined(env, &result);
809 }
810 return result;
811 }
812
CreateIncrementalSource(napi_env env,napi_callback_info info)813 napi_value ImageSourceNapi::CreateIncrementalSource(napi_env env, napi_callback_info info)
814 {
815 napi_value globalValue;
816 napi_get_global(env, &globalValue);
817 napi_value func;
818 napi_get_named_property(env, globalValue, "requireNapi", &func);
819
820 napi_value imageInfo;
821 napi_create_string_utf8(env, "multimedia.image", NAPI_AUTO_LENGTH, &imageInfo);
822 napi_value funcArgv[1] = { imageInfo };
823 napi_value returnValue;
824 napi_call_function(env, globalValue, func, 1, funcArgv, &returnValue);
825
826 napi_value result = nullptr;
827 napi_get_undefined(env, &result);
828
829 napi_status status;
830 HiLog::Debug(LABEL, "CreateIncrementalSource IN");
831
832 napi_value thisVar = nullptr;
833 napi_value argValue[NUM_2] = {0};
834 size_t argCount = NUM_2;
835 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
836 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
837
838 uint32_t errorCode = 0;
839 IncrementalSourceOptions incOpts;
840 if (argCount == NUM_2) {
841 parseSourceOptions(env, argValue[NUM_1], &(incOpts.sourceOptions));
842 }
843
844 incOpts.incrementalMode = IncrementalMode::INCREMENTAL_DATA;
845 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateIncrementalImageSource(incOpts, errorCode);
846 DecodeOptions decodeOpts;
847 std::unique_ptr<IncrementalPixelMap> incPixelMap = imageSource->CreateIncrementalPixelMap(0, decodeOpts, errorCode);
848 HiLog::Debug(LABEL, "CreateIncrementalImageSource end");
849 if (errorCode != SUCCESS) {
850 HiLog::Error(LABEL, "CreateIncrementalImageSource error");
851 napi_get_undefined(env, &result);
852 return result;
853 }
854 napi_value constructor = nullptr;
855 status = napi_get_reference_value(env, sConstructor_, &constructor);
856 if (IMG_IS_OK(status)) {
857 sImgSrc_ = std::move(imageSource);
858 sIncPixelMap_ = std::move(incPixelMap);
859 status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
860 }
861 if (!IMG_IS_OK(status)) {
862 HiLog::Error(LABEL, "New instance could not be obtained");
863 napi_get_undefined(env, &result);
864 }
865 return result;
866 }
867
GetImageInfo(napi_env env,napi_callback_info info)868 napi_value ImageSourceNapi::GetImageInfo(napi_env env, napi_callback_info info)
869 {
870 StartTrace(HITRACE_TAG_ZIMAGE, "GetImageInfo");
871 napi_value result = nullptr;
872 napi_get_undefined(env, &result);
873
874 int32_t refCount = 1;
875 napi_status status;
876 napi_value thisVar = nullptr;
877 napi_value argValue[NUM_2] = {0};
878 size_t argCount = 2;
879 HiLog::Debug(LABEL, "GetImageInfo IN");
880 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
881 HiLog::Debug(LABEL, "GetImageInfo argCount is [%{public}zu]", argCount);
882
883 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
884
885 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
886 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
887
888 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_),
889 nullptr, HiLog::Error(LABEL, "fail to unwrap context"));
890
891 asyncContext->rImageSource = asyncContext->constructor_->nativeImgSrc;
892
893 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rImageSource),
894 nullptr, HiLog::Error(LABEL, "empty native pixelmap"));
895 HiLog::Debug(LABEL, "GetImageInfo argCount is [%{public}zu]", argCount);
896 if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_function) {
897 HiLog::Debug(LABEL, "GetImageInfo arg0 getType is [%{public}u]", ImageNapiUtils::getType(env, argValue[NUM_0]));
898 napi_create_reference(env, argValue[NUM_0], refCount, &asyncContext->callbackRef);
899 } else if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_number) {
900 napi_get_value_uint32(env, argValue[NUM_0], &asyncContext->index);
901 } else if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_number
902 && ImageNapiUtils::getType(env, argValue[NUM_1]) == napi_function) {
903 HiLog::Debug(LABEL, "GetImageInfo arg0 getType is [%{public}u]", ImageNapiUtils::getType(env, argValue[NUM_0]));
904 HiLog::Debug(LABEL, "GetImageInfo arg1 getType is [%{public}u]", ImageNapiUtils::getType(env, argValue[NUM_1]));
905 napi_get_value_uint32(env, argValue[NUM_0], &asyncContext->index);
906 napi_create_reference(env, argValue[NUM_1], refCount, &asyncContext->callbackRef);
907 }
908
909 if (asyncContext->callbackRef == nullptr) {
910 napi_create_promise(env, &(asyncContext->deferred), &result);
911 } else {
912 napi_get_undefined(env, &result);
913 }
914
915 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageInfo",
916 [](napi_env env, void *data) {
917 auto context = static_cast<ImageSourceAsyncContext*>(data);
918 int index = (context->index >= NUM_0) ? context->index : NUM_0;
919 context->status = context->rImageSource->GetImageInfo(index, context->imageInfo);
920 }, GetImageInfoComplete, asyncContext, asyncContext->work);
921
922 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
923 nullptr, HiLog::Error(LABEL, "fail to create async work"));
924 FinishTrace(HITRACE_TAG_ZIMAGE);
925 return result;
926 }
927
CreatePixelMapExecute(napi_env env,void * data)928 static void CreatePixelMapExecute(napi_env env, void *data)
929 {
930 HiLog::Debug(LABEL, "CreatePixelMapExecute IN");
931 if (data == nullptr) {
932 HiLog::Error(LABEL, "data is nullptr");
933 return;
934 }
935 uint32_t errorCode = 0;
936 auto context = static_cast<ImageSourceAsyncContext*>(data);
937 if (context == nullptr) {
938 HiLog::Error(LABEL, "empty context");
939 return;
940 }
941
942 if (context->errMsg.size() > 0) {
943 HiLog::Error(LABEL, "mismatch args");
944 context->status = ERROR;
945 return;
946 }
947
948 if (context->rImageSource == nullptr) {
949 HiLog::Error(LABEL, "empty context rImageSource");
950 return;
951 }
952
953 if (context->constructor_ != nullptr) {
954 auto incPixelMap = context->constructor_->GetIncrementalPixelMap();
955 if (incPixelMap != nullptr) {
956 HiLog::Info(LABEL, "Get Incremental PixelMap!!!");
957 context->rPixelMap = incPixelMap;
958 }
959 } else {
960 HiLog::Info(LABEL, "Create PixelMap!!!");
961 }
962 if (context->rPixelMap == nullptr) {
963 int index = (context->index >= NUM_0) ? context->index : NUM_0;
964 context->rPixelMap = context->rImageSource->CreatePixelMapEx(index, context->decodeOpts, errorCode);
965 }
966
967 if (IMG_NOT_NULL(context->rPixelMap)) {
968 context->status = SUCCESS;
969 } else {
970 context->status = ERROR;
971 context->errMsg = "Create PixelMap error";
972 HiLog::Error(LABEL, "Create PixelMap error");
973 }
974 HiLog::Debug(LABEL, "CreatePixelMapExecute OUT");
975 }
976
CreatePixelMapComplete(napi_env env,napi_status status,void * data)977 static void CreatePixelMapComplete(napi_env env, napi_status status, void *data)
978 {
979 HiLog::Debug(LABEL, "CreatePixelMapComplete IN");
980 napi_value result = nullptr;
981 auto context = static_cast<ImageSourceAsyncContext*>(data);
982
983 if (context->status == SUCCESS) {
984 result = PixelMapNapi::CreatePixelMap(env, context->rPixelMap);
985 } else {
986 napi_get_undefined(env, &result);
987 }
988 HiLog::Debug(LABEL, "CreatePixelMapComplete OUT");
989 ImageSourceCallbackRoutine(env, context, result);
990 }
991
CreatePixelMap(napi_env env,napi_callback_info info)992 napi_value ImageSourceNapi::CreatePixelMap(napi_env env, napi_callback_info info)
993 {
994 napi_value result = nullptr;
995 napi_get_undefined(env, &result);
996
997 int32_t refCount = 1;
998 napi_status status;
999 napi_value thisVar = nullptr;
1000 napi_value argValue[NUM_2] = {0};
1001 size_t argCount = NUM_2;
1002 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1003 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, thisVar), nullptr, HiLog::Error(LABEL, "fail to get thisVar"));
1004 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
1005
1006 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
1007
1008 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
1009 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_),
1010 nullptr, HiLog::Error(LABEL, "fail to unwrap context"));
1011 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_->nativeImgSrc),
1012 nullptr, HiLog::Error(LABEL, "fail to unwrap nativeImgSrc"));
1013 asyncContext->rImageSource = asyncContext->constructor_->nativeImgSrc;
1014 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rImageSource),
1015 nullptr, HiLog::Error(LABEL, "empty native rImageSource"));
1016
1017 if (argCount == NUM_0) {
1018 HiLog::Debug(LABEL, "CreatePixelMap with no arg");
1019 } else if (argCount == NUM_1 || argCount == NUM_2) {
1020 if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_object) {
1021 if (!ParseDecodeOptions(env, argValue[NUM_0], &(asyncContext->decodeOpts),
1022 &(asyncContext->index), asyncContext->errMsg)) {
1023 HiLog::Error(LABEL, "DecodeOptions mismatch");
1024 }
1025 }
1026 if (ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1027 napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1028 }
1029 } else {
1030 HiLog::Error(LABEL, "argCount mismatch");
1031 return result;
1032 }
1033 if (asyncContext->callbackRef == nullptr) {
1034 napi_create_promise(env, &(asyncContext->deferred), &result);
1035 } else {
1036 napi_get_undefined(env, &result);
1037 }
1038
1039 ImageNapiUtils::HicheckerReport();
1040 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePixelMap", CreatePixelMapExecute,
1041 CreatePixelMapComplete, asyncContext, asyncContext->work);
1042
1043 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1044 nullptr, HiLog::Error(LABEL, "fail to create async work"));
1045 return result;
1046 }
1047
ParsePropertyOptions(napi_env env,napi_value root,ImageSourceAsyncContext * context)1048 static bool ParsePropertyOptions(napi_env env, napi_value root, ImageSourceAsyncContext* context)
1049 {
1050 napi_value tmpValue = nullptr;
1051 if (!GET_UINT32_BY_NAME(root, "index", context->index)) {
1052 HiLog::Debug(LABEL, "no index");
1053 return false;
1054 }
1055 if (!GET_NODE_BY_NAME(root, "defaultValue", tmpValue)) {
1056 HiLog::Debug(LABEL, "no defaultValue");
1057 } else {
1058 if (tmpValue != nullptr) {
1059 context->defaultValueStr = GetStringArgument(env, tmpValue);
1060 }
1061 }
1062 return true;
1063 }
1064
ModifyImagePropertyComplete(napi_env env,napi_status status,ImageSourceAsyncContext * context)1065 static void ModifyImagePropertyComplete(napi_env env, napi_status status, ImageSourceAsyncContext *context)
1066 {
1067 if (context == nullptr) {
1068 HiLog::Error(LABEL, "context is nullptr");
1069 return;
1070 }
1071
1072 napi_value result[NUM_2] = {0};
1073 napi_get_undefined(env, &result[NUM_0]);
1074 napi_get_undefined(env, &result[NUM_1]);
1075 napi_value retVal;
1076 napi_value callback = nullptr;
1077 if (context->status == ERR_MEDIA_WRITE_PARCEL_FAIL) {
1078 if (context->fdIndex != -1) {
1079 ImageNapiUtils::CreateErrorObj(env, result[0], context->status,
1080 "Create Fd without write permission!");
1081 }
1082 } else if (context->status == ERR_MEDIA_OUT_OF_RANGE) {
1083 ImageNapiUtils::CreateErrorObj(env, result[0], context->status,
1084 "The given buffer size is too small to add new exif data!");
1085 } else if (context->status == ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
1086 ImageNapiUtils::CreateErrorObj(env, result[0], context->status,
1087 "The exif data format is not standard, so modify it failed!");
1088 } else if (context->status == ERR_MEDIA_VALUE_INVALID) {
1089 ImageNapiUtils::CreateErrorObj(env, result[0], context->status, context->errMsg);
1090 }
1091
1092 if (context->deferred) {
1093 if (context->status == SUCCESS) {
1094 napi_resolve_deferred(env, context->deferred, result[NUM_1]);
1095 } else {
1096 napi_reject_deferred(env, context->deferred, result[NUM_0]);
1097 }
1098 } else {
1099 HiLog::Debug(LABEL, "call callback function");
1100 napi_get_reference_value(env, context->callbackRef, &callback);
1101 napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
1102 napi_delete_reference(env, context->callbackRef);
1103 }
1104
1105 napi_delete_async_work(env, context->work);
1106
1107 delete context;
1108 context = nullptr;
1109 }
1110
GetImagePropertyComplete(napi_env env,napi_status status,ImageSourceAsyncContext * context)1111 static void GetImagePropertyComplete(napi_env env, napi_status status, ImageSourceAsyncContext *context)
1112 {
1113 if (context == nullptr) {
1114 HiLog::Error(LABEL, "context is nullptr");
1115 return;
1116 }
1117
1118 napi_value result[NUM_2] = {0};
1119 napi_value retVal;
1120 napi_value callback = nullptr;
1121
1122 napi_get_undefined(env, &result[NUM_0]);
1123 napi_get_undefined(env, &result[NUM_1]);
1124
1125 if (context->status == SUCCESS) {
1126 napi_create_string_utf8(env, context->valueStr.c_str(), context->valueStr.length(), &result[NUM_1]);
1127 } else if (context->status == ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
1128 ImageNapiUtils::CreateErrorObj(env, result[0], context->status, "Unsupport EXIF info key!");
1129 } else {
1130 ImageNapiUtils::CreateErrorObj(env, result[0], context->status, "There is generic napi failure!");
1131 }
1132
1133 if (context->deferred) {
1134 if (context->status == SUCCESS) {
1135 napi_resolve_deferred(env, context->deferred, result[NUM_1]);
1136 } else {
1137 napi_reject_deferred(env, context->deferred, result[NUM_0]);
1138 }
1139 } else {
1140 HiLog::Debug(LABEL, "call callback function");
1141 napi_get_reference_value(env, context->callbackRef, &callback);
1142 napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
1143 napi_delete_reference(env, context->callbackRef);
1144 }
1145
1146 napi_delete_async_work(env, context->work);
1147 delete context;
1148 context = nullptr;
1149 }
1150
UnwrapContext(napi_env env,napi_callback_info info)1151 static std::unique_ptr<ImageSourceAsyncContext> UnwrapContext(napi_env env, napi_callback_info info)
1152 {
1153 int32_t refCount = 1;
1154 napi_status status;
1155 napi_value thisVar = nullptr;
1156 napi_value argValue[NUM_3] = {0};
1157 size_t argCount = NUM_3;
1158 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1159 HiLog::Debug(LABEL, "GetImageProperty argCount is [%{public}zu]", argCount);
1160
1161 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
1162
1163 std::unique_ptr<ImageSourceAsyncContext> context = std::make_unique<ImageSourceAsyncContext>();
1164 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&context->constructor_));
1165
1166 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_),
1167 nullptr, HiLog::Error(LABEL, "fail to unwrap context"));
1168
1169 context->rImageSource = context->constructor_->nativeImgSrc;
1170
1171 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->rImageSource),
1172 nullptr, HiLog::Error(LABEL, "empty native rImageSource"));
1173
1174 if (argCount < NUM_1 || argCount > NUM_3) {
1175 HiLog::Error(LABEL, "argCount missmatch");
1176 return nullptr;
1177 }
1178 if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_string) {
1179 context->keyStr = GetStringArgument(env, argValue[NUM_0]);
1180 } else {
1181 HiLog::Error(LABEL, "arg 0 type missmatch");
1182 return nullptr;
1183 }
1184 if (argCount == NUM_2 || argCount == NUM_3) {
1185 if (ImageNapiUtils::getType(env, argValue[NUM_1]) == napi_object) {
1186 IMG_NAPI_CHECK_RET_D(ParsePropertyOptions(env, argValue[NUM_1], context.get()),
1187 nullptr, HiLog::Error(LABEL, "PropertyOptions mismatch"));
1188 }
1189 if (ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1190 napi_create_reference(env, argValue[argCount - 1], refCount, &context->callbackRef);
1191 }
1192 }
1193 return context;
1194 }
1195
CheckExifDataValue(const std::string & key,const std::string & value,std::string & errorInfo)1196 static bool CheckExifDataValue(const std::string &key, const std::string &value, std::string &errorInfo)
1197 {
1198 if (IsSameTextStr(key, "BitsPerSample")) {
1199 std::vector<std::string> bitsVec;
1200 SplitStr(value, ",", bitsVec);
1201 if (bitsVec.size() > NUM_2) {
1202 errorInfo = "BitsPerSample has invalid exif value: ";
1203 errorInfo.append(value);
1204 return false;
1205 }
1206 for (size_t i = 0; i < bitsVec.size(); i++) {
1207 if (!IsNumericStr(bitsVec[i])) {
1208 errorInfo = "BitsPerSample has invalid exif value: ";
1209 errorInfo.append(bitsVec[i]);
1210 return false;
1211 }
1212 }
1213 } else if (IsSameTextStr(key, "Orientation")) {
1214 if (!IsNumericStr(value) || atoi(value.c_str()) < 1 || static_cast<uint32_t>(atoi(value.c_str())) > NUM_8) {
1215 errorInfo = "Orientation has invalid exif value: ";
1216 errorInfo.append(value);
1217 return false;
1218 }
1219 } else if (IsSameTextStr(key, "ImageLength") || IsSameTextStr(key, "ImageWidth")) {
1220 if (!IsNumericStr(value)) {
1221 errorInfo = "ImageLength or ImageWidth has invalid exif value: ";
1222 errorInfo.append(value);
1223 return false;
1224 }
1225 } else if (IsSameTextStr(key, "GPSLatitude") || IsSameTextStr(key, "GPSLongitude")) {
1226 std::vector<std::string> gpsVec;
1227 SplitStr(value, ",", gpsVec);
1228 if (gpsVec.size() != NUM_2) {
1229 errorInfo = "GPSLatitude or GPSLongitude has invalid exif value: ";
1230 errorInfo.append(value);
1231 return false;
1232 }
1233
1234 for (size_t i = 0; i < gpsVec.size(); i++) {
1235 if (!IsNumericStr(gpsVec[i])) {
1236 errorInfo = "GPSLatitude or GPSLongitude has invalid exif value: ";
1237 errorInfo.append(gpsVec[i]);
1238 return false;
1239 }
1240 }
1241 } else if (IsSameTextStr(key, "GPSLatitudeRef")) {
1242 if (!IsSameTextStr(value, "N") && !IsSameTextStr(value, "S")) {
1243 errorInfo = "GPSLatitudeRef has invalid exif value: ";
1244 errorInfo.append(value);
1245 return false;
1246 }
1247 } else if (IsSameTextStr(key, "GPSLongitudeRef")) {
1248 if (!IsSameTextStr(value, "W") && !IsSameTextStr(value, "E")) {
1249 errorInfo = "GPSLongitudeRef has invalid exif value: ";
1250 errorInfo.append(value);
1251 return false;
1252 }
1253 }
1254 return true;
1255 }
1256
UnwrapContextForModify(napi_env env,napi_callback_info info)1257 static std::unique_ptr<ImageSourceAsyncContext> UnwrapContextForModify(napi_env env,
1258 napi_callback_info info)
1259 {
1260 int32_t refCount = 1;
1261 napi_status status;
1262 napi_value thisVar = nullptr;
1263 napi_value argValue[NUM_4] = {0};
1264 size_t argCount = NUM_4;
1265 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1266 HiLog::Debug(LABEL, "UnwrapContextForModify argCount is [%{public}zu]", argCount);
1267
1268 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
1269
1270 std::unique_ptr<ImageSourceAsyncContext> context = std::make_unique<ImageSourceAsyncContext>();
1271 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&context->constructor_));
1272
1273 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_),
1274 nullptr, HiLog::Error(LABEL, "fail to unwrap context"));
1275
1276 context->rImageSource = context->constructor_->nativeImgSrc;
1277
1278 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->rImageSource),
1279 nullptr, HiLog::Error(LABEL, "empty native rImageSource"));
1280 if (argCount < NUM_1 || argCount > NUM_4) {
1281 HiLog::Error(LABEL, "argCount missmatch");
1282 return nullptr;
1283 }
1284 if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_string) {
1285 context->keyStr = GetStringArgument(env, argValue[NUM_0]);
1286 } else {
1287 HiLog::Error(LABEL, "arg 0 type missmatch");
1288 return nullptr;
1289 }
1290 if (ImageNapiUtils::getType(env, argValue[NUM_1]) == napi_string) {
1291 context->valueStr = GetStringArgument(env, argValue[NUM_1]);
1292 } else {
1293 HiLog::Error(LABEL, "arg 1 type missmatch");
1294 return nullptr;
1295 }
1296 if (argCount == NUM_3 || argCount == NUM_4) {
1297 if (ImageNapiUtils::getType(env, argValue[NUM_2]) == napi_object) {
1298 IMG_NAPI_CHECK_RET_D(ParsePropertyOptions(env, argValue[NUM_2], context.get()),
1299 nullptr, HiLog::Error(LABEL, "PropertyOptions mismatch"));
1300 }
1301 if (ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1302 napi_create_reference(env, argValue[argCount - 1], refCount, &context->callbackRef);
1303 }
1304 }
1305 context->pathName = ImageSourceNapi::filePath_;
1306 context->fdIndex = ImageSourceNapi::fileDescriptor_;
1307 context->sourceBuffer = ImageSourceNapi::fileBuffer_;
1308 context->sourceBufferSize = ImageSourceNapi::fileBufferSize_;
1309 return context;
1310 }
1311
ModifyImageProperty(napi_env env,napi_callback_info info)1312 napi_value ImageSourceNapi::ModifyImageProperty(napi_env env, napi_callback_info info)
1313 {
1314 napi_value result = nullptr;
1315 napi_get_undefined(env, &result);
1316
1317 napi_status status;
1318 std::unique_ptr<ImageSourceAsyncContext> asyncContext = UnwrapContextForModify(env, info);
1319 if (asyncContext == nullptr) {
1320 return ImageNapiUtils::ThrowExceptionError(env, static_cast<int32_t>(napi_invalid_arg),
1321 "async context unwrap failed");
1322 }
1323
1324 if (asyncContext->callbackRef == nullptr) {
1325 napi_create_promise(env, &(asyncContext->deferred), &result);
1326 } else {
1327 napi_get_undefined(env, &result);
1328 }
1329
1330 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ModifyImageProperty",
1331 [](napi_env env, void *data) {
1332 auto context = static_cast<ImageSourceAsyncContext*>(data);
1333
1334 if (!CheckExifDataValue(context->keyStr, context->valueStr, context->errMsg)) {
1335 HiLog::Error(LABEL, "There is invalid exif data parameter");
1336 context->status = ERR_MEDIA_VALUE_INVALID;
1337 return;
1338 }
1339 if (!IsSameTextStr(context->pathName, "")) {
1340 context->status = context->rImageSource->ModifyImageProperty(context->index,
1341 context->keyStr, context->valueStr, context->pathName);
1342 } else if (context->fdIndex != -1) {
1343 context->status = context->rImageSource->ModifyImageProperty(context->index,
1344 context->keyStr, context->valueStr, context->fdIndex);
1345 } else if (context->sourceBuffer != nullptr) {
1346 context->status = context->rImageSource->ModifyImageProperty(context->index,
1347 context->keyStr, context->valueStr, static_cast<uint8_t *>(context->sourceBuffer),
1348 context->sourceBufferSize);
1349 } else {
1350 HiLog::Error(LABEL, "There is no image source!");
1351 }
1352 },
1353 reinterpret_cast<napi_async_complete_callback>(ModifyImagePropertyComplete),
1354 asyncContext,
1355 asyncContext->work);
1356
1357 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1358 nullptr, HiLog::Error(LABEL, "fail to create async work"));
1359 return result;
1360 }
1361
GetImageProperty(napi_env env,napi_callback_info info)1362 napi_value ImageSourceNapi::GetImageProperty(napi_env env, napi_callback_info info)
1363 {
1364 StartTrace(HITRACE_TAG_ZIMAGE, "GetImageProperty");
1365 napi_value result = nullptr;
1366 napi_get_undefined(env, &result);
1367
1368 napi_status status;
1369 std::unique_ptr<ImageSourceAsyncContext> asyncContext = UnwrapContext(env, info);
1370 if (asyncContext == nullptr) {
1371 return ImageNapiUtils::ThrowExceptionError(env, static_cast<int32_t>(napi_invalid_arg),
1372 "async context unwrap failed");
1373 }
1374
1375 if (asyncContext->callbackRef == nullptr) {
1376 napi_create_promise(env, &(asyncContext->deferred), &result);
1377 } else {
1378 napi_get_undefined(env, &result);
1379 }
1380
1381 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageProperty",
1382 [](napi_env env, void *data) {
1383 auto context = static_cast<ImageSourceAsyncContext*>(data);
1384 context->status = context->rImageSource->GetImagePropertyString(context->index,
1385 context->keyStr,
1386 context->valueStr);
1387 },
1388 reinterpret_cast<napi_async_complete_callback>(GetImagePropertyComplete),
1389 asyncContext,
1390 asyncContext->work);
1391
1392 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1393 nullptr, HiLog::Error(LABEL, "fail to create async work"));
1394 FinishTrace(HITRACE_TAG_ZIMAGE);
1395 return result;
1396 }
1397
UpdateDataExecute(napi_env env,void * data)1398 static void UpdateDataExecute(napi_env env, void *data)
1399 {
1400 auto context = static_cast<ImageSourceAsyncContext*>(data);
1401 uint8_t *buffer = static_cast<uint8_t*>(context->updataBuffer);
1402 if (context->updataBufferOffset < context->updataBufferSize) {
1403 buffer = buffer + context->updataBufferOffset;
1404 }
1405
1406 uint32_t lastSize = context->updataBufferSize - context->updataBufferOffset;
1407 uint32_t size = context->updataLength < lastSize ? context->updataLength : lastSize;
1408
1409 uint32_t res = context->rImageSource->UpdateData(buffer, size,
1410 context->isCompleted);
1411 context->isSuccess = res == 0;
1412 if (context->isSuccess && context->constructor_ != nullptr) {
1413 auto incPixelMap = context->constructor_->GetIncrementalPixelMap();
1414 if (incPixelMap != nullptr) {
1415 uint8_t decodeProgress = 0;
1416 uint32_t err = incPixelMap->PromoteDecoding(decodeProgress);
1417 if (!(err == SUCCESS || (err == ERR_IMAGE_SOURCE_DATA_INCOMPLETE && !context->isCompleted))) {
1418 HiLog::Error(LABEL, "UpdateData PromoteDecoding error");
1419 context->isSuccess = false;
1420 }
1421 if (context->isCompleted) {
1422 incPixelMap->DetachFromDecoding();
1423 }
1424 }
1425 }
1426 }
1427
UpdateDataComplete(napi_env env,napi_status status,void * data)1428 static void UpdateDataComplete(napi_env env, napi_status status, void *data)
1429 {
1430 napi_value result = nullptr;
1431 napi_create_object(env, &result);
1432
1433 auto context = static_cast<ImageSourceAsyncContext*>(data);
1434
1435 napi_get_boolean(env, context->isSuccess, &result);
1436 ImageSourceCallbackRoutine(env, context, result);
1437 }
1438
isNapiTypedArray(napi_env env,napi_value val)1439 static bool isNapiTypedArray(napi_env env, napi_value val)
1440 {
1441 bool res = false;
1442 napi_is_typedarray(env, val, &res);
1443 HiLog::Debug(LABEL, "isNapiTypedArray %{public}d", res);
1444 return res;
1445 }
1446
UpdateData(napi_env env,napi_callback_info info)1447 napi_value ImageSourceNapi::UpdateData(napi_env env, napi_callback_info info)
1448 {
1449 napi_value result = nullptr;
1450 napi_get_undefined(env, &result);
1451
1452 int32_t refCount = 1;
1453 napi_status status;
1454 napi_value thisVar = nullptr;
1455 napi_value argValue[NUM_5] = {0};
1456 size_t argCount = 5;
1457 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1458 HiLog::Debug(LABEL, "UpdateData argCount is [%{public}zu]", argCount);
1459
1460 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
1461
1462 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
1463 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
1464
1465 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_),
1466 nullptr, HiLog::Error(LABEL, "fail to unwrap context"));
1467
1468 asyncContext->rImageSource = asyncContext->constructor_->nativeImgSrc;
1469
1470 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rImageSource),
1471 nullptr, HiLog::Error(LABEL, "empty native rImageSource"));
1472 HiLog::Debug(LABEL, "UpdateData argCount %{public}zu", argCount);
1473 if (argCount > NUM_0 && isNapiTypedArray(env, argValue[NUM_0])) {
1474 HiLog::Error(LABEL, "UpdateData napi_get_arraybuffer_info ");
1475 napi_typedarray_type type;
1476 napi_value arraybuffer;
1477 size_t offset;
1478 status = napi_get_typedarray_info(env, argValue[NUM_0], &type,
1479 &(asyncContext->updataBufferSize), &(asyncContext->updataBuffer),
1480 &arraybuffer, &offset);
1481 }
1482
1483 if (argCount >= NUM_2 && ImageNapiUtils::getType(env, argValue[NUM_1]) == napi_boolean) {
1484 status = napi_get_value_bool(env, argValue[NUM_1], &(asyncContext->isCompleted));
1485 }
1486
1487 if (argCount >= NUM_3 && ImageNapiUtils::getType(env, argValue[NUM_2]) == napi_number) {
1488 asyncContext->updataBufferOffset = 0;
1489 status = napi_get_value_uint32(env, argValue[NUM_2], &(asyncContext->updataBufferOffset));
1490 HiLog::Debug(LABEL, "asyncContext->updataBufferOffset is [%{public}u]", asyncContext->updataBufferOffset);
1491 }
1492
1493 if (argCount >= NUM_4 && ImageNapiUtils::getType(env, argValue[NUM_3]) == napi_number) {
1494 asyncContext->updataLength = 0;
1495 status = napi_get_value_uint32(env, argValue[NUM_3], &(asyncContext->updataLength));
1496 HiLog::Debug(LABEL, "asyncContext->updataLength is [%{public}u]", asyncContext->updataLength);
1497 }
1498
1499 if (!IMG_IS_OK(status)) {
1500 HiLog::Error(LABEL, "fail to UpdateData");
1501 napi_get_undefined(env, &result);
1502 return result;
1503 }
1504
1505 if (argCount == NUM_5 && ImageNapiUtils::getType(env, argValue[NUM_4]) == napi_function) {
1506 napi_create_reference(env, argValue[NUM_4], refCount, &asyncContext->callbackRef);
1507 }
1508
1509 if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[NUM_2]) == napi_function) {
1510 napi_create_reference(env, argValue[NUM_2], refCount, &asyncContext->callbackRef);
1511 }
1512
1513 if (asyncContext->callbackRef == nullptr) {
1514 napi_create_promise(env, &(asyncContext->deferred), &result);
1515 } else {
1516 napi_get_undefined(env, &result);
1517 }
1518
1519 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "UpdateData",
1520 UpdateDataExecute, UpdateDataComplete, asyncContext, asyncContext->work);
1521
1522 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1523 nullptr, HiLog::Error(LABEL, "fail to create async work"));
1524 return result;
1525 }
1526
ReleaseComplete(napi_env env,napi_status status,void * data)1527 static void ReleaseComplete(napi_env env, napi_status status, void *data)
1528 {
1529 napi_value result = nullptr;
1530 napi_get_undefined(env, &result);
1531
1532 auto context = static_cast<ImageSourceAsyncContext*>(data);
1533 delete context->constructor_;
1534 context->constructor_ = nullptr;
1535 ImageSourceCallbackRoutine(env, context, result);
1536 }
1537
Release(napi_env env,napi_callback_info info)1538 napi_value ImageSourceNapi::Release(napi_env env, napi_callback_info info)
1539 {
1540 HiLog::Debug(LABEL, "Release enter");
1541 napi_value result = nullptr;
1542 napi_get_undefined(env, &result);
1543
1544 int32_t refCount = 1;
1545 napi_status status;
1546 napi_value thisVar = nullptr;
1547 napi_value argValue[NUM_1] = {0};
1548 size_t argCount = 1;
1549
1550 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1551 HiLog::Debug(LABEL, "Release argCount is [%{public}zu]", argCount);
1552 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
1553
1554 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
1555 status = napi_remove_wrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
1556
1557 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_), result,
1558 HiLog::Error(LABEL, "fail to unwrap context"));
1559
1560 HiLog::Debug(LABEL, "Release argCount is [%{public}zu]", argCount);
1561 if (argCount == 1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_function) {
1562 napi_create_reference(env, argValue[NUM_0], refCount, &asyncContext->callbackRef);
1563 }
1564
1565 if (asyncContext->callbackRef == nullptr) {
1566 napi_create_promise(env, &(asyncContext->deferred), &result);
1567 }
1568
1569 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "Release",
1570 [](napi_env env, void *data) {}, ReleaseComplete, asyncContext, asyncContext->work);
1571 HiLog::Debug(LABEL, "Release exit");
1572 return result;
1573 }
1574
release()1575 void ImageSourceNapi::release()
1576 {
1577 if (!isRelease) {
1578 if (nativeImgSrc != nullptr) {
1579 nativeImgSrc = nullptr;
1580 }
1581 isRelease = true;
1582 }
1583 }
1584
UnwrapContextForList(napi_env env,napi_callback_info info)1585 static std::unique_ptr<ImageSourceAsyncContext> UnwrapContextForList(napi_env env, napi_callback_info info)
1586 {
1587 int32_t refCount = 1;
1588 napi_status status;
1589 napi_value thisVar = nullptr;
1590 napi_value argValue[NUM_3] = {0};
1591 size_t argCount = NUM_3;
1592
1593 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1594 HiLog::Debug(LABEL, "UnwrapContextForList argCount is [%{public}zu]", argCount);
1595
1596 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
1597
1598 std::unique_ptr<ImageSourceAsyncContext> context = std::make_unique<ImageSourceAsyncContext>();
1599 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&context->constructor_));
1600
1601 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_),
1602 nullptr, HiLog::Error(LABEL, "fail to unwrap context"));
1603
1604 context->rImageSource = context->constructor_->nativeImgSrc;
1605
1606 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->rImageSource),
1607 nullptr, HiLog::Error(LABEL, "empty native rImageSource"));
1608
1609 if (argCount > NUM_2) {
1610 HiLog::Error(LABEL, "argCount missmatch");
1611 return nullptr;
1612 }
1613
1614 if (argCount > NUM_0) {
1615 if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_object) {
1616 HiLog::Debug(LABEL, "UnwrapContextForList object");
1617 if (!ParseDecodeOptions(env, argValue[NUM_0], &(context->decodeOpts),
1618 &(context->index), context->errMsg)) {
1619 HiLog::Error(LABEL, "DecodeOptions mismatch");
1620 }
1621 }
1622
1623 if (ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1624 HiLog::Debug(LABEL, "UnwrapContextForList function");
1625 napi_create_reference(env, argValue[argCount - 1], refCount, &context->callbackRef);
1626 }
1627 }
1628
1629 return context;
1630 }
1631
CheckAsyncContext(ImageSourceAsyncContext * context,bool check)1632 static ImageSourceAsyncContext* CheckAsyncContext(ImageSourceAsyncContext* context, bool check)
1633 {
1634 if (context == nullptr) {
1635 HiLog::Error(LABEL, "context is nullptr");
1636 return nullptr;
1637 }
1638
1639 if (check) {
1640 if (context->errMsg.size() > 0) {
1641 HiLog::Error(LABEL, "mismatch args");
1642 context->status = ERROR;
1643 return nullptr;
1644 }
1645
1646 if (context->rImageSource == nullptr) {
1647 HiLog::Error(LABEL, "empty context rImageSource");
1648 return nullptr;
1649 }
1650 }
1651
1652 return context;
1653 }
1654
STATIC_EXEC_FUNC(CreatePixelMapList)1655 STATIC_EXEC_FUNC(CreatePixelMapList)
1656 {
1657 if (data == nullptr) {
1658 HiLog::Error(LABEL, "data is nullptr");
1659 return;
1660 }
1661
1662 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), true);
1663 if (context == nullptr) {
1664 HiLog::Error(LABEL, "check async context fail");
1665 return;
1666 }
1667
1668 context->pixelMaps = nullptr;
1669 uint32_t errorCode = 0;
1670 uint32_t frameCount = context->rImageSource->GetFrameCount(errorCode);
1671 if ((errorCode == SUCCESS) && (context->index >= NUM_0) && (context->index < frameCount)) {
1672 context->pixelMaps = context->rImageSource->CreatePixelMapList(context->decodeOpts, errorCode);
1673 }
1674 if ((errorCode == SUCCESS) && IMG_NOT_NULL(context->pixelMaps)) {
1675 context->status = SUCCESS;
1676 } else {
1677 HiLog::Error(LABEL, "Create PixelMap List error, error=%{public}u", errorCode);
1678 context->errMsg = "Create PixelMap List error";
1679 context->status = ERROR;
1680 }
1681 }
1682
STATIC_COMPLETE_FUNC(CreatePixelMapList)1683 STATIC_COMPLETE_FUNC(CreatePixelMapList)
1684 {
1685 if (data == nullptr) {
1686 HiLog::Error(LABEL, "data is nullptr");
1687 return;
1688 }
1689
1690 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), false);
1691 if (context == nullptr) {
1692 HiLog::Error(LABEL, "check async context fail");
1693 return;
1694 }
1695
1696 napi_value result = nullptr;
1697 if ((context->status == SUCCESS) && IMG_NOT_NULL(context->pixelMaps)) {
1698 HiLog::Debug(LABEL, "CreatePixelMapListComplete array");
1699 napi_create_array(env, &result);
1700 size_t i = 0;
1701 for (auto &pixelMap : *context->pixelMaps.get()) {
1702 auto napiPixelMap = PixelMapNapi::CreatePixelMap(env, std::move(pixelMap));
1703 napi_set_element(env, result, i, napiPixelMap);
1704 i++;
1705 }
1706 } else {
1707 HiLog::Debug(LABEL, "CreatePixelMapListComplete undefined");
1708 napi_get_undefined(env, &result);
1709 }
1710
1711 HiLog::Debug(LABEL, "CreatePixelMapListComplete set to nullptr");
1712 context->pixelMaps = nullptr;
1713
1714 ImageSourceCallbackRoutine(env, context, result);
1715 }
1716
CreatePixelMapList(napi_env env,napi_callback_info info)1717 napi_value ImageSourceNapi::CreatePixelMapList(napi_env env, napi_callback_info info)
1718 {
1719 StartTrace(HITRACE_TAG_ZIMAGE, "CreatePixelMapList");
1720
1721 auto asyncContext = UnwrapContextForList(env, info);
1722 if (asyncContext == nullptr) {
1723 return ImageNapiUtils::ThrowExceptionError(env, static_cast<int32_t>(napi_invalid_arg),
1724 "async context unwrap failed");
1725 }
1726
1727 napi_value result = nullptr;
1728 napi_get_undefined(env, &result);
1729 if (asyncContext->callbackRef == nullptr) {
1730 napi_create_promise(env, &(asyncContext->deferred), &result);
1731 } else {
1732 napi_get_undefined(env, &result);
1733 }
1734
1735 ImageNapiUtils::HicheckerReport();
1736
1737 napi_status status;
1738 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePixelMapList", CreatePixelMapListExec,
1739 CreatePixelMapListComplete, asyncContext, asyncContext->work);
1740 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to create async work"));
1741
1742 FinishTrace(HITRACE_TAG_ZIMAGE);
1743 return result;
1744 }
1745
STATIC_EXEC_FUNC(GetDelayTime)1746 STATIC_EXEC_FUNC(GetDelayTime)
1747 {
1748 if (data == nullptr) {
1749 HiLog::Error(LABEL, "data is nullptr");
1750 return;
1751 }
1752
1753 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), true);
1754 if (context == nullptr) {
1755 HiLog::Error(LABEL, "check async context fail");
1756 return;
1757 }
1758
1759 uint32_t errorCode = 0;
1760 context->delayTimes = context->rImageSource->GetDelayTime(errorCode);
1761 if ((errorCode == SUCCESS) && IMG_NOT_NULL(context->delayTimes)) {
1762 context->status = SUCCESS;
1763 } else {
1764 HiLog::Error(LABEL, "Get DelayTime error, error=%{public}u", errorCode);
1765 context->errMsg = "Get DelayTime error";
1766 context->status = errorCode;
1767 }
1768 }
1769
STATIC_COMPLETE_FUNC(GetDelayTime)1770 STATIC_COMPLETE_FUNC(GetDelayTime)
1771 {
1772 if (data == nullptr) {
1773 HiLog::Error(LABEL, "data is nullptr");
1774 return;
1775 }
1776
1777 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), false);
1778 if (context == nullptr) {
1779 HiLog::Error(LABEL, "check async context fail");
1780 return;
1781 }
1782
1783 napi_value result = nullptr;
1784 if (context->status == SUCCESS && IMG_NOT_NULL(context->delayTimes)) {
1785 HiLog::Debug(LABEL, "GetDelayTimeComplete array");
1786 napi_create_array(env, &result);
1787 size_t i = 0;
1788 for (auto delayTime : *context->delayTimes) {
1789 napi_value napiDelayTime = nullptr;
1790 napi_create_uint32(env, delayTime, &napiDelayTime);
1791 napi_set_element(env, result, i, napiDelayTime);
1792 i++;
1793 }
1794 } else {
1795 HiLog::Debug(LABEL, "GetDelayTimeComplete undefined");
1796 napi_get_undefined(env, &result);
1797 }
1798
1799 HiLog::Debug(LABEL, "GetDelayTimeComplete set to nullptr");
1800 context->delayTimes = nullptr;
1801 ImageSourceCallbackRoutine(env, context, result);
1802 }
1803
GetDelayTime(napi_env env,napi_callback_info info)1804 napi_value ImageSourceNapi::GetDelayTime(napi_env env, napi_callback_info info)
1805 {
1806 StartTrace(HITRACE_TAG_ZIMAGE, "GetDelayTime");
1807
1808 auto asyncContext = UnwrapContextForList(env, info);
1809 if (asyncContext == nullptr) {
1810 return ImageNapiUtils::ThrowExceptionError(env, ERR_IMAGE_DATA_ABNORMAL,
1811 "async context unwrap failed");
1812 }
1813
1814 napi_value result = nullptr;
1815 napi_get_undefined(env, &result);
1816 if (asyncContext->callbackRef == nullptr) {
1817 napi_create_promise(env, &(asyncContext->deferred), &result);
1818 } else {
1819 napi_get_undefined(env, &result);
1820 }
1821
1822 napi_status status;
1823 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetDelayTime", GetDelayTimeExec,
1824 GetDelayTimeComplete, asyncContext, asyncContext->work);
1825 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to create async work"));
1826
1827 FinishTrace(HITRACE_TAG_ZIMAGE);
1828 return result;
1829 }
1830
STATIC_EXEC_FUNC(GetFrameCount)1831 STATIC_EXEC_FUNC(GetFrameCount)
1832 {
1833 if (data == nullptr) {
1834 HiLog::Error(LABEL, "data is nullptr");
1835 return;
1836 }
1837
1838 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), true);
1839 if (context == nullptr) {
1840 HiLog::Error(LABEL, "check async context fail");
1841 return;
1842 }
1843
1844 uint32_t errorCode = 0;
1845 context->frameCount = context->rImageSource->GetFrameCount(errorCode);
1846 HiLog::Debug(LABEL, "GetFrameCountExec count=%{public}u, error=%{public}u", context->frameCount, errorCode);
1847 if (errorCode == SUCCESS) {
1848 context->status = SUCCESS;
1849 } else {
1850 HiLog::Error(LABEL, "Get FrameCount error, error=%{public}u", errorCode);
1851 context->errMsg = "Get FrameCount error";
1852 context->status = errorCode;
1853 }
1854 }
1855
STATIC_COMPLETE_FUNC(GetFrameCount)1856 STATIC_COMPLETE_FUNC(GetFrameCount)
1857 {
1858 if (data == nullptr) {
1859 HiLog::Error(LABEL, "data is nullptr");
1860 return;
1861 }
1862
1863 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), false);
1864 if (context == nullptr) {
1865 HiLog::Error(LABEL, "check async context fail");
1866 return;
1867 }
1868
1869 napi_value result = nullptr;
1870 if (context->status == SUCCESS) {
1871 HiLog::Debug(LABEL, "GetFrameCountComplete uint");
1872 napi_create_uint32(env, context->frameCount, &result);
1873 } else {
1874 HiLog::Debug(LABEL, "GetFrameCountComplete undefined");
1875 napi_get_undefined(env, &result);
1876 }
1877
1878 context->frameCount = 0;
1879 ImageSourceCallbackRoutine(env, context, result);
1880 }
1881
GetFrameCount(napi_env env,napi_callback_info info)1882 napi_value ImageSourceNapi::GetFrameCount(napi_env env, napi_callback_info info)
1883 {
1884 StartTrace(HITRACE_TAG_ZIMAGE, "GetFrameCount");
1885
1886 auto asyncContext = UnwrapContextForList(env, info);
1887 if (asyncContext == nullptr) {
1888 return ImageNapiUtils::ThrowExceptionError(env, ERR_IMAGE_DATA_ABNORMAL,
1889 "async context unwrap failed");
1890 }
1891
1892 napi_value result = nullptr;
1893 napi_get_undefined(env, &result);
1894 if (asyncContext->callbackRef == nullptr) {
1895 napi_create_promise(env, &(asyncContext->deferred), &result);
1896 } else {
1897 napi_get_undefined(env, &result);
1898 }
1899
1900 napi_status status;
1901 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetFrameCount", GetFrameCountExec,
1902 GetFrameCountComplete, asyncContext, asyncContext->work);
1903 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, HiLog::Error(LABEL, "fail to create async work"));
1904
1905 FinishTrace(HITRACE_TAG_ZIMAGE);
1906 return result;
1907 }
1908
CreateImageSourceNapi(napi_env env,napi_value * result)1909 int32_t ImageSourceNapi::CreateImageSourceNapi(napi_env env, napi_value* result)
1910 {
1911 napi_value constructor = nullptr;
1912 napi_status status = napi_ok;
1913 PrepareNapiEnv(env);
1914
1915 status = napi_get_reference_value(env, sConstructor_, &constructor);
1916 if (status == napi_ok && constructor != nullptr) {
1917 status = napi_new_instance(env, constructor, NUM_0, nullptr, result);
1918 }
1919
1920 if (status != napi_ok || result == nullptr) {
1921 HiLog::Error(LABEL, "CreateImageSourceNapi new instance failed");
1922 napi_get_undefined(env, result);
1923 return ERR_IMAGE_DATA_ABNORMAL;
1924 }
1925 return SUCCESS;
1926 }
1927
SetIncrementalPixelMap(std::shared_ptr<IncrementalPixelMap> incrementalPixelMap)1928 void ImageSourceNapi::SetIncrementalPixelMap(std::shared_ptr<IncrementalPixelMap> incrementalPixelMap)
1929 {
1930 navIncPixelMap_ = incrementalPixelMap;
1931 }
1932
SetNativeImageSource(std::shared_ptr<ImageSource> imageSource)1933 void ImageSourceNapi::SetNativeImageSource(std::shared_ptr<ImageSource> imageSource)
1934 {
1935 nativeImgSrc = imageSource;
1936 }
1937
SetImageResource(ImageResource resource)1938 void ImageSourceNapi::SetImageResource(ImageResource resource)
1939 {
1940 resource_.type = resource.type;
1941 resource_.fd = resource.fd;
1942 resource_.path = resource.path;
1943 resource_.buffer = resource.buffer;
1944 resource_.bufferSize = resource.bufferSize;
1945 }
1946
GetImageResource()1947 ImageResource ImageSourceNapi::GetImageResource()
1948 {
1949 return resource_;
1950 }
1951 } // namespace Media
1952 } // namespace OHOS
1953