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 "pixel_map_napi.h"
17 #include "media_errors.h"
18 #include "image_log.h"
19 #include "image_napi_utils.h"
20 #include "image_pixel_map_napi.h"
21 #include "image_source_napi.h"
22 #include "image_trace.h"
23 #include "log_tags.h"
24 #include "color_space_object_convertor.h"
25 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
26 #include <cstdint>
27 #include <regex>
28 #include <vector>
29 #include <memory>
30 #include "vpe_utils.h"
31 #include "napi_message_sequence.h"
32 #include "pixel_map_from_surface.h"
33 #include "transaction/rs_interfaces.h"
34 #include "color_utils.h"
35 #endif
36 #include "hitrace_meter.h"
37 #include "pixel_map.h"
38 #include "image_format_convert.h"
39 #include <securec.h>
40 
41 #undef LOG_DOMAIN
42 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
43 
44 #undef LOG_TAG
45 #define LOG_TAG "PixelMapNapi"
46 
47 namespace {
48     constexpr uint32_t NUM_0 = 0;
49     constexpr uint32_t NUM_1 = 1;
50     constexpr uint32_t NUM_2 = 2;
51     constexpr uint32_t NUM_3 = 3;
52     constexpr uint32_t NUM_4 = 4;
53 }
54 
55 enum class FormatType:int8_t {
56     UNKNOWN,
57     YUV,
58     RGB
59 };
60 
61 namespace OHOS {
62 namespace Media {
63 static const std::string CREATE_PIXEL_MAP_FROM_PARCEL = "createPixelMapFromParcel";
64 static const std::string MARSHALLING = "marshalling";
65 static const std::map<std::string, std::set<uint32_t>> ETS_API_ERROR_CODE = {
66     {CREATE_PIXEL_MAP_FROM_PARCEL, {62980096, 62980105, 62980115, 62980097,
67         62980177, 62980178, 62980179, 62980180, 62980246}},
68     {MARSHALLING, {62980115, 62980097, 62980096}}
69 };
70 static const std::string CLASS_NAME = "PixelMap";
71 static const std::int32_t NEW_INSTANCE_ARGC = 1;
72 thread_local napi_ref PixelMapNapi::sConstructor_ = nullptr;
73 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
74 NAPI_MessageSequence* napi_messageSequence = nullptr;
75 #endif
76 napi_ref PixelMapNapi::AntiAliasingLevel_ = nullptr;
77 napi_ref PixelMapNapi::HdrMetadataKey_ = nullptr;
78 napi_ref PixelMapNapi::HdrMetadataType_ = nullptr;
79 static std::mutex pixelMapCrossThreadMutex_;
80 struct PositionArea {
81     void* pixels;
82     size_t size;
83     uint32_t offset;
84     uint32_t stride;
85     Rect region;
86 };
87 
88 struct ImageEnum {
89     std::string name;
90     int32_t numVal;
91     std::string strVal;
92 };
93 
94 static std::vector<struct ImageEnum> AntiAliasingLevelMap = {
95     {"NONE", 0, ""},
96     {"LOW", 1, ""},
97     {"MEDIUM", 2, ""},
98     {"HIGH", 3, ""},
99 };
100 
101 static std::vector<struct ImageEnum> HdrMetadataKeyMap = {
102     {"HDR_METADATA_TYPE", 0, ""},
103     {"HDR_STATIC_METADATA", 1, ""},
104     {"HDR_DYNAMIC_METADATA", 2, ""},
105     {"HDR_GAINMAP_METADATA", 3, ""},
106 };
107 
108 static std::vector<struct ImageEnum> HdrMetadataTypeMap = {
109     {"NONE", 0, ""},
110     {"BASE", 1, ""},
111     {"GAINMAP", 2, ""},
112     {"ALTERNATE", 3, ""},
113 };
114 
115 struct PixelMapAsyncContext {
116     napi_env env;
117     napi_async_work work;
118     napi_deferred deferred;
119     napi_ref callbackRef;
120     napi_ref error = nullptr;
121     uint32_t status;
122     PixelMapNapi *nConstructor;
123     void* colorsBuffer;
124     size_t colorsBufferSize;
125     InitializationOptions opts;
126     PositionArea area;
127     std::shared_ptr<PixelMap> rPixelMap;
128     std::shared_ptr<PixelMap> alphaMap;
129     std::shared_ptr<PixelMap> wPixelMap;
130     double alpha = -1;
131     uint32_t resultUint32;
132     ImageInfo imageInfo;
133     double xArg = 0;
134     double yArg = 0;
135     bool xBarg = false;
136     bool yBarg = false;
137     std::shared_ptr<OHOS::ColorManager::ColorSpace> colorSpace;
138     std::string surfaceId;
139     PixelFormat destFormat = PixelFormat::UNKNOWN;
140     FormatType srcFormatType = FormatType::UNKNOWN;
141     FormatType dstFormatType = FormatType::UNKNOWN;
142     AntiAliasingOption antiAliasing;
143 };
144 using PixelMapAsyncContextPtr = std::unique_ptr<PixelMapAsyncContext>;
145 std::shared_ptr<PixelMap> srcPixelMap = nullptr;
146 
147 class AgainstTransferGC {
148 public:
149     std::shared_ptr<PixelMap> pixelMap = nullptr;
~AgainstTransferGC()150     ~AgainstTransferGC()
151     {
152         pixelMap = nullptr;
153     }
154 };
155 
ParsePixlForamt(int32_t val)156 static PixelFormat ParsePixlForamt(int32_t val)
157 {
158     if (val < static_cast<int32_t>(PixelFormat::EXTERNAL_MAX)) {
159         return PixelFormat(val);
160     }
161 
162     return PixelFormat::UNKNOWN;
163 }
164 
ParseAlphaType(int32_t val)165 static AlphaType ParseAlphaType(int32_t val)
166 {
167     if (val <= static_cast<int32_t>(AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL)) {
168         return AlphaType(val);
169     }
170 
171     return AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
172 }
173 
ParseScaleMode(int32_t val)174 static ScaleMode ParseScaleMode(int32_t val)
175 {
176     if (val <= static_cast<int32_t>(ScaleMode::CENTER_CROP)) {
177         return ScaleMode(val);
178     }
179 
180     return ScaleMode::FIT_TARGET_SIZE;
181 }
182 
ParseAntiAliasingOption(int32_t val)183 static AntiAliasingOption ParseAntiAliasingOption(int32_t val)
184 {
185     if (val <= static_cast<int32_t>(AntiAliasingOption::SPLINE)) {
186         return AntiAliasingOption(val);
187     }
188 
189     return AntiAliasingOption::NONE;
190 }
191 
parseSize(napi_env env,napi_value root,Size * size)192 static bool parseSize(napi_env env, napi_value root, Size* size)
193 {
194     if (size == nullptr) {
195         return false;
196     }
197 
198     if (!GET_INT32_BY_NAME(root, "height", size->height)) {
199         return false;
200     }
201 
202     if (!GET_INT32_BY_NAME(root, "width", size->width)) {
203         return false;
204     }
205 
206     return true;
207 }
208 
parseInitializationOptions(napi_env env,napi_value root,InitializationOptions * opts)209 static bool parseInitializationOptions(napi_env env, napi_value root, InitializationOptions* opts)
210 {
211     uint32_t tmpNumber = 0;
212     napi_value tmpValue = nullptr;
213 
214     if (opts == nullptr) {
215         return false;
216     }
217 
218     if (!GET_BOOL_BY_NAME(root, "editable", opts->editable)) {
219         opts->editable = true;
220     }
221 
222     if (!GET_UINT32_BY_NAME(root, "alphaType", tmpNumber)) {
223         IMAGE_LOGD("no alphaType in initialization options");
224     }
225     opts->alphaType = ParseAlphaType(tmpNumber);
226 
227     tmpNumber = 0;
228     if (!GET_UINT32_BY_NAME(root, "pixelFormat", tmpNumber)) {
229         IMAGE_LOGD("no pixelFormat in initialization options");
230     }
231     opts->pixelFormat = ParsePixlForamt(tmpNumber);
232 
233     tmpNumber = 0;
234     if (!GET_UINT32_BY_NAME(root, "srcPixelFormat", tmpNumber)) {
235         IMAGE_LOGD("no srcPixelFormat in initialization options");
236     }
237     opts->srcPixelFormat = ParsePixlForamt(tmpNumber);
238 
239     tmpNumber = 0;
240     if (!GET_UINT32_BY_NAME(root, "scaleMode", tmpNumber)) {
241         IMAGE_LOGD("no scaleMode in initialization options");
242     }
243     opts->scaleMode = ParseScaleMode(tmpNumber);
244 
245     if (!GET_NODE_BY_NAME(root, "size", tmpValue)) {
246         return false;
247     }
248 
249     if (!parseSize(env, tmpValue, &(opts->size))) {
250         return false;
251     }
252     return true;
253 }
254 
ParserImageType(napi_env env,napi_value argv)255 ImageType PixelMapNapi::ParserImageType(napi_env env, napi_value argv)
256 {
257     napi_value constructor = nullptr;
258     napi_value global = nullptr;
259     bool isInstance = false;
260     napi_status ret = napi_invalid_arg;
261 
262     napi_get_global(env, &global);
263 
264     ret = napi_get_named_property(env, global, "PixelMap", &constructor);
265     if (ret != napi_ok) {
266         IMAGE_LOGI("Get PixelMapNapi property failed!");
267     }
268 
269     ret = napi_instanceof(env, argv, constructor, &isInstance);
270     if (ret == napi_ok && isInstance) {
271         return ImageType::TYPE_PIXEL_MAP;
272     }
273 
274     IMAGE_LOGI("InValued type!");
275     return ImageType::TYPE_UNKNOWN;
276 }
277 
parseRegion(napi_env env,napi_value root,Rect * region)278 static bool parseRegion(napi_env env, napi_value root, Rect* region)
279 {
280     napi_value tmpValue = nullptr;
281 
282     if (region == nullptr) {
283         return false;
284     }
285 
286     if (!GET_INT32_BY_NAME(root, "x", region->left)) {
287         return false;
288     }
289 
290     if (!GET_INT32_BY_NAME(root, "y", region->top)) {
291         return false;
292     }
293 
294     if (!GET_NODE_BY_NAME(root, "size", tmpValue)) {
295         return false;
296     }
297 
298     if (!GET_INT32_BY_NAME(tmpValue, "height", region->height)) {
299         return false;
300     }
301 
302     if (!GET_INT32_BY_NAME(tmpValue, "width", region->width)) {
303         return false;
304     }
305 
306     return true;
307 }
308 
parsePositionArea(napi_env env,napi_value root,PositionArea * area)309 static bool parsePositionArea(napi_env env, napi_value root, PositionArea* area)
310 {
311     napi_value tmpValue = nullptr;
312 
313     if (area == nullptr) {
314         return false;
315     }
316 
317     if (!GET_BUFFER_BY_NAME(root, "pixels", area->pixels, area->size)) {
318         return false;
319     }
320 
321     if (!GET_UINT32_BY_NAME(root, "offset", area->offset)) {
322         return false;
323     }
324 
325     if (!GET_UINT32_BY_NAME(root, "stride", area->stride)) {
326         return false;
327     }
328 
329     if (!GET_NODE_BY_NAME(root, "region", tmpValue)) {
330         return false;
331     }
332 
333     if (!parseRegion(env, tmpValue, &(area->region))) {
334         return false;
335     }
336     return true;
337 }
338 
CreateEnumTypeObject(napi_env env,napi_valuetype type,napi_ref * ref,std::vector<struct ImageEnum> imageEnumMap)339 static napi_value CreateEnumTypeObject(napi_env env,
340     napi_valuetype type, napi_ref* ref, std::vector<struct ImageEnum> imageEnumMap)
341 {
342     napi_value result = nullptr;
343     napi_status status;
344     int32_t refCount = 1;
345     std::string propName;
346     status = napi_create_object(env, &result);
347     if (status == napi_ok) {
348         for (auto imgEnum : imageEnumMap) {
349             napi_value enumNapiValue = nullptr;
350             if (type == napi_string) {
351                 status = napi_create_string_utf8(env, imgEnum.strVal.c_str(),
352                     NAPI_AUTO_LENGTH, &enumNapiValue);
353             } else if (type == napi_number) {
354                 status = napi_create_int32(env, imgEnum.numVal, &enumNapiValue);
355             } else {
356                 IMAGE_LOGE("Unsupported type %{public}d!", type);
357             }
358             if (status == napi_ok && enumNapiValue != nullptr) {
359                 status = napi_set_named_property(env, result, imgEnum.name.c_str(), enumNapiValue);
360             }
361             if (status != napi_ok) {
362                 IMAGE_LOGE("Failed to add named prop!");
363                 break;
364             }
365         }
366 
367         if (status == napi_ok) {
368             status = napi_create_reference(env, result, refCount, ref);
369             if (status == napi_ok) {
370                 return result;
371             }
372         }
373     }
374     IMAGE_LOGE("CreateEnumTypeObject is Failed!");
375     napi_get_undefined(env, &result);
376     return result;
377 }
378 
CommonCallbackRoutine(napi_env env,PixelMapAsyncContext * & asyncContext,const napi_value & valueParam)379 static void CommonCallbackRoutine(napi_env env, PixelMapAsyncContext* &asyncContext, const napi_value &valueParam)
380 {
381     napi_value result[NUM_2] = {0};
382     napi_value retVal;
383     napi_value callback = nullptr;
384 
385     napi_get_undefined(env, &result[NUM_0]);
386     napi_get_undefined(env, &result[NUM_1]);
387 
388     napi_handle_scope scope = nullptr;
389     napi_open_handle_scope(env, &scope);
390     if (scope == nullptr) {
391         return;
392     }
393 
394     if (asyncContext == nullptr) {
395         napi_close_handle_scope(env, scope);
396         return;
397     }
398     if (asyncContext->status == SUCCESS) {
399         result[NUM_1] = valueParam;
400     } else if (asyncContext->error != nullptr) {
401         napi_get_reference_value(env, asyncContext->error, &result[NUM_0]);
402         napi_delete_reference(env, asyncContext->error);
403     } else {
404         napi_create_uint32(env, asyncContext->status, &result[NUM_0]);
405     }
406 
407     if (asyncContext->deferred) {
408         if (asyncContext->status == SUCCESS) {
409             napi_resolve_deferred(env, asyncContext->deferred, result[NUM_1]);
410         } else {
411             napi_reject_deferred(env, asyncContext->deferred, result[NUM_0]);
412         }
413     } else {
414         napi_get_reference_value(env, asyncContext->callbackRef, &callback);
415         napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
416         napi_delete_reference(env, asyncContext->callbackRef);
417     }
418 
419     napi_delete_async_work(env, asyncContext->work);
420     napi_close_handle_scope(env, scope);
421 
422     delete asyncContext;
423     asyncContext = nullptr;
424 }
425 
STATIC_COMPLETE_FUNC(EmptyResult)426 STATIC_COMPLETE_FUNC(EmptyResult)
427 {
428     napi_value result = nullptr;
429     napi_get_undefined(env, &result);
430 
431     auto context = static_cast<PixelMapAsyncContext*>(data);
432 
433     CommonCallbackRoutine(env, context, result);
434 }
435 
STATIC_COMPLETE_FUNC(GeneralError)436 STATIC_COMPLETE_FUNC(GeneralError)
437 {
438     if (data == nullptr) {
439         IMAGE_LOGE("GeneralErrorComplete invalid parameter: data is null");
440         return;
441     }
442 
443     napi_value result = nullptr;
444     napi_get_undefined(env, &result);
445     auto context = static_cast<PixelMapAsyncContext*>(data);
446     context->status = ERR_RESOURCE_UNAVAILABLE;
447     CommonCallbackRoutine(env, context, result);
448 }
449 
PixelMapNapi()450 PixelMapNapi::PixelMapNapi():env_(nullptr)
451 {
452     static std::atomic<uint32_t> currentId = 0;
453     uniqueId_ = currentId.fetch_add(1, std::memory_order_relaxed);
454 }
455 
~PixelMapNapi()456 PixelMapNapi::~PixelMapNapi()
457 {
458     release();
459 }
460 
DoInitAfter(napi_env env,napi_value exports,napi_value constructor,size_t property_count,const napi_property_descriptor * properties)461 static napi_value DoInitAfter(napi_env env,
462                               napi_value exports,
463                               napi_value constructor,
464                               size_t property_count,
465                               const napi_property_descriptor* properties)
466 {
467     napi_value global = nullptr;
468     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
469         napi_get_global(env, &global)),
470         nullptr, IMAGE_LOGE("Init:get global fail")
471     );
472 
473     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
474         napi_set_named_property(env, global, CLASS_NAME.c_str(), constructor)),
475         nullptr, IMAGE_LOGE("Init:set global named property fail")
476     );
477 
478     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
479         napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor)),
480         nullptr, IMAGE_LOGE("set named property fail")
481     );
482 
483     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
484         napi_define_properties(env, exports, property_count, properties)),
485         nullptr, IMAGE_LOGE("define properties fail")
486     );
487     return exports;
488 }
489 
RegisterNapi()490 std::vector<napi_property_descriptor> PixelMapNapi::RegisterNapi()
491 {
492     std::vector<napi_property_descriptor> props = {
493         DECLARE_NAPI_FUNCTION("readPixelsToBuffer", ReadPixelsToBuffer),
494         DECLARE_NAPI_FUNCTION("readPixelsToBufferSync", ReadPixelsToBufferSync),
495         DECLARE_NAPI_FUNCTION("readPixels", ReadPixels),
496         DECLARE_NAPI_FUNCTION("readPixelsSync", ReadPixelsSync),
497         DECLARE_NAPI_FUNCTION("writePixels", WritePixels),
498         DECLARE_NAPI_FUNCTION("writePixelsSync", WritePixelsSync),
499         DECLARE_NAPI_FUNCTION("writeBufferToPixels", WriteBufferToPixels),
500         DECLARE_NAPI_FUNCTION("writeBufferToPixelsSync", WriteBufferToPixelsSync),
501         DECLARE_NAPI_FUNCTION("getImageInfo", GetImageInfo),
502         DECLARE_NAPI_FUNCTION("getImageInfoSync", GetImageInfoSync),
503         DECLARE_NAPI_FUNCTION("getBytesNumberPerRow", GetBytesNumberPerRow),
504         DECLARE_NAPI_FUNCTION("getPixelBytesNumber", GetPixelBytesNumber),
505         DECLARE_NAPI_FUNCTION("isSupportAlpha", IsSupportAlpha),
506         DECLARE_NAPI_FUNCTION("setAlphaAble", SetAlphaAble),
507         DECLARE_NAPI_FUNCTION("createAlphaPixelmap", CreateAlphaPixelmap),
508         DECLARE_NAPI_FUNCTION("createAlphaPixelmapSync", CreateAlphaPixelmapSync),
509         DECLARE_NAPI_FUNCTION("getDensity", GetDensity),
510         DECLARE_NAPI_FUNCTION("setDensity", SetDensity),
511         DECLARE_NAPI_FUNCTION("opacity", SetAlpha),
512         DECLARE_NAPI_FUNCTION("opacitySync", SetAlphaSync),
513         DECLARE_NAPI_FUNCTION("release", Release),
514         DECLARE_NAPI_FUNCTION("scale", Scale),
515         DECLARE_NAPI_FUNCTION("scaleSync", ScaleSync),
516         DECLARE_NAPI_FUNCTION("translate", Translate),
517         DECLARE_NAPI_FUNCTION("translateSync", TranslateSync),
518         DECLARE_NAPI_FUNCTION("rotate", Rotate),
519         DECLARE_NAPI_FUNCTION("rotateSync", RotateSync),
520         DECLARE_NAPI_FUNCTION("flip", Flip),
521         DECLARE_NAPI_FUNCTION("flipSync", FlipSync),
522         DECLARE_NAPI_FUNCTION("crop", Crop),
523         DECLARE_NAPI_FUNCTION("cropSync", CropSync),
524         DECLARE_NAPI_FUNCTION("getColorSpace", GetColorSpace),
525         DECLARE_NAPI_FUNCTION("setColorSpace", SetColorSpace),
526         DECLARE_NAPI_FUNCTION("applyColorSpace", ApplyColorSpace),
527         DECLARE_NAPI_FUNCTION("marshalling", Marshalling),
528         DECLARE_NAPI_FUNCTION("unmarshalling", Unmarshalling),
529         DECLARE_NAPI_GETTER("isEditable", GetIsEditable),
530         DECLARE_NAPI_GETTER("isStrideAlignment", GetIsStrideAlignment),
531         DECLARE_NAPI_FUNCTION("toSdr", ToSdr),
532         DECLARE_NAPI_FUNCTION("convertPixelFormat", ConvertPixelMapFormat),
533         DECLARE_NAPI_FUNCTION("setTransferDetached", SetTransferDetached),
534         DECLARE_NAPI_FUNCTION("getMetadata", GetMetadata),
535         DECLARE_NAPI_FUNCTION("setMetadata", SetMetadata),
536         DECLARE_NAPI_FUNCTION("setMetadataSync", SetMetadataSync),
537         DECLARE_NAPI_FUNCTION("setMemoryNameSync", SetMemoryNameSync),
538     };
539     return props;
540 }
541 
Init(napi_env env,napi_value exports)542 napi_value PixelMapNapi::Init(napi_env env, napi_value exports)
543 {
544     std::vector<napi_property_descriptor> props = PixelMapNapi::RegisterNapi();
545     napi_property_descriptor static_prop[] = {
546         DECLARE_NAPI_STATIC_FUNCTION("createPixelMap", CreatePixelMap),
547         DECLARE_NAPI_STATIC_FUNCTION("createPremultipliedPixelMap", CreatePremultipliedPixelMap),
548         DECLARE_NAPI_STATIC_FUNCTION("createUnpremultipliedPixelMap", CreateUnpremultipliedPixelMap),
549         DECLARE_NAPI_STATIC_FUNCTION("createPixelMapSync", CreatePixelMapSync),
550         DECLARE_NAPI_STATIC_FUNCTION("unmarshalling", Unmarshalling),
551         DECLARE_NAPI_STATIC_FUNCTION(CREATE_PIXEL_MAP_FROM_PARCEL.c_str(), CreatePixelMapFromParcel),
552 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
553         DECLARE_NAPI_STATIC_FUNCTION("createPixelMapFromSurface", CreatePixelMapFromSurface),
554         DECLARE_NAPI_STATIC_FUNCTION("createPixelMapFromSurfaceSync", CreatePixelMapFromSurfaceSync),
555         DECLARE_NAPI_STATIC_FUNCTION("convertPixelFormat", ConvertPixelMapFormat),
556 #endif
557         DECLARE_NAPI_PROPERTY("AntiAliasingLevel",
558             CreateEnumTypeObject(env, napi_number, &AntiAliasingLevel_, AntiAliasingLevelMap)),
559         DECLARE_NAPI_PROPERTY("HdrMetadataKey",
560             CreateEnumTypeObject(env, napi_number, &HdrMetadataKey_, HdrMetadataKeyMap)),
561         DECLARE_NAPI_PROPERTY("HdrMetadataType",
562             CreateEnumTypeObject(env, napi_number, &HdrMetadataType_, HdrMetadataTypeMap)),
563     };
564 
565     napi_value constructor = nullptr;
566 
567     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
568         napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
569                           Constructor, nullptr, props.size(),
570                           props.data(), &constructor)),
571         nullptr, IMAGE_LOGE("define class fail")
572     );
573 
574     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
575         napi_create_reference(env, constructor, 1, &sConstructor_)),
576         nullptr, IMAGE_LOGE("create reference fail")
577     );
578 
579     auto result = DoInitAfter(env, exports, constructor,
580         IMG_ARRAY_SIZE(static_prop), static_prop);
581 
582     IMAGE_LOGD("Init success");
583     return result;
584 }
585 
GetPixelMap(napi_env env,napi_value pixelmap)586 std::shared_ptr<PixelMap> PixelMapNapi::GetPixelMap(napi_env env, napi_value pixelmap)
587 {
588     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
589 
590     napi_status status = napi_unwrap(env, pixelmap, reinterpret_cast<void**>(&pixelMapNapi));
591     if (!IMG_IS_OK(status)) {
592         IMAGE_LOGE("GetPixelMap napi unwrap failed");
593         return nullptr;
594     }
595 
596     if (pixelMapNapi == nullptr) {
597         IMAGE_LOGE("GetPixelMap pixmapNapi is nullptr");
598         return nullptr;
599     }
600 
601     auto pixelmapNapiPtr = pixelMapNapi.release();
602     if (pixelmapNapiPtr == nullptr) {
603         IMAGE_LOGE("GetPixelMap pixelmapNapi is nullptr");
604         return nullptr;
605     }
606     return pixelmapNapiPtr->nativePixelMap_;
607 }
608 
GetPixelMaps(napi_env env,napi_value pixelmaps)609 std::shared_ptr<std::vector<std::shared_ptr<PixelMap>>> PixelMapNapi::GetPixelMaps(napi_env env, napi_value pixelmaps)
610 {
611     auto PixelMaps = std::make_shared<std::vector<std::shared_ptr<PixelMap>>>();
612     uint32_t length = 0;
613     auto status = napi_get_array_length(env, pixelmaps, &length);
614     if (!IMG_IS_OK(status)) {
615         IMAGE_LOGE("GetPixelMaps napi get array length failed");
616         return nullptr;
617     }
618     for (uint32_t i = 0; i < length; ++i) {
619         napi_value element;
620         status = napi_get_element(env, pixelmaps, i, &element);
621         if (!IMG_IS_OK(status)) {
622             IMAGE_LOGE("GetPixelMaps napi get element failed");
623             return nullptr;
624         }
625         std::shared_ptr<PixelMap> pixelMap;
626         pixelMap = GetPixelMap(env, element);
627         PixelMaps->push_back(pixelMap);
628     }
629     return PixelMaps;
630 }
631 
GetPixelMap()632 std::shared_ptr<PixelMap>* PixelMapNapi::GetPixelMap()
633 {
634     return &nativePixelMap_;
635 }
636 
IsLockPixelMap()637 bool PixelMapNapi::IsLockPixelMap()
638 {
639     return (lockCount > 0);
640 }
641 
LockPixelMap()642 bool PixelMapNapi::LockPixelMap()
643 {
644     lockCount++;
645     return true;
646 }
647 
UnlockPixelMap()648 void PixelMapNapi::UnlockPixelMap()
649 {
650     if (lockCount > 0) {
651         lockCount--;
652     }
653 }
654 
OHOS_MEDIA_GetPixelMap(napi_env env,napi_value value)655 extern "C" __attribute__((visibility("default"))) void* OHOS_MEDIA_GetPixelMap(napi_env env, napi_value value)
656 {
657     PixelMapNapi *pixmapNapi = nullptr;
658     napi_unwrap(env, value, reinterpret_cast<void**>(&pixmapNapi));
659     if (pixmapNapi == nullptr) {
660         IMAGE_LOGE("pixmapNapi unwrapped is nullptr");
661         return nullptr;
662     }
663     return reinterpret_cast<void*>(pixmapNapi->GetPixelMap());
664 }
665 
OHOS_MEDIA_GetImageInfo(napi_env env,napi_value value,OhosPixelMapInfo * info)666 extern "C" __attribute__((visibility("default"))) int32_t OHOS_MEDIA_GetImageInfo(napi_env env, napi_value value,
667     OhosPixelMapInfo *info)
668 {
669     IMAGE_LOGD("GetImageInfo IN");
670 
671     if (info == nullptr) {
672         IMAGE_LOGE("info is nullptr");
673         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
674     }
675 
676     PixelMapNapi *pixmapNapi = nullptr;
677     napi_unwrap(env, value, reinterpret_cast<void**>(&pixmapNapi));
678     if (pixmapNapi == nullptr) {
679         IMAGE_LOGE("pixmapNapi unwrapped is nullptr");
680         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
681     }
682 
683     std::shared_ptr<PixelMap> pixelMap = pixmapNapi->GetPixelNapiInner();
684     if ((pixelMap == nullptr)) {
685         IMAGE_LOGE("pixelMap is nullptr");
686         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
687     }
688 
689     ImageInfo imageInfo;
690     pixelMap->GetImageInfo(imageInfo);
691     info->width = imageInfo.size.width;
692     info->height = imageInfo.size.height;
693     info->rowSize = pixelMap->GetRowStride();
694     info->pixelFormat = static_cast<int32_t>(imageInfo.pixelFormat);
695 
696     IMAGE_LOGD("GetImageInfo, w=%{public}u, h=%{public}u, r=%{public}u, f=%{public}d",
697         info->width, info->height, info->rowSize, info->pixelFormat);
698 
699     return OHOS_IMAGE_RESULT_SUCCESS;
700 }
701 
OHOS_MEDIA_AccessPixels(napi_env env,napi_value value,uint8_t ** addrPtr)702 extern "C" __attribute__((visibility("default"))) int32_t OHOS_MEDIA_AccessPixels(napi_env env, napi_value value,
703     uint8_t** addrPtr)
704 {
705     IMAGE_LOGD("AccessPixels IN");
706 
707     PixelMapNapi *pixmapNapi = nullptr;
708     napi_unwrap(env, value, reinterpret_cast<void**>(&pixmapNapi));
709     if (pixmapNapi == nullptr) {
710         IMAGE_LOGE("pixmapNapi unwrapped is nullptr");
711         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
712     }
713 
714     std::shared_ptr<PixelMap> pixelMap = pixmapNapi->GetPixelNapiInner();
715     if (pixelMap == nullptr) {
716         IMAGE_LOGE("pixelMap is nullptr");
717         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
718     }
719 
720     const uint8_t *constPixels = pixelMap->GetPixels();
721     if (constPixels == nullptr) {
722         IMAGE_LOGE("const pixels is nullptr");
723         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
724     }
725 
726     uint8_t *pixels = const_cast<uint8_t*>(constPixels);
727     if (pixels == nullptr) {
728         IMAGE_LOGE("pixels is nullptr");
729         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
730     }
731 
732     pixmapNapi->LockPixelMap();
733 
734     if (addrPtr != nullptr) {
735         *addrPtr = pixels;
736     }
737 
738     IMAGE_LOGD("AccessPixels OUT");
739     return OHOS_IMAGE_RESULT_SUCCESS;
740 }
741 
OHOS_MEDIA_UnAccessPixels(napi_env env,napi_value value)742 extern "C" __attribute__((visibility("default"))) int32_t OHOS_MEDIA_UnAccessPixels(napi_env env, napi_value value)
743 {
744     IMAGE_LOGD("UnAccessPixels IN");
745 
746     PixelMapNapi *pixmapNapi = nullptr;
747     napi_unwrap(env, value, reinterpret_cast<void**>(&pixmapNapi));
748     if (pixmapNapi == nullptr) {
749         IMAGE_LOGE("pixmapNapi unwrapped is nullptr");
750         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
751     }
752 
753     pixmapNapi->UnlockPixelMap();
754 
755     return OHOS_IMAGE_RESULT_SUCCESS;
756 }
757 
DetachPixelMapFunc(napi_env env,void * value,void *)758 void *DetachPixelMapFunc(napi_env env, void *value, void *)
759 {
760     IMAGE_LOGD("DetachPixelMapFunc in");
761     if (value == nullptr) {
762         IMAGE_LOGE("DetachPixelMapFunc value is nullptr");
763         return value;
764     }
765     auto pixelNapi = reinterpret_cast<PixelMapNapi*>(value);
766     pixelNapi->setPixelNapiEditable(false);
767     AgainstTransferGC *data = new AgainstTransferGC();
768     data->pixelMap = pixelNapi->GetPixelNapiInner();
769     if (pixelNapi->GetTransferDetach()) {
770         pixelNapi->ReleasePixelNapiInner();
771     }
772     return reinterpret_cast<void*>(data);
773 }
774 
NewPixelNapiInstance(napi_env & env,napi_value & constructor,std::shared_ptr<PixelMap> & pixelMap,napi_value & result)775 static napi_status NewPixelNapiInstance(napi_env &env, napi_value &constructor,
776     std::shared_ptr<PixelMap> &pixelMap, napi_value &result)
777 {
778     napi_status status;
779     if (pixelMap == nullptr) {
780         status = napi_invalid_arg;
781         IMAGE_LOGE("NewPixelNapiInstance pixelMap is nullptr");
782         return status;
783     }
784     size_t argc = NEW_INSTANCE_ARGC;
785     napi_value argv[NEW_INSTANCE_ARGC] = { 0 };
786     napi_create_int32(env, pixelMap->GetUniqueId(), &argv[0]);
787     PixelMapContainer::GetInstance().Insert(pixelMap->GetUniqueId(), pixelMap);
788     status = napi_new_instance(env, constructor, argc, argv, &result);
789     return status;
790 }
791 
AttachPixelMapFunc(napi_env env,void * value,void *)792 napi_value AttachPixelMapFunc(napi_env env, void *value, void *)
793 {
794     if (value == nullptr) {
795         IMAGE_LOGE("attach value is nullptr");
796         return nullptr;
797     }
798     std::lock_guard<std::mutex> lock(pixelMapCrossThreadMutex_);
799 
800     napi_value result = nullptr;
801     if (value == nullptr) {
802         IMAGE_LOGE("attach value lock losed");
803         napi_get_undefined(env, &result);
804         return result;
805     }
806     AgainstTransferGC *data = reinterpret_cast<AgainstTransferGC*>(value);
807     std::shared_ptr<PixelMap> attachPixelMap = std::move(data->pixelMap);
808     delete data;
809     if (attachPixelMap == nullptr) {
810         IMAGE_LOGE("AttachPixelMapFunc attachPixelMap is nullptr");
811         napi_get_undefined(env, &result);
812         return result;
813     }
814     napi_value constructor = nullptr;
815     napi_status status;
816 
817     if (PixelMapNapi::GetConstructor() == nullptr) {
818         IMAGE_LOGI("PixelMapNapi::GetConstructor() is nullptr");
819         napi_value exports = nullptr;
820         napi_create_object(env, &exports);
821         PixelMapNapi::Init(env, exports);
822     }
823     napi_value globalValue;
824     napi_get_global(env, &globalValue);
825     status = napi_get_named_property(env, globalValue, CLASS_NAME.c_str(), &constructor);
826     if (!IMG_IS_OK(status)) {
827         IMAGE_LOGI("napi_get_named_property failed requireNapi in");
828         napi_value func;
829         napi_get_named_property(env, globalValue, "requireNapi", &func);
830 
831         napi_value imageInfo;
832         napi_create_string_utf8(env, "multimedia.image", NAPI_AUTO_LENGTH, &imageInfo);
833         napi_value funcArgv[1] = { imageInfo };
834         napi_value returnValue;
835         napi_call_function(env, globalValue, func, 1, funcArgv, &returnValue);
836         status = napi_get_named_property(env, globalValue, CLASS_NAME.c_str(), &constructor);
837         IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("napi_get_named_property error"));
838     }
839 
840     status = NewPixelNapiInstance(env, constructor, attachPixelMap, result);
841     if (!IMG_IS_OK(status)) {
842         IMAGE_LOGE("AttachPixelMapFunc napi_get_referencce_value failed");
843     }
844     return result;
845 }
846 
Constructor(napi_env env,napi_callback_info info)847 napi_value PixelMapNapi::Constructor(napi_env env, napi_callback_info info)
848 {
849     napi_value undefineVar = nullptr;
850     napi_get_undefined(env, &undefineVar);
851 
852     napi_status status;
853     napi_value thisVar = nullptr;
854     napi_get_undefined(env, &thisVar);
855     size_t argc = NEW_INSTANCE_ARGC;
856     napi_value argv[NEW_INSTANCE_ARGC] = { 0 };
857     IMAGE_LOGD("Constructor IN");
858     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
859     IMG_NAPI_CHECK_RET(IMG_IS_READY(status, thisVar), undefineVar);
860     uint32_t pixelMapId = 0;
861     napi_get_value_uint32(env, argv[0], &pixelMapId);
862     std::unique_ptr<PixelMapNapi> pPixelMapNapi = std::make_unique<PixelMapNapi>();
863 
864     IMG_NAPI_CHECK_RET(IMG_NOT_NULL(pPixelMapNapi), undefineVar);
865 
866     pPixelMapNapi->env_ = env;
867     if (PixelMapContainer::GetInstance().Find(pixelMapId)) {
868         pPixelMapNapi->nativePixelMap_ = PixelMapContainer::GetInstance()[pixelMapId];
869         IMAGE_LOGD("Constructor in napi_id:%{public}d, id:%{public}d",
870             pPixelMapNapi->GetUniqueId(), pPixelMapNapi->nativePixelMap_->GetUniqueId());
871     } else {
872         IMAGE_LOGE("Constructor nativePixelMap is nullptr");
873     }
874 
875     napi_coerce_to_native_binding_object(
876         env, thisVar, DetachPixelMapFunc, AttachPixelMapFunc, pPixelMapNapi.get(), nullptr);
877 
878     status = napi_wrap_with_size(env, thisVar, reinterpret_cast<void*>(pPixelMapNapi.get()), PixelMapNapi::Destructor,
879         nullptr, nullptr, static_cast<size_t>(pPixelMapNapi->nativePixelMap_->GetByteCount()));
880     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), undefineVar, IMAGE_LOGE("Failure wrapping js to native napi"));
881 
882     pPixelMapNapi.release();
883     PixelMapContainer::GetInstance().Erase(pixelMapId);
884     return thisVar;
885 }
886 
Destructor(napi_env env,void * nativeObject,void * finalize)887 void PixelMapNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
888 {
889     if (nativeObject != nullptr) {
890         std::lock_guard<std::mutex> lock(pixelMapCrossThreadMutex_);
891         IMAGE_LOGD("Destructor pixelmapNapi");
892         delete reinterpret_cast<PixelMapNapi*>(nativeObject);
893         nativeObject = nullptr;
894     }
895 }
896 
BuildContextError(napi_env env,napi_ref & error,const std::string errMsg,const int32_t errCode)897 static void BuildContextError(napi_env env, napi_ref &error, const std::string errMsg, const int32_t errCode)
898 {
899     IMAGE_LOGE("%{public}s", errMsg.c_str());
900     napi_value tmpError;
901     ImageNapiUtils::CreateErrorObj(env, tmpError, errCode, errMsg);
902     napi_create_reference(env, tmpError, NUM_1, &(error));
903 }
904 
STATIC_EXEC_FUNC(CreatePixelMap)905 STATIC_EXEC_FUNC(CreatePixelMap)
906 {
907     if (data == nullptr) {
908         IMAGE_LOGE("CreatePixelMapExec invalid parameter: data is null");
909         return;
910     }
911 
912     auto context = static_cast<PixelMapAsyncContext*>(data);
913     auto colors = static_cast<uint32_t*>(context->colorsBuffer);
914     if (colors == nullptr) {
915         if (context->opts.pixelFormat == PixelFormat::RGBA_1010102 ||
916             context->opts.pixelFormat == PixelFormat::YCBCR_P010 ||
917             context->opts.pixelFormat == PixelFormat::YCRCB_P010) {
918             context->opts.useDMA = true;
919         }
920         auto pixelmap = PixelMap::Create(context->opts);
921         context->rPixelMap = std::move(pixelmap);
922     } else {
923         if (context->opts.pixelFormat == PixelFormat::RGBA_1010102 ||
924             context->opts.pixelFormat == PixelFormat::YCBCR_P010 ||
925             context->opts.pixelFormat == PixelFormat::YCRCB_P010) {
926             context->rPixelMap = nullptr;
927         } else {
928             auto pixelmap = PixelMap::Create(colors, context->colorsBufferSize, context->opts);
929             context->rPixelMap = std::move(pixelmap);
930         }
931     }
932     if (IMG_NOT_NULL(context->rPixelMap)) {
933         context->status = SUCCESS;
934     } else {
935         context->status = ERROR;
936     }
937 }
938 
CreatePixelMapComplete(napi_env env,napi_status status,void * data)939 void PixelMapNapi::CreatePixelMapComplete(napi_env env, napi_status status, void *data)
940 {
941     if (data == nullptr) {
942         IMAGE_LOGE("CreatePixelMapComplete invalid parameter: data is null");
943         return;
944     }
945 
946     napi_value constructor = nullptr;
947     napi_value result = nullptr;
948 
949     IMAGE_LOGD("CreatePixelMapComplete IN");
950     auto context = static_cast<PixelMapAsyncContext*>(data);
951 
952     status = napi_get_reference_value(env, sConstructor_, &constructor);
953 
954     if (IMG_IS_OK(status)) {
955         status = NewPixelNapiInstance(env, constructor, context->rPixelMap, result);
956     }
957 
958     if (!IMG_IS_OK(status)) {
959         context->status = ERROR;
960         IMAGE_LOGE("New instance could not be obtained");
961         napi_get_undefined(env, &result);
962     }
963 
964     CommonCallbackRoutine(env, context, result);
965 }
966 
STATIC_EXEC_FUNC(CreatePremultipliedPixelMap)967 STATIC_EXEC_FUNC(CreatePremultipliedPixelMap)
968 {
969     if (data == nullptr) {
970         IMAGE_LOGE("CreatePremultipliedPixelMapExec invalid parameter: data is null");
971         return;
972     }
973 
974     auto context = static_cast<PixelMapAsyncContext*>(data);
975     if (IMG_NOT_NULL(context->rPixelMap) && IMG_NOT_NULL(context->wPixelMap)) {
976         bool isPremul = true;
977         if (context->wPixelMap->IsEditable()) {
978             context->status = context->rPixelMap->ConvertAlphaFormat(*context->wPixelMap.get(), isPremul);
979         } else {
980             context->status = ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
981         }
982     } else {
983         context->status = ERR_IMAGE_READ_PIXELMAP_FAILED;
984     }
985 }
986 
STATIC_EXEC_FUNC(CreateUnpremultipliedPixelMap)987 STATIC_EXEC_FUNC(CreateUnpremultipliedPixelMap)
988 {
989     if (data == nullptr) {
990         IMAGE_LOGE("CreateUnpremultipliedPixelMapExec invalid parameter: data is null");
991         return;
992     }
993 
994     auto context = static_cast<PixelMapAsyncContext*>(data);
995     if (IMG_NOT_NULL(context->rPixelMap) && IMG_NOT_NULL(context->wPixelMap)) {
996         bool isPremul = false;
997         if (context->wPixelMap->IsEditable()) {
998             context->status = context->rPixelMap->ConvertAlphaFormat(*context->wPixelMap.get(), isPremul);
999         } else {
1000             context->status = ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY;
1001         }
1002     } else {
1003         context->status = ERR_IMAGE_READ_PIXELMAP_FAILED;
1004     }
1005 }
1006 
CreatePremultipliedPixelMap(napi_env env,napi_callback_info info)1007 napi_value PixelMapNapi::CreatePremultipliedPixelMap(napi_env env, napi_callback_info info)
1008 {
1009     napi_value result = nullptr;
1010     napi_get_undefined(env, &result);
1011     int32_t refCount = 1;
1012     napi_status status;
1013     napi_value thisVar = nullptr;
1014     napi_value argValue[NUM_3] = {0};
1015     size_t argCount = NUM_3;
1016     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1017 
1018     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1019     IMG_NAPI_CHECK_RET_D(argCount >= NUM_2,
1020         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1021         "Invalid args count"),
1022         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
1023     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1024 
1025     if (ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP &&
1026         ParserImageType(env, argValue[NUM_1]) == ImageType::TYPE_PIXEL_MAP) {
1027         asyncContext->rPixelMap = GetPixelMap(env, argValue[NUM_0]);
1028         asyncContext->wPixelMap = GetPixelMap(env, argValue[NUM_1]);
1029         if (asyncContext->rPixelMap == nullptr || asyncContext->wPixelMap == nullptr) {
1030             BuildContextError(env, asyncContext->error, "input image type mismatch", ERR_IMAGE_GET_DATA_ABNORMAL);
1031         }
1032     } else {
1033         BuildContextError(env, asyncContext->error, "input image type mismatch",
1034             ERR_IMAGE_GET_DATA_ABNORMAL);
1035     }
1036 
1037     IMG_NAPI_CHECK_RET_D(asyncContext->error == nullptr, nullptr, IMAGE_LOGE("input image type mismatch"));
1038     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1039         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1040     }
1041     if (asyncContext->callbackRef == nullptr) {
1042         napi_create_promise(env, &(asyncContext->deferred), &result);
1043     }
1044 
1045     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->error == nullptr,
1046         BuildContextError(env, asyncContext->error, "CreatePremultipliedPixelMapError", ERR_IMAGE_GET_DATA_ABNORMAL),
1047         IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePremultipliedPixelMapGeneralError",
1048         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1049         result);
1050 
1051     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePremultipliedPixelMap",
1052         CreatePremultipliedPixelMapExec, EmptyResultComplete, asyncContext, asyncContext->work);
1053 
1054     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1055         nullptr, IMAGE_LOGE("fail to create async work"));
1056     return result;
1057 }
1058 
CreateUnpremultipliedPixelMap(napi_env env,napi_callback_info info)1059 napi_value PixelMapNapi::CreateUnpremultipliedPixelMap(napi_env env, napi_callback_info info)
1060 {
1061     napi_value result = nullptr;
1062     napi_get_undefined(env, &result);
1063     int32_t refCount = 1;
1064     napi_status status;
1065     napi_value thisVar = nullptr;
1066     napi_value argValue[NUM_3] = {0};
1067     size_t argCount = NUM_3;
1068     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1069 
1070     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1071     IMG_NAPI_CHECK_RET_D(argCount >= NUM_2,
1072         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1073         "Invalid args count"),
1074         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
1075     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1076 
1077     if (ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP &&
1078         ParserImageType(env, argValue[NUM_1]) == ImageType::TYPE_PIXEL_MAP) {
1079         asyncContext->rPixelMap = GetPixelMap(env, argValue[NUM_0]);
1080         asyncContext->wPixelMap = GetPixelMap(env, argValue[NUM_1]);
1081         if (asyncContext->rPixelMap == nullptr || asyncContext->wPixelMap == nullptr) {
1082             BuildContextError(env, asyncContext->error, "input image type mismatch", ERR_IMAGE_GET_DATA_ABNORMAL);
1083         }
1084     } else {
1085         BuildContextError(env, asyncContext->error, "input image type mismatch",
1086             ERR_IMAGE_GET_DATA_ABNORMAL);
1087     }
1088 
1089     IMG_NAPI_CHECK_RET_D(asyncContext->error == nullptr, nullptr, IMAGE_LOGE("input image type mismatch"));
1090     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1091         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1092     }
1093     if (asyncContext->callbackRef == nullptr) {
1094         napi_create_promise(env, &(asyncContext->deferred), &result);
1095     }
1096 
1097     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->error == nullptr,
1098         BuildContextError(env, asyncContext->error, "CreateUnpremultipliedPixelMapError", ERR_IMAGE_GET_DATA_ABNORMAL),
1099         IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateUnpremultipliedPixelMapGeneralError",
1100         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1101         result);
1102 
1103     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateUnpremultipliedPixelMap",
1104         CreateUnpremultipliedPixelMapExec, EmptyResultComplete, asyncContext, asyncContext->work);
1105 
1106     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1107         nullptr, IMAGE_LOGE("fail to create async work"));
1108     return result;
1109 }
1110 
CreatePixelMap(napi_env env,napi_callback_info info)1111 napi_value PixelMapNapi::CreatePixelMap(napi_env env, napi_callback_info info)
1112 {
1113     if (PixelMapNapi::GetConstructor() == nullptr) {
1114         napi_value exports = nullptr;
1115         napi_create_object(env, &exports);
1116         PixelMapNapi::Init(env, exports);
1117     }
1118 
1119     napi_value result = nullptr;
1120     napi_get_undefined(env, &result);
1121 
1122     int32_t refCount = 1;
1123 
1124     napi_status status;
1125     napi_value thisVar = nullptr;
1126     napi_value argValue[NUM_4] = {0};
1127     size_t argCount = NUM_4;
1128     IMAGE_LOGD("CreatePixelMap IN");
1129 
1130     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1131 
1132     // we are static method!
1133     // thisVar is nullptr here
1134     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1135     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1136 
1137     status = napi_get_arraybuffer_info(env, argValue[NUM_0], &(asyncContext->colorsBuffer),
1138         &(asyncContext->colorsBufferSize));
1139 
1140     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("colors mismatch"));
1141 
1142     IMG_NAPI_CHECK_RET_D(parseInitializationOptions(env, argValue[1], &(asyncContext->opts)),
1143         nullptr, IMAGE_LOGE("InitializationOptions mismatch"));
1144 
1145     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1146         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1147     }
1148 
1149     if (asyncContext->callbackRef == nullptr) {
1150         napi_create_promise(env, &(asyncContext->deferred), &result);
1151     } else {
1152         napi_get_undefined(env, &result);
1153     }
1154 
1155     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePixelMap",
1156         CreatePixelMapExec, CreatePixelMapComplete, asyncContext, asyncContext->work);
1157 
1158     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1159         nullptr, IMAGE_LOGE("fail to create async work"));
1160     return result;
1161 }
1162 
CreatePixelMapSync(napi_env env,napi_callback_info info)1163 napi_value PixelMapNapi::CreatePixelMapSync(napi_env env, napi_callback_info info)
1164 {
1165     if (PixelMapNapi::GetConstructor() == nullptr) {
1166         napi_value exports = nullptr;
1167         napi_create_object(env, &exports);
1168         PixelMapNapi::Init(env, exports);
1169     }
1170 
1171     napi_value result = nullptr;
1172     napi_get_undefined(env, &result);
1173     napi_value constructor = nullptr;
1174     napi_status status;
1175     napi_value thisVar = nullptr;
1176     napi_value argValue[NUM_2] = {0};
1177     size_t argCount = NUM_2;
1178     IMAGE_LOGD("CreatePixelMap IN");
1179 
1180     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1181 
1182     // we are static method!
1183     // thisVar is nullptr here
1184     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1185 
1186     IMG_NAPI_CHECK_RET_D(argCount == NUM_2 || argCount == NUM_1,
1187         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1188         "Invalid args count"),
1189         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
1190     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1191 
1192     if (argCount == NUM_2) {
1193         status = napi_get_arraybuffer_info(env, argValue[NUM_0], &(asyncContext->colorsBuffer),
1194         &(asyncContext->colorsBufferSize));
1195         IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("colors mismatch"));
1196         IMG_NAPI_CHECK_RET_D(parseInitializationOptions(env, argValue[1], &(asyncContext->opts)),
1197             nullptr, IMAGE_LOGE("InitializationOptions mismatch"));
1198     } else if (argCount == NUM_1) {
1199         IMG_NAPI_CHECK_RET_D(parseInitializationOptions(env, argValue[NUM_0], &(asyncContext->opts)),
1200             nullptr, IMAGE_LOGE("InitializationOptions mismatch"));
1201     }
1202     CreatePixelMapExec(env, static_cast<void*>((asyncContext).get()));
1203     status = napi_get_reference_value(env, sConstructor_, &constructor);
1204     if (IMG_IS_OK(status)) {
1205             status = NewPixelNapiInstance(env, constructor, asyncContext->rPixelMap, result);
1206     }
1207     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to create pixel map sync"));
1208     return result;
1209 }
1210 
1211 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
STATIC_EXEC_FUNC(CreatePixelMapFromSurface)1212 STATIC_EXEC_FUNC(CreatePixelMapFromSurface)
1213 {
1214     if (data == nullptr) {
1215         IMAGE_LOGE("CreatePixelMapFromSurfaceExec invalid parameter: data is null");
1216         return;
1217     }
1218 
1219     auto context = static_cast<PixelMapAsyncContext*>(data);
1220     IMAGE_LOGD("CreatePixelMapFromSurface id:%{public}s,area:%{public}d,%{public}d,%{public}d,%{public}d",
1221         context->surfaceId.c_str(), context->area.region.left, context->area.region.top,
1222         context->area.region.height, context->area.region.width);
1223 
1224     if (!std::regex_match(context->surfaceId, std::regex("\\d+"))) {
1225         IMAGE_LOGE("CreatePixelMapFromSurface empty or invalid surfaceId");
1226         context->status = ERR_IMAGE_INVALID_PARAMETER;
1227         return;
1228     }
1229 
1230     auto &rsClient = Rosen::RSInterfaces::GetInstance();
1231     OHOS::Rect r = {
1232         .x = context->area.region.left,
1233         .y = context->area.region.top,
1234         .w = context->area.region.width,
1235         .h = context->area.region.height,
1236     };
1237     std::shared_ptr<Media::PixelMap> pixelMap =
1238         rsClient.CreatePixelMapFromSurfaceId(std::stoull(context->surfaceId), r);
1239 #ifndef EXT_PIXEL
1240     if (pixelMap == nullptr) {
1241         pixelMap = CreatePixelMapFromSurfaceId(std::stoull(context->surfaceId), context->area.region);
1242     }
1243 #endif
1244     context->rPixelMap = std::move(pixelMap);
1245 
1246     if (IMG_NOT_NULL(context->rPixelMap)) {
1247         context->status = SUCCESS;
1248     } else {
1249         context->status = ERR_IMAGE_INVALID_PARAMETER;
1250     }
1251 }
1252 
CreatePixelMapFromSurfaceComplete(napi_env env,napi_status status,void * data)1253 void PixelMapNapi::CreatePixelMapFromSurfaceComplete(napi_env env, napi_status status, void *data)
1254 {
1255     if (data == nullptr) {
1256         IMAGE_LOGE("CreatePixelMapFromSurfaceComplete invalid parameter: data is null");
1257         return;
1258     }
1259 
1260     napi_value constructor = nullptr;
1261     napi_value result = nullptr;
1262 
1263     IMAGE_LOGD("CreatePixelMapFromSurface IN");
1264     auto context = static_cast<PixelMapAsyncContext*>(data);
1265     status = napi_get_reference_value(env, sConstructor_, &constructor);
1266     if (IMG_IS_OK(status)) {
1267         status = NewPixelNapiInstance(env, constructor, context->rPixelMap, result);
1268     }
1269 
1270     if (!IMG_IS_OK(status)) {
1271         context->status = ERR_IMAGE_PIXELMAP_CREATE_FAILED;
1272         IMAGE_LOGE("New instance could not be obtained");
1273         napi_get_undefined(env, &result);
1274     }
1275 
1276     CommonCallbackRoutine(env, context, result);
1277 }
1278 
setSurfaceId(const char * surfaceId,std::string & dst)1279 void setSurfaceId(const char *surfaceId, std::string &dst)
1280 {
1281     dst = surfaceId;
1282 }
1283 
GetStringArgument(napi_env env,napi_value value)1284 static std::string GetStringArgument(napi_env env, napi_value value)
1285 {
1286     std::string strValue = "";
1287     size_t bufLength = 0;
1288     napi_status status = napi_get_value_string_utf8(env, value, nullptr, NUM_0, &bufLength);
1289     if (status == napi_ok && bufLength > NUM_0 && bufLength < PATH_MAX) {
1290         char *buffer = reinterpret_cast<char *>(malloc((bufLength + NUM_1) * sizeof(char)));
1291         if (buffer == nullptr) {
1292             IMAGE_LOGE("No memory");
1293             return strValue;
1294         }
1295 
1296         status = napi_get_value_string_utf8(env, value, buffer, bufLength + NUM_1, &bufLength);
1297         if (status == napi_ok) {
1298             IMAGE_LOGD("Get Success");
1299             strValue.assign(buffer, 0, bufLength + NUM_1);
1300         }
1301         if (buffer != nullptr) {
1302             free(buffer);
1303             buffer = nullptr;
1304         }
1305     }
1306     return strValue;
1307 }
1308 #endif
1309 
CreatePixelMapFromSurface(napi_env env,napi_callback_info info)1310 napi_value PixelMapNapi::CreatePixelMapFromSurface(napi_env env, napi_callback_info info)
1311 {
1312 #if defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
1313     napi_value result = nullptr;
1314     return result;
1315 #else
1316     napi_value globalValue;
1317     napi_get_global(env, &globalValue);
1318     napi_value func;
1319     napi_get_named_property(env, globalValue, "requireNapi", &func);
1320 
1321     napi_value imageInfo;
1322     napi_create_string_utf8(env, "multimedia.image", NAPI_AUTO_LENGTH, &imageInfo);
1323     napi_value funcArgv[1] = { imageInfo };
1324     napi_value returnValue;
1325     napi_call_function(env, globalValue, func, 1, funcArgv, &returnValue);
1326 
1327     napi_value result = nullptr;
1328     napi_get_undefined(env, &result);
1329     int32_t refCount = 1;
1330     napi_status status;
1331     napi_value thisVar = nullptr;
1332     napi_value argValue[NUM_4] = {0};
1333     size_t argCount = NUM_4;
1334     IMAGE_LOGD("CreatePixelMapFromSurface IN");
1335     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1336     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1337     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1338     asyncContext->surfaceId = GetStringArgument(env, argValue[NUM_0]);
1339     bool ret = parseRegion(env, argValue[NUM_1], &(asyncContext->area.region));
1340     IMAGE_LOGD("CreatePixelMapFromSurface get data: %{public}d", ret);
1341     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1342         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1343     }
1344     if (asyncContext->callbackRef == nullptr) {
1345         napi_create_promise(env, &(asyncContext->deferred), &result);
1346     } else {
1347         napi_get_undefined(env, &result);
1348     }
1349     IMG_NAPI_CHECK_BUILD_ERROR(ret,
1350         BuildContextError(env, asyncContext->error, "image invalid parameter", ERR_IMAGE_GET_DATA_ABNORMAL),
1351         IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePixelMapFromSurfaceGeneralError",
1352         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1353         result);
1354     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePixelMapFromSurface",
1355         CreatePixelMapFromSurfaceExec, CreatePixelMapFromSurfaceComplete, asyncContext, asyncContext->work);
1356     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1357         nullptr, IMAGE_LOGE("fail to create async work"));
1358     return result;
1359 #endif
1360 }
1361 
CreatePixelMapFromSurfaceSync(napi_env env,napi_callback_info info)1362 napi_value PixelMapNapi::CreatePixelMapFromSurfaceSync(napi_env env, napi_callback_info info)
1363 {
1364 #if defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
1365     napi_value result = nullptr;
1366     return result;
1367 #else
1368     if (PixelMapNapi::GetConstructor() == nullptr) {
1369         napi_value exports = nullptr;
1370         napi_create_object(env, &exports);
1371         PixelMapNapi::Init(env, exports);
1372     }
1373 
1374     napi_value result = nullptr;
1375     napi_get_undefined(env, &result);
1376     napi_value constructor = nullptr;
1377     napi_status status;
1378     napi_value thisVar = nullptr;
1379     napi_value argValue[NUM_2] = {0};
1380     size_t argCount = NUM_2;
1381     IMAGE_LOGD("CreatePixelMap IN");
1382 
1383     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1384     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1385         ImageNapiUtils::ThrowExceptionError(env, ERR_IMAGE_GET_DATA_ABNORMAL,
1386         "Failed to get data"),
1387         IMAGE_LOGE("CreatePixelMapFromSurfaceSync fail to get data"));
1388 
1389     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1390     asyncContext->surfaceId = GetStringArgument(env, argValue[NUM_0]);
1391     bool ret = parseRegion(env, argValue[NUM_1], &(asyncContext->area.region));
1392     IMAGE_LOGD("CreatePixelMapFromSurface get data: %{public}d", ret);
1393     IMG_NAPI_CHECK_RET_D(ret,
1394         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1395         "Invalid args count"),
1396         IMAGE_LOGE("CreatePixelMapFromSurfaceSync invalid args count"));
1397 
1398     CreatePixelMapFromSurfaceExec(env, static_cast<void*>((asyncContext).get()));
1399     status = napi_get_reference_value(env, sConstructor_, &constructor);
1400     if (IMG_IS_OK(status)) {
1401             status = NewPixelNapiInstance(env, constructor, asyncContext->rPixelMap, result);
1402     }
1403     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1404         ImageNapiUtils::ThrowExceptionError(env, ERR_IMAGE_PIXELMAP_CREATE_FAILED,
1405         "Failed to create pixelmap"),
1406         IMAGE_LOGE("CreatePixelMapFromSurfaceSync fail to create pixel map sync"));
1407     return result;
1408 #endif
1409 }
1410 
CreatePixelMap(napi_env env,std::shared_ptr<PixelMap> pixelmap)1411 napi_value PixelMapNapi::CreatePixelMap(napi_env env, std::shared_ptr<PixelMap> pixelmap)
1412 {
1413     if (PixelMapNapi::GetConstructor() == nullptr) {
1414         napi_value exports = nullptr;
1415         napi_create_object(env, &exports);
1416         PixelMapNapi::Init(env, exports);
1417     }
1418 
1419     napi_value constructor = nullptr;
1420     napi_value result = nullptr;
1421     napi_status status;
1422 
1423     IMAGE_LOGD("CreatePixelMap IN");
1424     status = napi_get_reference_value(env, sConstructor_, &constructor);
1425 
1426     if (IMG_IS_OK(status)) {
1427         status = NewPixelNapiInstance(env, constructor, pixelmap, result);
1428     }
1429 
1430     if (!IMG_IS_OK(status)) {
1431         IMAGE_LOGE("CreatePixelMap | New instance could not be obtained");
1432         napi_get_undefined(env, &result);
1433     }
1434 
1435     return result;
1436 }
1437 
STATIC_EXEC_FUNC(Unmarshalling)1438 STATIC_EXEC_FUNC(Unmarshalling)
1439 {
1440 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1441     if (data == nullptr) {
1442         IMAGE_LOGE("UnmarshallingExec invalid parameter: data is null");
1443         return;
1444     }
1445     auto context = static_cast<PixelMapAsyncContext*>(data);
1446 
1447     auto messageParcel = napi_messageSequence->GetMessageParcel();
1448     auto pixelmap = PixelMap::Unmarshalling(*messageParcel);
1449     std::unique_ptr<OHOS::Media::PixelMap> pixelmap_ptr(pixelmap);
1450 
1451     context->rPixelMap = std::move(pixelmap_ptr);
1452 
1453     if (IMG_NOT_NULL(context->rPixelMap)) {
1454         context->status = SUCCESS;
1455     } else {
1456         context->status = ERROR;
1457     }
1458 #endif
1459 }
1460 
UnmarshallingComplete(napi_env env,napi_status status,void * data)1461 void PixelMapNapi::UnmarshallingComplete(napi_env env, napi_status status, void *data)
1462 {
1463     if (data == nullptr) {
1464         IMAGE_LOGE("UnmarshallingComplete invalid parameter: data is null");
1465         return;
1466     }
1467 
1468     napi_value constructor = nullptr;
1469     napi_value result = nullptr;
1470 
1471     IMAGE_LOGD("UnmarshallingComplete IN");
1472     auto context = static_cast<PixelMapAsyncContext*>(data);
1473 
1474     status = napi_get_reference_value(env, sConstructor_, &constructor);
1475     if (IMG_IS_OK(status)) {
1476         status = NewPixelNapiInstance(env, constructor, context->rPixelMap, result);
1477     }
1478 
1479     if (!IMG_IS_OK(status)) {
1480         context->status = ERROR;
1481         IMAGE_LOGE("New instance could not be obtained");
1482         napi_get_undefined(env, &result);
1483     }
1484 
1485     CommonCallbackRoutine(env, context, result);
1486 }
1487 
Unmarshalling(napi_env env,napi_callback_info info)1488 napi_value PixelMapNapi::Unmarshalling(napi_env env, napi_callback_info info)
1489 {
1490 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1491     if (PixelMapNapi::GetConstructor() == nullptr) {
1492         napi_value exports = nullptr;
1493         napi_create_object(env, &exports);
1494         PixelMapNapi::Init(env, exports);
1495     }
1496     napi_value result = nullptr;
1497     napi_get_undefined(env, &result);
1498 
1499     int32_t refCount = 1;
1500 
1501     napi_status status;
1502     napi_value thisVar = nullptr;
1503     napi_value argValue[NUM_4] = {0};
1504     size_t argCount = NUM_4;
1505     IMAGE_LOGD("Unmarshalling IN");
1506 
1507     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1508 
1509     // we are static method!
1510     // thisVar is nullptr here
1511     if (!IMG_IS_OK(status)) {
1512         return ImageNapiUtils::ThrowExceptionError(
1513             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to napi_get_cb_info");
1514     }
1515     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1516 
1517     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1518         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1519     }
1520 
1521     napi_unwrap(env, argValue[NUM_0], (void **)&napi_messageSequence);
1522 
1523     if (asyncContext->callbackRef == nullptr) {
1524         napi_create_promise(env, &(asyncContext->deferred), &result);
1525     } else {
1526         napi_get_undefined(env, &result);
1527     }
1528 
1529     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "Unmarshalling",
1530         UnmarshallingExec, UnmarshallingComplete, asyncContext, asyncContext->work);
1531 
1532     if (!IMG_IS_OK(status)) {
1533         return ImageNapiUtils::ThrowExceptionError(
1534             env, ERROR, "Fail to create async work");
1535     }
1536     return result;
1537 #else
1538     napi_value result = nullptr;
1539     return result;
1540 #endif
1541 }
1542 
ThrowExceptionError(napi_env env,const std::string & tag,const std::uint32_t & code,const std::string & info)1543 napi_value PixelMapNapi::ThrowExceptionError(napi_env env,
1544     const std::string &tag, const std::uint32_t &code, const std::string &info)
1545 {
1546     auto errNode = ETS_API_ERROR_CODE.find(tag);
1547     if (errNode != ETS_API_ERROR_CODE.end() &&
1548         errNode->second.find(code) != errNode->second.end()) {
1549         return ImageNapiUtils::ThrowExceptionError(env, code, info);
1550     }
1551     return ImageNapiUtils::ThrowExceptionError(env, ERROR, "Operation failed");
1552 }
1553 
CreatePixelMapFromParcel(napi_env env,napi_callback_info info)1554 napi_value PixelMapNapi::CreatePixelMapFromParcel(napi_env env, napi_callback_info info)
1555 #if defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
1556 {
1557     napi_value result = nullptr;
1558     return result;
1559 }
1560 #else
1561 {
1562     if (PixelMapNapi::GetConstructor() == nullptr) {
1563         napi_value exports = nullptr;
1564         napi_create_object(env, &exports);
1565         PixelMapNapi::Init(env, exports);
1566     }
1567     napi_value result = nullptr;
1568     napi_get_undefined(env, &result);
1569     napi_status status;
1570     napi_value thisVar = nullptr;
1571     napi_value argValue[NUM_1] = {0};
1572     size_t argCount = NUM_1;
1573     IMAGE_LOGD("CreatePixelMapFromParcel IN");
1574     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1575     if (!IMG_IS_OK(status) || argCount != NUM_1) {
1576         return PixelMapNapi::ThrowExceptionError(env,
1577             CREATE_PIXEL_MAP_FROM_PARCEL, ERR_IMAGE_INVALID_PARAMETER, "Fail to napi_get_cb_info");
1578     }
1579     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1580     napi_unwrap(env, argValue[NUM_0], (void **)&napi_messageSequence);
1581     auto messageParcel = napi_messageSequence->GetMessageParcel();
1582     if (messageParcel == nullptr) {
1583         return PixelMapNapi::ThrowExceptionError(env,
1584             CREATE_PIXEL_MAP_FROM_PARCEL, ERR_IPC, "get pacel failed");
1585     }
1586     PIXEL_MAP_ERR error;
1587     auto pixelmap = PixelMap::Unmarshalling(*messageParcel, error);
1588     if (!IMG_NOT_NULL(pixelmap)) {
1589         return PixelMapNapi::ThrowExceptionError(env,
1590             CREATE_PIXEL_MAP_FROM_PARCEL, error.errorCode, error.errorInfo);
1591     }
1592     std::shared_ptr<OHOS::Media::PixelMap> pixelPtr(pixelmap);
1593     napi_value constructor = nullptr;
1594     status = napi_get_reference_value(env, sConstructor_, &constructor);
1595     if (IMG_IS_OK(status)) {
1596         status = NewPixelNapiInstance(env, constructor, pixelPtr, result);
1597     }
1598     if (!IMG_IS_OK(status)) {
1599         IMAGE_LOGE("New instance could not be obtained");
1600         return PixelMapNapi::ThrowExceptionError(env,
1601             CREATE_PIXEL_MAP_FROM_PARCEL, ERR_IMAGE_NAPI_ERROR, "New instance could not be obtained");
1602     }
1603     return result;
1604 }
1605 #endif
1606 
GetIsEditable(napi_env env,napi_callback_info info)1607 napi_value PixelMapNapi::GetIsEditable(napi_env env, napi_callback_info info)
1608 {
1609     napi_value result = nullptr;
1610     napi_get_undefined(env, &result);
1611 
1612     napi_status status;
1613     napi_value thisVar = nullptr;
1614     size_t argCount = 0;
1615     IMAGE_LOGD("GetIsEditable IN");
1616 
1617     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1618 
1619     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1620 
1621     PixelMapNapi* pixelMapNapi = nullptr;
1622     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1623 
1624     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1625 
1626     if (pixelMapNapi->nativePixelMap_ == nullptr) {
1627         return result;
1628     }
1629     bool isEditable = pixelMapNapi->nativePixelMap_->IsEditable();
1630 
1631     napi_get_boolean(env, isEditable, &result);
1632 
1633     return result;
1634 }
1635 
GetIsStrideAlignment(napi_env env,napi_callback_info info)1636 napi_value PixelMapNapi::GetIsStrideAlignment(napi_env env, napi_callback_info info)
1637 {
1638     napi_value result = nullptr;
1639     napi_get_undefined(env, &result);
1640 
1641     napi_status status;
1642     napi_value thisVar = nullptr;
1643     size_t argCount = 0;
1644     IMAGE_LOGD("GetIsStrideAlignment IN");
1645 
1646     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1647 
1648     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1649 
1650     PixelMapNapi* pixelMapNapi = nullptr;
1651     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1652 
1653     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi),
1654         result, IMAGE_LOGE("fail to unwrap context"));
1655 
1656     if (pixelMapNapi->nativePixelMap_ == nullptr) {
1657         return result;
1658     }
1659     bool isDMA = pixelMapNapi->nativePixelMap_->IsStrideAlignment();
1660     napi_get_boolean(env, isDMA, &result);
1661     return result;
1662 }
1663 
ReadPixelsToBuffer(napi_env env,napi_callback_info info)1664 napi_value PixelMapNapi::ReadPixelsToBuffer(napi_env env, napi_callback_info info)
1665 {
1666     ImageTrace imageTrace("PixelMapNapi::ReadPixelsToBuffer");
1667     napi_value result = nullptr;
1668     napi_get_undefined(env, &result);
1669 
1670     int32_t refCount = 1;
1671     napi_status status;
1672     napi_value thisVar = nullptr;
1673     napi_value argValue[NUM_2] = {0};
1674     size_t argCount = NUM_2;
1675 
1676     IMAGE_LOGD("ReadPixelsToBuffer IN");
1677     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1678 
1679     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1680 
1681     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1682     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1683 
1684     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1685         nullptr, IMAGE_LOGE("fail to unwrap context"));
1686     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1687 
1688     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1689         nullptr, IMAGE_LOGE("empty native pixelmap"));
1690 
1691     status = napi_get_arraybuffer_info(env, argValue[NUM_0],
1692         &(asyncContext->colorsBuffer), &(asyncContext->colorsBufferSize));
1693 
1694     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("colors mismatch"));
1695 
1696     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1697         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1698     }
1699 
1700     if (asyncContext->callbackRef == nullptr) {
1701         napi_create_promise(env, &(asyncContext->deferred), &result);
1702     } else {
1703         napi_get_undefined(env, &result);
1704     }
1705 
1706     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1707         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . ReadPixelsToBuffer failed",
1708         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ReadPixelsToBufferGeneralError",
1709         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1710         result);
1711     IMG_CREATE_CREATE_ASYNC_WORK_WITH_QOS(env, status, "ReadPixelsToBuffer",
1712         [](napi_env env, void *data) {
1713             auto context = static_cast<PixelMapAsyncContext*>(data);
1714             context->status = context->rPixelMap->ReadPixels(
1715                 context->colorsBufferSize, static_cast<uint8_t*>(context->colorsBuffer));
1716         }, EmptyResultComplete, asyncContext, asyncContext->work, napi_qos_user_initiated);
1717 
1718     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1719         nullptr, IMAGE_LOGE("fail to create async work"));
1720     return result;
1721 }
1722 
ReadPixelsToBufferSync(napi_env env,napi_callback_info info)1723 napi_value PixelMapNapi::ReadPixelsToBufferSync(napi_env env, napi_callback_info info)
1724 {
1725     ImageTrace imageTrace("PixelMapNapi::ReadPixelsToBufferSync");
1726     napi_value result = nullptr;
1727     napi_get_undefined(env, &result);
1728     napi_status napiStatus;
1729     uint32_t status = SUCCESS;
1730     napi_value thisVar = nullptr;
1731     size_t argCount = NUM_1;
1732     napi_value argValue[NUM_1] = {0};
1733     void* colorsBuffer = nullptr;
1734     size_t colorsBufferSize = 0;
1735 
1736     IMAGE_LOGD("ReadPixelsToBuffeSync IN");
1737     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
1738     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1739     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
1740         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1741         "ReadPixelsToBuffeSync failed"),
1742         IMAGE_LOGE("ReadPixelsToBuffeSync failed, invalid parameter"));
1743 
1744     napiStatus = napi_get_arraybuffer_info(env, argValue[NUM_0],
1745         &colorsBuffer, &colorsBufferSize);
1746     IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed"));
1747 
1748     PixelMapNapi* pixelMapNapi = nullptr;
1749     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1750 
1751     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1752     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1753         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1754         "Pixelmap has crossed threads . ReadPixelsToBuffeSync failed"),
1755         IMAGE_LOGE("Pixelmap has crossed threads . ReadPixelsToBuffeSync failed"));
1756 
1757     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1758         status = pixelMapNapi->nativePixelMap_->ReadPixels(
1759             colorsBufferSize, static_cast<uint8_t*>(colorsBuffer));
1760         if (status != SUCCESS) {
1761             IMAGE_LOGE("ReadPixels failed");
1762         }
1763     } else {
1764         IMAGE_LOGE("Null native ref");
1765     }
1766     return result;
1767 }
1768 
ReadPixels(napi_env env,napi_callback_info info)1769 napi_value PixelMapNapi::ReadPixels(napi_env env, napi_callback_info info)
1770 {
1771     napi_value result = nullptr;
1772     napi_get_undefined(env, &result);
1773 
1774     int32_t refCount = 1;
1775     napi_status status;
1776     napi_value thisVar = nullptr;
1777     napi_value argValue[NUM_2] = {0};
1778     size_t argCount = NUM_2;
1779 
1780     IMAGE_LOGD("ReadPixels IN");
1781     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1782 
1783     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1784 
1785     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1786     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1787 
1788     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1789         nullptr, IMAGE_LOGE("fail to unwrap context"));
1790 
1791     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1792 
1793     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1794         nullptr, IMAGE_LOGE("empty native pixelmap"));
1795 
1796     IMG_NAPI_CHECK_RET_D(parsePositionArea(env, argValue[NUM_0], &(asyncContext->area)),
1797         nullptr, IMAGE_LOGE("fail to parse position area"));
1798 
1799     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1800         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1801     }
1802 
1803     if (asyncContext->callbackRef == nullptr) {
1804         napi_create_promise(env, &(asyncContext->deferred), &result);
1805     } else {
1806         napi_get_undefined(env, &result);
1807     }
1808 
1809     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1810         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . ReadPixels failed",
1811         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ReadPixelsGeneralError",
1812         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1813         result);
1814     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ReadPixels",
1815         [](napi_env env, void *data) {
1816             auto context = static_cast<PixelMapAsyncContext*>(data);
1817             auto area = context->area;
1818             context->status = context->rPixelMap->ReadPixels(
1819                 area.size, area.offset, area.stride, area.region, static_cast<uint8_t*>(area.pixels));
1820         }, EmptyResultComplete, asyncContext, asyncContext->work);
1821 
1822     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1823         nullptr, IMAGE_LOGE("fail to create async work"));
1824     return result;
1825 }
1826 
ReadPixelsSync(napi_env env,napi_callback_info info)1827 napi_value PixelMapNapi::ReadPixelsSync(napi_env env, napi_callback_info info)
1828 {
1829     napi_value result = nullptr;
1830     napi_get_undefined(env, &result);
1831 
1832     napi_status status;
1833     napi_value thisVar = nullptr;
1834     napi_value argValue[NUM_1] = {0};
1835     size_t argCount = NUM_1;
1836     PositionArea area;
1837     IMAGE_LOGD("ReadPixelsSync IN");
1838     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1839 
1840     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1841     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
1842         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1843         "Invalid args count"),
1844         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
1845     IMG_NAPI_CHECK_RET_D(parsePositionArea(env, argValue[NUM_0], &area),
1846         nullptr, IMAGE_LOGE("fail to parse position area"));
1847 
1848     PixelMapNapi* pixelMapNapi = nullptr;
1849     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1850     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1851     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1852         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1853         "Pixelmap has crossed threads . ReadPixelsToBuffeSync failed"),
1854         IMAGE_LOGE("Pixelmap has crossed threads . ReadPixelsToBuffeSync failed"));
1855 
1856     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi->nativePixelMap_),
1857         nullptr, IMAGE_LOGE("empty native pixelmap"));
1858 
1859     auto nativeStatus = pixelMapNapi->nativePixelMap_->ReadPixels(
1860         area.size, area.offset, area.stride, area.region, static_cast<uint8_t*>(area.pixels));
1861 
1862     IMG_NAPI_CHECK_RET_D(nativeStatus == SUCCESS,
1863         nullptr, IMAGE_LOGE("fail to read pixels"));
1864     return result;
1865 }
1866 
WritePixels(napi_env env,napi_callback_info info)1867 napi_value PixelMapNapi::WritePixels(napi_env env, napi_callback_info info)
1868 {
1869     napi_value result = nullptr;
1870     napi_get_undefined(env, &result);
1871 
1872     int32_t refCount = 1;
1873     napi_status status;
1874     napi_value thisVar = nullptr;
1875     napi_value argValue[NUM_2] = {0};
1876     size_t argCount = NUM_2;
1877 
1878     IMAGE_LOGD("WritePixels IN");
1879     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1880 
1881     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1882 
1883     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1884     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1885 
1886     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1887         nullptr, IMAGE_LOGE("fail to unwrap context"));
1888     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1889 
1890     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1891         nullptr, IMAGE_LOGE("empty native pixelmap"));
1892 
1893     IMG_NAPI_CHECK_RET_D(parsePositionArea(env, argValue[NUM_0], &(asyncContext->area)),
1894         nullptr, IMAGE_LOGE("fail to parse position area"));
1895 
1896     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1897         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1898     }
1899 
1900     if (asyncContext->callbackRef == nullptr) {
1901         napi_create_promise(env, &(asyncContext->deferred), &result);
1902     } else {
1903         napi_get_undefined(env, &result);
1904     }
1905     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1906         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . WritePixels failed",
1907         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WritePixelsGeneralError",
1908         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1909         result);
1910     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WritePixels",
1911         [](napi_env env, void *data) {
1912             auto context = static_cast<PixelMapAsyncContext*>(data);
1913             auto area = context->area;
1914             context->status = context->rPixelMap->WritePixels(
1915                 static_cast<uint8_t*>(area.pixels), area.size, area.offset, area.stride, area.region);
1916         }, EmptyResultComplete, asyncContext, asyncContext->work);
1917 
1918     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1919         nullptr, IMAGE_LOGE("fail to create async work"));
1920     return result;
1921 }
1922 
WritePixelsSync(napi_env env,napi_callback_info info)1923 napi_value PixelMapNapi::WritePixelsSync(napi_env env, napi_callback_info info)
1924 {
1925     napi_value result = nullptr;
1926     napi_get_undefined(env, &result);
1927     napi_status napiStatus;
1928     uint32_t status = SUCCESS;
1929     napi_value thisVar = nullptr;
1930     size_t argCount = NUM_1;
1931     napi_value argValue[NUM_1] = {0};
1932     PositionArea area;
1933     IMAGE_LOGD("WritePixelsSyncIN");
1934     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
1935     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to arg info"));
1936     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
1937         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
1938         "Invalid args count"),
1939         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
1940     IMG_NAPI_CHECK_RET_D(parsePositionArea(env, argValue[NUM_0], &area),
1941         nullptr, IMAGE_LOGE("fail to parse position area"));
1942 
1943     PixelMapNapi* pixelMapNapi = nullptr;
1944     napiStatus = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1945     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1946     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1947         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1948         "Pixelmap has crossed threads . WritePixelsSync failed"),
1949         IMAGE_LOGE("Pixelmap has crossed threads . WritePixelsSync failed"));
1950 
1951     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1952         status = pixelMapNapi->nativePixelMap_->WritePixels(
1953             static_cast<uint8_t*>(area.pixels), area.size, area.offset, area.stride, area.region);
1954         IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr,
1955             IMAGE_LOGE("fail to write pixels"));
1956     } else {
1957         IMAGE_LOGE("Null native ref");
1958     }
1959     return result;
1960 }
1961 
WriteBufferToPixels(napi_env env,napi_callback_info info)1962 napi_value PixelMapNapi::WriteBufferToPixels(napi_env env, napi_callback_info info)
1963 {
1964     ImageTrace imageTrace("PixelMapNapi::WriteBufferToPixels");
1965     napi_value result = nullptr;
1966     napi_get_undefined(env, &result);
1967 
1968     int32_t refCount = 1;
1969     napi_status status;
1970     napi_value thisVar = nullptr;
1971     napi_value argValue[NUM_2] = {0};
1972     size_t argCount = NUM_2;
1973 
1974     IMAGE_LOGD("WriteBufferToPixels IN");
1975     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1976 
1977     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1978 
1979     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1980     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1981 
1982     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1983         nullptr, IMAGE_LOGE("fail to unwrap context"));
1984     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1985 
1986     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1987         nullptr, IMAGE_LOGE("empty native pixelmap"));
1988     status = napi_get_arraybuffer_info(env, argValue[NUM_0],
1989         &(asyncContext->colorsBuffer), &(asyncContext->colorsBufferSize));
1990 
1991     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1992         nullptr, IMAGE_LOGE("fail to get buffer info"));
1993 
1994     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1995         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1996     }
1997 
1998     if (asyncContext->callbackRef == nullptr) {
1999         napi_create_promise(env, &(asyncContext->deferred), &result);
2000     } else {
2001         napi_get_undefined(env, &result);
2002     }
2003     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
2004         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . WriteBufferToPixels failed",
2005         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WriteBufferToPixelsGeneralError",
2006         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
2007         result);
2008     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WriteBufferToPixels",
2009         [](napi_env env, void *data) {
2010             auto context = static_cast<PixelMapAsyncContext*>(data);
2011             context->status = context->rPixelMap->WritePixels(static_cast<uint8_t*>(context->colorsBuffer),
2012                 context->colorsBufferSize);
2013         }, EmptyResultComplete, asyncContext, asyncContext->work);
2014 
2015     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
2016         nullptr, IMAGE_LOGE("fail to create async work"));
2017     return result;
2018 }
2019 
WriteBufferToPixelsSync(napi_env env,napi_callback_info info)2020 napi_value PixelMapNapi::WriteBufferToPixelsSync(napi_env env, napi_callback_info info)
2021 {
2022     ImageTrace imageTrace("PixelMapNapi::WriteBufferToPixelsSync");
2023     napi_value result = nullptr;
2024     napi_get_undefined(env, &result);
2025     napi_status napiStatus;
2026     uint32_t status = SUCCESS;
2027     napi_value thisVar = nullptr;
2028     size_t argCount = NUM_1;
2029     napi_value argValue[NUM_1] = {0};
2030     void* colorsBuffer = nullptr;
2031     size_t colorsBufferSize = 0;
2032 
2033     IMAGE_LOGD("WriteBufferToPixelsSync IN");
2034     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
2035     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2036     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
2037         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2038         "WriteBufferToPixelsSync failed"),
2039         IMAGE_LOGE("WriteBufferToPixelsSync failed, invalid parameter"));
2040 
2041     napiStatus = napi_get_arraybuffer_info(env, argValue[NUM_0],
2042         &colorsBuffer, &colorsBufferSize);
2043     IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed"));
2044 
2045     PixelMapNapi* pixelMapNapi = nullptr;
2046     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2047 
2048     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2049     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2050         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2051         "Pixelmap has crossed threads . WriteBufferToPixelsSync failed"),
2052         IMAGE_LOGE("Pixelmap has crossed threads . WriteBufferToPixelsSync failed"));
2053 
2054     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2055         status = pixelMapNapi->nativePixelMap_->WritePixels(
2056             static_cast<uint8_t*>(colorsBuffer), colorsBufferSize);
2057         if (status != SUCCESS) {
2058             IMAGE_LOGE("WritePixels failed");
2059         }
2060     } else {
2061         IMAGE_LOGE("Null native ref");
2062     }
2063     return result;
2064 }
2065 
STATIC_NAPI_VALUE_FUNC(GetImageInfo)2066 STATIC_NAPI_VALUE_FUNC(GetImageInfo)
2067 {
2068     if (data == nullptr) {
2069         IMAGE_LOGE("GetImageInfoNapiValue invalid parameter: data is null");
2070         return nullptr;
2071     }
2072 
2073     IMAGE_LOGD("[PixelMap]GetImageInfoNapiValue IN");
2074     napi_value result = nullptr;
2075     napi_create_object(env, &result);
2076     auto imageInfo = static_cast<ImageInfo*>(data);
2077     auto rPixelMap = static_cast<PixelMap*>(ptr);
2078     napi_value size = nullptr;
2079     napi_create_object(env, &size);
2080     napi_value sizeWith = nullptr;
2081     napi_create_int32(env, imageInfo->size.width, &sizeWith);
2082     napi_set_named_property(env, size, "width", sizeWith);
2083     napi_value sizeHeight = nullptr;
2084     napi_create_int32(env, imageInfo->size.height, &sizeHeight);
2085     napi_set_named_property(env, size, "height", sizeHeight);
2086     napi_set_named_property(env, result, "size", size);
2087     napi_value pixelFormatValue = nullptr;
2088     napi_create_int32(env, static_cast<int32_t>(imageInfo->pixelFormat), &pixelFormatValue);
2089     napi_set_named_property(env, result, "pixelFormat", pixelFormatValue);
2090     napi_value colorSpaceValue = nullptr;
2091     napi_create_int32(env, static_cast<int32_t>(imageInfo->colorSpace), &colorSpaceValue);
2092     napi_set_named_property(env, result, "colorSpace", colorSpaceValue);
2093     napi_value alphaTypeValue = nullptr;
2094     napi_create_int32(env, static_cast<int32_t>(imageInfo->alphaType), &alphaTypeValue);
2095     napi_set_named_property(env, result, "alphaType", alphaTypeValue);
2096     napi_value densityValue = nullptr;
2097     napi_create_int32(env, static_cast<int32_t>(imageInfo->baseDensity), &densityValue);
2098     napi_set_named_property(env, result, "density", densityValue);
2099     napi_value strideValue = nullptr;
2100     napi_create_int32(env, static_cast<int32_t>(rPixelMap->GetRowStride()), &strideValue);
2101     napi_set_named_property(env, result, "stride", strideValue);
2102     napi_value encodedFormatValue = nullptr;
2103     napi_create_string_utf8(env, imageInfo->encodedFormat.c_str(),
2104         imageInfo->encodedFormat.length(), &encodedFormatValue);
2105     napi_set_named_property(env, result, "mimeType", encodedFormatValue);
2106     napi_value isHdrValue = nullptr;
2107     napi_get_boolean(env, rPixelMap->IsHdr(), &isHdrValue);
2108     napi_set_named_property(env, result, "isHdr", isHdrValue);
2109     return result;
2110 }
2111 
STATIC_COMPLETE_FUNC(GetImageInfo)2112 STATIC_COMPLETE_FUNC(GetImageInfo)
2113 {
2114     IMAGE_LOGD("[PixelMap]GetImageInfoComplete IN");
2115     auto context = static_cast<PixelMapAsyncContext*>(data);
2116     napi_value result = GetImageInfoNapiValue(env, &(context->imageInfo), context->rPixelMap.get());
2117 
2118     if (!IMG_IS_OK(status)) {
2119         context->status = ERROR;
2120         IMAGE_LOGE("napi_create_int32 failed!");
2121         napi_get_undefined(env, &result);
2122     } else {
2123         context->status = SUCCESS;
2124     }
2125     IMAGE_LOGD("[PixelMap]GetImageInfoComplete OUT");
2126     CommonCallbackRoutine(env, context, result);
2127 }
GetImageInfo(napi_env env,napi_callback_info info)2128 napi_value PixelMapNapi::GetImageInfo(napi_env env, napi_callback_info info)
2129 {
2130     napi_value result = nullptr;
2131     napi_get_undefined(env, &result);
2132     int32_t refCount = 1;
2133     napi_status status;
2134     napi_value thisVar = nullptr;
2135     napi_value argValue[NUM_1] = {0};
2136     size_t argCount = 1;
2137     IMAGE_LOGD("GetImageInfo IN");
2138     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2139     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
2140     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
2141     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
2142     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
2143         nullptr, IMAGE_LOGE("fail to unwrap context"));
2144     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
2145     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
2146         nullptr, IMAGE_LOGE("empty native pixelmap"));
2147     if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
2148         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
2149     }
2150     if (asyncContext->callbackRef == nullptr) {
2151         napi_create_promise(env, &(asyncContext->deferred), &result);
2152     } else {
2153         napi_get_undefined(env, &result);
2154     }
2155     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
2156         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . GetImageInfo failed",
2157         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageInfoGeneralError",
2158         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
2159         result);
2160     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageInfo",
2161         [](napi_env env, void *data) {
2162             auto context = static_cast<PixelMapAsyncContext*>(data);
2163             context->rPixelMap->GetImageInfo(context->imageInfo);
2164             context->status = SUCCESS;
2165         }, GetImageInfoComplete, asyncContext, asyncContext->work);
2166     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
2167         nullptr, IMAGE_LOGE("fail to create async work"));
2168     return result;
2169 }
2170 
GetImageInfoSync(napi_env env,napi_callback_info info)2171 napi_value PixelMapNapi::GetImageInfoSync(napi_env env, napi_callback_info info)
2172 {
2173     napi_value result = nullptr;
2174     napi_get_undefined(env, &result);
2175     napi_status napiStatus;
2176     napi_value thisVar = nullptr;
2177     size_t argCount = NUM_0;
2178 
2179     IMAGE_LOGD("GetImageInfoSync IN");
2180     IMG_JS_ARGS(env, info, napiStatus, argCount, nullptr, thisVar);
2181     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to arg info"));
2182 
2183     PixelMapNapi* pixelMapNapi = nullptr;
2184     napiStatus = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2185 
2186     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2187     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2188         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2189         "Pixelmap has crossed threads . GetImageInfoSync failed"),
2190         IMAGE_LOGE("Pixelmap has crossed threads . GetImageInfoSync failed"));
2191 
2192     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2193         ImageInfo imageinfo;
2194         pixelMapNapi->nativePixelMap_->GetImageInfo(imageinfo);
2195         result = GetImageInfoNapiValue(env, &imageinfo, pixelMapNapi->nativePixelMap_.get());
2196     } else {
2197         IMAGE_LOGE("native pixelmap is nullptr!");
2198     }
2199     return result;
2200 }
2201 
GetBytesNumberPerRow(napi_env env,napi_callback_info info)2202 napi_value PixelMapNapi::GetBytesNumberPerRow(napi_env env, napi_callback_info info)
2203 {
2204     ImageTrace imageTrace("PixelMapNapi::GetBytesNumberPerRow");
2205     napi_value result = nullptr;
2206     napi_get_undefined(env, &result);
2207 
2208     napi_status status;
2209     napi_value thisVar = nullptr;
2210     size_t argCount = 0;
2211 
2212     IMAGE_LOGD("GetBytesNumberPerRow IN");
2213     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
2214 
2215     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2216 
2217     PixelMapNapi* pixelMapNapi = nullptr;
2218     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2219 
2220     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2221     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2222         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2223         "Pixelmap has crossed threads . GetBytesNumberPerRow failed"),
2224         IMAGE_LOGE("Pixelmap has crossed threads . GetBytesNumberPerRow failed"));
2225 
2226     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2227         uint32_t rowBytes = pixelMapNapi->nativePixelMap_->GetRowBytes();
2228         status = napi_create_int32(env, rowBytes, &result);
2229         if (!IMG_IS_OK(status)) {
2230             IMAGE_LOGE("napi_create_int32 failed!");
2231         }
2232     } else {
2233         IMAGE_LOGE("native pixelmap is nullptr!");
2234     }
2235     return result;
2236 }
2237 
GetPixelBytesNumber(napi_env env,napi_callback_info info)2238 napi_value PixelMapNapi::GetPixelBytesNumber(napi_env env, napi_callback_info info)
2239 {
2240     ImageTrace imageTrace("PixelMapNapi::GetPixelBytesNumber");
2241     napi_value result = nullptr;
2242     napi_get_undefined(env, &result);
2243 
2244     napi_status status;
2245     napi_value thisVar = nullptr;
2246     size_t argCount = 0;
2247 
2248     IMAGE_LOGD("GetPixelBytesNumber IN");
2249     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
2250 
2251     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2252 
2253     PixelMapNapi* pixelMapNapi = nullptr;
2254     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2255 
2256     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2257     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2258         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2259         "Pixelmap has crossed threads . GetPixelBytesNumber failed"),
2260         IMAGE_LOGE("Pixelmap has crossed threads . GetPixelBytesNumber failed"));
2261 
2262     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2263         uint32_t byteCount = pixelMapNapi->nativePixelMap_->GetByteCount();
2264         status = napi_create_int32(env, byteCount, &result);
2265         if (!IMG_IS_OK(status)) {
2266             IMAGE_LOGE("napi_create_int32 failed!");
2267         }
2268     } else {
2269         IMAGE_LOGE("native pixelmap is nullptr!");
2270     }
2271     return result;
2272 }
2273 
IsSupportAlpha(napi_env env,napi_callback_info info)2274 napi_value PixelMapNapi::IsSupportAlpha(napi_env env, napi_callback_info info)
2275 {
2276     napi_value result = nullptr;
2277     napi_get_undefined(env, &result);
2278 
2279     napi_status status;
2280     napi_value thisVar = nullptr;
2281     size_t argCount = NUM_0;
2282 
2283     IMAGE_LOGD("IsSupportAlpha IN");
2284     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
2285 
2286     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2287 
2288     PixelMapNapi* pixelMapNapi = nullptr;
2289     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2290 
2291     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2292     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2293         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2294         "Pixelmap has crossed threads . IsSupportAlpha failed"),
2295         IMAGE_LOGE("Pixelmap has crossed threads . IsSupportAlpha failed"));
2296 
2297     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2298         AlphaType alphaType = pixelMapNapi->nativePixelMap_->GetAlphaType();
2299         bool isSupportAlpha = !(alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
2300         status = napi_get_boolean(env, isSupportAlpha, &result);
2301         if (!IMG_IS_OK(status)) {
2302             IMAGE_LOGE("napi_create_bool failed!");
2303         }
2304     } else {
2305         IMAGE_LOGE("native pixelmap is nullptr!");
2306     }
2307     return result;
2308 }
2309 
SetAlphaAble(napi_env env,napi_callback_info info)2310 napi_value PixelMapNapi::SetAlphaAble(napi_env env, napi_callback_info info)
2311 {
2312     napi_value result = nullptr;
2313     napi_get_undefined(env, &result);
2314 
2315     napi_status status;
2316     napi_value thisVar = nullptr;
2317     napi_value argValue[NUM_1] = {0};
2318     size_t argCount = NUM_1;
2319     bool isAlphaAble = false;
2320 
2321     IMAGE_LOGD("SetAlphaAble IN");
2322     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2323 
2324     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2325     NAPI_ASSERT(env, argCount > NUM_0, "Invalid input");
2326     NAPI_ASSERT(env, ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_boolean, "Invalid input type");
2327     NAPI_ASSERT(env, napi_get_value_bool(env, argValue[NUM_0], &isAlphaAble) == napi_ok, "Parse input error");
2328 
2329     PixelMapNapi* pixelMapNapi = nullptr;
2330     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2331 
2332     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2333     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2334         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2335         "Pixelmap has crossed threads . SetAlphaAble failed"),
2336         IMAGE_LOGE("Pixelmap has crossed threads . SetAlphaAble failed"));
2337     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2338         AlphaType alphaType = pixelMapNapi->nativePixelMap_->GetAlphaType();
2339         if (isAlphaAble && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
2340             pixelMapNapi->nativePixelMap_->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
2341         } else if ((!isAlphaAble) && !(alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
2342             pixelMapNapi->nativePixelMap_->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
2343         }
2344     } else {
2345         IMAGE_LOGE("native pixelmap is nullptr!");
2346     }
2347     return result;
2348 }
2349 
CreateAlphaPixelmapComplete(napi_env env,napi_status status,void * data)2350 static void CreateAlphaPixelmapComplete(napi_env env, napi_status status, void *data)
2351 {
2352     if (data == nullptr) {
2353         IMAGE_LOGE("CreateAlphaPixelmapComplete invalid parameter: data is null");
2354         return;
2355     }
2356 
2357     napi_value result = nullptr;
2358     napi_get_undefined(env, &result);
2359     auto context = static_cast<PixelMapAsyncContext*>(data);
2360 
2361     if (context->alphaMap != nullptr) {
2362         result = PixelMapNapi::CreatePixelMap(env, context->alphaMap);
2363         context->status = SUCCESS;
2364     } else {
2365         context->status = ERROR;
2366     }
2367     CommonCallbackRoutine(env, context, result);
2368 }
2369 
CreateAlphaPixelmap(napi_env env,napi_callback_info info)2370 napi_value PixelMapNapi::CreateAlphaPixelmap(napi_env env, napi_callback_info info)
2371 {
2372     napi_value result = nullptr;
2373     napi_get_undefined(env, &result);
2374     int32_t refCount = 1;
2375     napi_status status;
2376     napi_value thisVar = nullptr;
2377     napi_value argValue[NUM_1] = {0};
2378     size_t argCount = 1;
2379     IMAGE_LOGD("CreateAlphaPixelmap IN");
2380     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2381     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
2382     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
2383     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
2384     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
2385         nullptr, IMAGE_LOGE("fail to unwrap context"));
2386     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
2387     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
2388         nullptr, IMAGE_LOGE("empty native pixelmap"));
2389     if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
2390         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
2391     }
2392     if (asyncContext->callbackRef == nullptr) {
2393         napi_create_promise(env, &(asyncContext->deferred), &result);
2394     } else {
2395         napi_get_undefined(env, &result);
2396     }
2397     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
2398         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . CreateAlphaPixelmap failed",
2399         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateAlphaPixelmapGeneralError",
2400         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
2401         result);
2402     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateAlphaPixelmap",
2403         [](napi_env env, void *data) {
2404             auto context = static_cast<PixelMapAsyncContext*>(data);
2405             InitializationOptions opts;
2406             opts.pixelFormat = PixelFormat::ALPHA_8;
2407             auto tmpPixelMap = PixelMap::Create(*(context->rPixelMap), opts);
2408             context->alphaMap = std::move(tmpPixelMap);
2409             context->status = SUCCESS;
2410         }, CreateAlphaPixelmapComplete, asyncContext, asyncContext->work);
2411     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
2412         nullptr, IMAGE_LOGE("fail to create async work"));
2413     return result;
2414 }
2415 
CreateAlphaPixelmapSync(napi_env env,napi_callback_info info)2416 napi_value PixelMapNapi::CreateAlphaPixelmapSync(napi_env env, napi_callback_info info)
2417 {
2418     napi_value result = nullptr;
2419     napi_get_undefined(env, &result);
2420     napi_status napiStatus;
2421     uint32_t status = SUCCESS;
2422     napi_value thisVar = nullptr;
2423     size_t argCount = NUM_0;
2424 
2425     IMAGE_LOGD("CreateAlphaPixelmapSync IN");
2426     IMG_JS_ARGS(env, info, napiStatus, argCount, nullptr, thisVar);
2427     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2428     IMG_NAPI_CHECK_RET_D(argCount == NUM_0,
2429         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2430         "CreateAlphaPixelmapSync failed"),
2431         IMAGE_LOGE("CreateAlphaPixelmapSync failed, invalid parameter"));
2432 
2433     PixelMapNapi* pixelMapNapi = nullptr;
2434     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2435 
2436     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2437     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2438         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2439         "Pixelmap has crossed threads . CreateAlphaPixelmapSync failed"),
2440         IMAGE_LOGE("Pixelmap has crossed threads . CreateAlphaPixelmapSync failed"));
2441 
2442     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2443         InitializationOptions opts;
2444         opts.pixelFormat = PixelFormat::ALPHA_8;
2445         auto tmpPixelMap = PixelMap::Create(*(pixelMapNapi->nativePixelMap_), opts);
2446         result = PixelMapNapi::CreatePixelMap(env, std::move(tmpPixelMap));
2447     } else {
2448         IMAGE_LOGE("Null native ref");
2449     }
2450     return result;
2451 }
2452 
GetDensity(napi_env env,napi_callback_info info)2453 napi_value PixelMapNapi::GetDensity(napi_env env, napi_callback_info info)
2454 {
2455     napi_value result = nullptr;
2456     napi_get_undefined(env, &result);
2457 
2458     napi_status status;
2459     napi_value thisVar = nullptr;
2460     size_t argCount = 0;
2461 
2462     IMAGE_LOGD("GetDensity IN");
2463     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
2464 
2465     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2466 
2467     PixelMapNapi* pixelMapNapi = nullptr;
2468     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2469 
2470     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2471     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2472         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2473         "Pixelmap has crossed threads . GetDensity failed"),
2474         IMAGE_LOGE("Pixelmap has crossed threads . GetDensity failed"));
2475 
2476     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2477         uint32_t baseDensity = static_cast<uint32_t>(pixelMapNapi->nativePixelMap_->GetBaseDensity());
2478         status = napi_create_int32(env, baseDensity, &result);
2479         if (!IMG_IS_OK(status)) {
2480             IMAGE_LOGE("napi_create_int32 failed!");
2481         }
2482     } else {
2483         IMAGE_LOGE("native pixelmap is nullptr!");
2484     }
2485     return result;
2486 }
2487 
SetDensity(napi_env env,napi_callback_info info)2488 napi_value PixelMapNapi::SetDensity(napi_env env, napi_callback_info info)
2489 {
2490     napi_value result = nullptr;
2491     napi_get_undefined(env, &result);
2492 
2493     napi_status status;
2494     napi_value thisVar = nullptr;
2495     napi_value argValue[NUM_1] = {0};
2496     size_t argCount = NUM_1;
2497     uint32_t density = 0;
2498 
2499     IMAGE_LOGD("SetDensity IN");
2500     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2501     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2502 
2503     NAPI_ASSERT(env,
2504         (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_number),
2505         "Density input mismatch");
2506     NAPI_ASSERT(env, napi_get_value_uint32(env, argValue[NUM_0], &density) == napi_ok, "Could not parse density");
2507 
2508     PixelMapNapi* pixelMapNapi = nullptr;
2509     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2510 
2511     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2512     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2513         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2514         "Pixelmap has crossed threads . SetDensity failed"),
2515         IMAGE_LOGE("Pixelmap has crossed threads . SetDensity failed"));
2516     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2517         ImageInfo imageinfo;
2518         pixelMapNapi->nativePixelMap_->GetImageInfo(imageinfo);
2519         imageinfo.baseDensity = static_cast<int32_t>(density);
2520         pixelMapNapi->nativePixelMap_->SetImageInfo(imageinfo, true);
2521     } else {
2522         IMAGE_LOGE("native pixelmap is nullptr!");
2523     }
2524     return result;
2525 }
2526 
Release(napi_env env,napi_callback_info info)2527 napi_value PixelMapNapi::Release(napi_env env, napi_callback_info info)
2528 {
2529     napi_value result = nullptr;
2530     napi_get_undefined(env, &result);
2531 
2532     int32_t refCount = 1;
2533     napi_status status;
2534     napi_value thisVar = nullptr;
2535     napi_value argValue[1] = {0};
2536     size_t argCount = 1;
2537 
2538     IMAGE_LOGD("Release IN");
2539     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2540 
2541     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
2542 
2543     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
2544     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
2545 
2546     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
2547         nullptr, IMAGE_LOGE("fail to unwrap context"));
2548 
2549     if (argCount == 1 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
2550         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
2551     }
2552 
2553     if (asyncContext->callbackRef == nullptr) {
2554         napi_create_promise(env, &(asyncContext->deferred), &result);
2555     } else {
2556         napi_get_undefined(env, &result);
2557     }
2558     if (asyncContext->nConstructor->IsLockPixelMap()) {
2559         asyncContext->status = ERROR;
2560     } else {
2561         if (asyncContext->nConstructor->nativePixelMap_ != nullptr) {
2562             IMAGE_LOGD("Release in napi_id:%{public}d, id:%{public}d",
2563                 asyncContext->nConstructor->GetUniqueId(),
2564                 asyncContext->nConstructor->nativePixelMap_->GetUniqueId());
2565             asyncContext->nConstructor->nativePixelMap_.reset();
2566         }
2567         asyncContext->status = SUCCESS;
2568     }
2569     IMG_CREATE_CREATE_ASYNC_WORK_WITH_QOS(env, status, "Release",
2570         [](napi_env env, void *data) {
2571         }, EmptyResultComplete, asyncContext, asyncContext->work, napi_qos_user_initiated);
2572 
2573     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
2574         nullptr, IMAGE_LOGE("fail to create async work"));
2575     return result;
2576 }
2577 
2578 struct NapiValues {
2579     napi_status status;
2580     napi_value thisVar = nullptr;
2581     napi_value result = nullptr;
2582     napi_value* argv = nullptr;
2583     size_t argc;
2584     int32_t refCount = 1;
2585     std::unique_ptr<PixelMapAsyncContext> context;
2586 };
2587 
prepareNapiEnv(napi_env env,napi_callback_info info,struct NapiValues * nVal)2588 static bool prepareNapiEnv(napi_env env, napi_callback_info info, struct NapiValues* nVal)
2589 {
2590     if (nVal == nullptr) {
2591         IMAGE_LOGE("prepareNapiEnv invalid parameter: nVal is null");
2592         return false;
2593     }
2594 
2595     napi_get_undefined(env, &(nVal->result));
2596     nVal->status = napi_get_cb_info(env, info, &(nVal->argc), nVal->argv, &(nVal->thisVar), nullptr);
2597     if (nVal->status != napi_ok) {
2598         IMAGE_LOGE("fail to napi_get_cb_info");
2599         return false;
2600     }
2601     nVal->context = std::make_unique<PixelMapAsyncContext>();
2602     nVal->status = napi_unwrap(env, nVal->thisVar, reinterpret_cast<void**>(&(nVal->context->nConstructor)));
2603     if (nVal->status != napi_ok) {
2604         IMAGE_LOGE("fail to unwrap context");
2605         return false;
2606     }
2607     if (nVal->context->nConstructor == nullptr ||
2608         nVal->context->nConstructor->GetPixelNapiInner() == nullptr) {
2609         IMAGE_LOGE("prepareNapiEnv pixelmap is nullptr");
2610         return false;
2611     }
2612     nVal->context->status = SUCCESS;
2613     return true;
2614 }
2615 
SetAlphaExec(napi_env env,PixelMapAsyncContext * context)2616 static void SetAlphaExec(napi_env env, PixelMapAsyncContext* context)
2617 {
2618     if (context == nullptr) {
2619         IMAGE_LOGE("Null context");
2620         return;
2621     }
2622     if (context->status == SUCCESS) {
2623         if (context->rPixelMap != nullptr) {
2624             context->status = context->rPixelMap->SetAlpha(
2625                 static_cast<float>(context->alpha));
2626         } else {
2627             IMAGE_LOGE("Null native ref");
2628             context->status = ERR_IMAGE_INIT_ABNORMAL;
2629         }
2630     } else {
2631         IMAGE_LOGD("Scale has failed. do nothing");
2632     }
2633 }
2634 
SetAlpha(napi_env env,napi_callback_info info)2635 napi_value PixelMapNapi::SetAlpha(napi_env env, napi_callback_info info)
2636 {
2637     NapiValues nVal;
2638     nVal.argc = NUM_2;
2639     napi_value argValue[NUM_2] = {0};
2640     nVal.argv = argValue;
2641 
2642     IMAGE_LOGD("SetAlpha IN");
2643     if (!prepareNapiEnv(env, info, &nVal)) {
2644         return nVal.result;
2645     }
2646     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2647 
2648     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
2649         IMAGE_LOGE("Invalid args count %{public}zu", nVal.argc);
2650         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2651     } else {
2652         if (napi_ok !=
2653             napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->alpha))) {
2654             IMAGE_LOGE("Arg 0 type mismatch");
2655             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2656         }
2657     }
2658     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2659         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2660     }
2661 
2662     if (nVal.context->callbackRef == nullptr) {
2663         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2664     }
2665     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2666         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . SetAlpha failed",
2667         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "SetAlphaGeneralError",
2668         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2669         nVal.result);
2670     napi_value _resource = nullptr;
2671     napi_create_string_utf8(env, "SetAlpha", NAPI_AUTO_LENGTH, &_resource);
2672     nVal.status = napi_create_async_work(env, nullptr, _resource,
2673         [](napi_env env, void *data) {
2674             auto context = static_cast<PixelMapAsyncContext*>(data);
2675             SetAlphaExec(env, context);
2676         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2677 
2678     if (nVal.status == napi_ok) {
2679         nVal.status = napi_queue_async_work(env, nVal.context->work);
2680         if (nVal.status == napi_ok) {
2681             nVal.context.release();
2682         }
2683     }
2684     return nVal.result;
2685 }
2686 
SetAlphaSync(napi_env env,napi_callback_info info)2687 napi_value PixelMapNapi::SetAlphaSync(napi_env env, napi_callback_info info)
2688 {
2689     napi_value result = nullptr;
2690     napi_get_undefined(env, &result);
2691     napi_status napiStatus;
2692     uint32_t status = SUCCESS;
2693     napi_value thisVar = nullptr;
2694     size_t argCount = NUM_1;
2695     napi_value argValue[NUM_1] = {0};
2696     double alpha = 0;
2697 
2698     IMAGE_LOGD("SetAlphaSync IN");
2699     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
2700     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2701     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
2702         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2703         "SetAlphaSync failed"),
2704         IMAGE_LOGE("SetAlphaSync failed, invalid parameter"));
2705     napiStatus= napi_get_value_double(env, argValue[NUM_0], &alpha);
2706 
2707     IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed"));
2708 
2709     PixelMapNapi* pixelMapNapi = nullptr;
2710     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2711 
2712     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2713     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2714         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2715         "Pixelmap has crossed threads . SetAlphaSync failed"),
2716         IMAGE_LOGE("Pixelmap has crossed threads . SetAlphaSync failed"));
2717 
2718     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2719         status = pixelMapNapi->nativePixelMap_->SetAlpha(
2720             static_cast<float>(alpha));
2721         if (status != SUCCESS) {
2722             IMAGE_LOGE("SetAlphaSync failed");
2723         }
2724     } else {
2725         IMAGE_LOGE("Null native ref");
2726     }
2727     return result;
2728 }
2729 
ScaleExec(napi_env env,PixelMapAsyncContext * context)2730 static void ScaleExec(napi_env env, PixelMapAsyncContext* context)
2731 {
2732     if (context == nullptr) {
2733         IMAGE_LOGE("Null context");
2734         return;
2735     }
2736     if (context->status == SUCCESS) {
2737         if (context->rPixelMap != nullptr) {
2738             if (context->antiAliasing == AntiAliasingOption::NONE) {
2739                 context->rPixelMap->scale(static_cast<float>(context->xArg), static_cast<float>(context->yArg));
2740             } else {
2741                 context->rPixelMap->scale(static_cast<float>(context->xArg), static_cast<float>(context->yArg),
2742                     context->antiAliasing);
2743             }
2744             context->status = SUCCESS;
2745         } else {
2746             IMAGE_LOGE("Null native ref");
2747             context->status = ERR_IMAGE_INIT_ABNORMAL;
2748         }
2749     } else {
2750         IMAGE_LOGD("Scale has failed. do nothing");
2751     }
2752 }
2753 
NapiParseCallbackOrAntiAliasing(napi_env & env,NapiValues & nVal,int argi)2754 static void NapiParseCallbackOrAntiAliasing(napi_env &env, NapiValues &nVal, int argi)
2755 {
2756     if (ImageNapiUtils::getType(env, nVal.argv[argi]) == napi_function) {
2757         napi_create_reference(env, nVal.argv[argi], nVal.refCount, &(nVal.context->callbackRef));
2758     } else {
2759         int32_t antiAliasing;
2760         if (!IMG_IS_OK(napi_get_value_int32(env, nVal.argv[argi], &antiAliasing))) {
2761             IMAGE_LOGE("Arg %{public}d type mismatch", argi);
2762             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2763         }
2764         nVal.context->antiAliasing = ParseAntiAliasingOption(antiAliasing);
2765     }
2766 }
2767 
Scale(napi_env env,napi_callback_info info)2768 napi_value PixelMapNapi::Scale(napi_env env, napi_callback_info info)
2769 {
2770     NapiValues nVal;
2771     nVal.argc = NUM_3;
2772     napi_value argValue[NUM_3] = {0};
2773     nVal.argv = argValue;
2774     IMAGE_LOGD("Scale IN");
2775     if (!prepareNapiEnv(env, info, &nVal)) {
2776         return nVal.result;
2777     }
2778     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2779 
2780     if (nVal.argc != NUM_2 && nVal.argc != NUM_3) {
2781         IMAGE_LOGE("Invalid args count %{public}zu", nVal.argc);
2782         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2783     } else {
2784         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->xArg))) {
2785             IMAGE_LOGE("Arg 0 type mismatch");
2786             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2787         }
2788         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_1], &(nVal.context->yArg))) {
2789             IMAGE_LOGE("Arg 1 type mismatch");
2790             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2791         }
2792     }
2793     if (nVal.argc == NUM_3) {
2794         NapiParseCallbackOrAntiAliasing(env, nVal, NUM_2);
2795     }
2796 
2797     if (nVal.context->callbackRef == nullptr) {
2798         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2799     }
2800     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2801         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Scale failed",
2802         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "ScaleGeneralError",
2803         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2804         nVal.result);
2805     napi_value _resource = nullptr;
2806     napi_create_string_utf8(env, "Scale", NAPI_AUTO_LENGTH, &_resource);
2807     nVal.status = napi_create_async_work(env, nullptr, _resource,
2808         [](napi_env env, void *data) {
2809             auto context = static_cast<PixelMapAsyncContext*>(data);
2810             ScaleExec(env, context);
2811         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2812 
2813     if (nVal.status == napi_ok) {
2814         nVal.status = napi_queue_async_work_with_qos(env, nVal.context->work, napi_qos_user_initiated);
2815         if (nVal.status == napi_ok) {
2816             nVal.context.release();
2817         }
2818     }
2819     return nVal.result;
2820 }
2821 
ScaleSync(napi_env env,napi_callback_info info)2822 napi_value PixelMapNapi::ScaleSync(napi_env env, napi_callback_info info)
2823 {
2824     napi_value result = nullptr;
2825     napi_get_undefined(env, &result);
2826     napi_status napiStatus;
2827     uint32_t status = SUCCESS;
2828     napi_value thisVar = nullptr;
2829     size_t argCount = NUM_3;
2830     napi_value argValue[NUM_3] = {0};
2831     double xArg = 0;
2832     double yArg = 0;
2833     int32_t antiAliasing = 0;
2834     IMAGE_LOGD("ScaleSync IN");
2835     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
2836 
2837     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to arg info"));
2838 
2839     IMG_NAPI_CHECK_RET_D(argCount == NUM_2 || argCount == NUM_3,
2840         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2841         "Invalid args count"),
2842         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
2843     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_double(env, argValue[NUM_0], &xArg)),
2844         result, IMAGE_LOGE("Arg 0 type mismatch"));
2845     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_double(env, argValue[NUM_1], &yArg)),
2846         result, IMAGE_LOGE("Arg 1 type mismatch"));
2847     if (argCount == NUM_3) {
2848         IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_int32(env, argValue[NUM_2], &antiAliasing)),
2849             result, IMAGE_LOGE("Arg 2 type mismatch"));
2850     }
2851     PixelMapNapi* pixelMapNapi = nullptr;
2852     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2853 
2854     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2855     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
2856         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2857         "Pixelmap has crossed threads . ScaleSync failed"),
2858         IMAGE_LOGE("Pixelmap has crossed threads . ScaleSync failed"));
2859 
2860     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2861         if (antiAliasing == 0) {
2862             pixelMapNapi->nativePixelMap_->scale(static_cast<float>(xArg), static_cast<float>(yArg));
2863         } else {
2864             pixelMapNapi->nativePixelMap_->scale(static_cast<float>(xArg), static_cast<float>(yArg),
2865                 ParseAntiAliasingOption(antiAliasing));
2866         }
2867     } else {
2868         IMAGE_LOGE("Null native ref");
2869     }
2870     return result;
2871 }
2872 
SetMemoryNameSync(napi_env env,napi_callback_info info)2873 napi_value PixelMapNapi::SetMemoryNameSync(napi_env env, napi_callback_info info)
2874 {
2875     napi_value result = nullptr;
2876 #if defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
2877     return result;
2878 #else
2879     napi_get_undefined(env, &result);
2880     napi_status napiStatus;
2881     napi_value thisVar = nullptr;
2882     size_t argCount = NUM_1;
2883     napi_value argValue[NUM_1] = {0};
2884     NapiValues nVal;
2885     nVal.argc = NUM_1;
2886     nVal.argv = argValue;
2887     IMAGE_LOGD("SetName IN");
2888     if (!prepareNapiEnv(env, info, &nVal)) {
2889         return nVal.result;
2890     }
2891     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2892     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
2893     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to arg info"));
2894     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
2895         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
2896         "Invalid args count"),
2897         IMAGE_LOGE("Invalid args count %{public}zu", argCount));
2898     std::string pixelMapName = GetStringArgument(env, argValue[0]);
2899 
2900     PixelMapNapi* pixelMapNapi = nullptr;
2901     napiStatus = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
2902 
2903     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
2904 
2905     // corssed threads error
2906     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2907         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . setname failed",
2908         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "SetNameError",
2909         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2910         nVal.result);
2911 
2912     if (pixelMapNapi->nativePixelMap_ != nullptr) {
2913         uint32_t ret = pixelMapNapi->nativePixelMap_->SetMemoryName(pixelMapName);
2914         if (ret == SUCCESS) {
2915             return result;
2916         } else if (ret == ERR_MEMORY_NOT_SUPPORT) {
2917             ImageNapiUtils::ThrowExceptionError(env, ERR_MEMORY_NOT_SUPPORT, "fail set name");
2918         } else if (ret == COMMON_ERR_INVALID_PARAMETER) {
2919             ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "name size out of range");
2920         }
2921     } else {
2922         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, "Invalid nativePixelMap");
2923         IMAGE_LOGE("Null native pixemap object");
2924     }
2925     return result;
2926 #endif
2927 }
2928 
TranslateExec(napi_env env,PixelMapAsyncContext * context)2929 static void TranslateExec(napi_env env, PixelMapAsyncContext* context)
2930 {
2931     if (context == nullptr) {
2932         IMAGE_LOGE("Null context");
2933         return;
2934     }
2935     if (context->status == SUCCESS) {
2936         if (context->rPixelMap != nullptr) {
2937             context->rPixelMap->translate(static_cast<float>(context->xArg), static_cast<float>(context->yArg));
2938             context->status = SUCCESS;
2939         } else {
2940             IMAGE_LOGE("Null native ref");
2941             context->status = ERR_IMAGE_INIT_ABNORMAL;
2942         }
2943     } else {
2944         IMAGE_LOGD("Translate has failed. do nothing");
2945     }
2946 }
2947 
Translate(napi_env env,napi_callback_info info)2948 napi_value PixelMapNapi::Translate(napi_env env, napi_callback_info info)
2949 {
2950     NapiValues nVal;
2951     nVal.argc = NUM_3;
2952     napi_value argValue[NUM_3] = {0};
2953     nVal.argv = argValue;
2954     IMAGE_LOGD("Translate IN");
2955     if (!prepareNapiEnv(env, info, &nVal)) {
2956         return nVal.result;
2957     }
2958     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2959 
2960     if (nVal.argc != NUM_2 && nVal.argc != NUM_3) {
2961         IMAGE_LOGE("Invalid args count");
2962         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2963     } else {
2964         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->xArg))) {
2965             IMAGE_LOGE("Arg 0 type mismatch");
2966             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2967         }
2968         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_1], &(nVal.context->yArg))) {
2969             IMAGE_LOGE("Arg 1 type mismatch");
2970             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2971         }
2972     }
2973     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2974         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2975     }
2976 
2977     if (nVal.context->callbackRef == nullptr) {
2978         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2979     }
2980     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2981         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Translate failed",
2982         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "TranslateGeneralError",
2983         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2984         nVal.result);
2985     napi_value _resource = nullptr;
2986     napi_create_string_utf8(env, "Translate", NAPI_AUTO_LENGTH, &_resource);
2987     nVal.status = napi_create_async_work(env, nullptr, _resource,
2988         [](napi_env env, void *data) {
2989             auto context = static_cast<PixelMapAsyncContext*>(data);
2990             TranslateExec(env, context);
2991         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2992 
2993     if (nVal.status == napi_ok) {
2994         nVal.status = napi_queue_async_work(env, nVal.context->work);
2995         if (nVal.status == napi_ok) {
2996             nVal.context.release();
2997         }
2998     }
2999     return nVal.result;
3000 }
3001 
TranslateSync(napi_env env,napi_callback_info info)3002 napi_value PixelMapNapi::TranslateSync(napi_env env, napi_callback_info info)
3003 {
3004     napi_value result = nullptr;
3005     napi_get_undefined(env, &result);
3006     napi_status napiStatus;
3007     uint32_t status = SUCCESS;
3008     napi_value thisVar = nullptr;
3009     size_t argCount = NUM_2;
3010     napi_value argValue[NUM_2] = {0};
3011     double x = 0;
3012     double y = 0;
3013 
3014     IMAGE_LOGD("TranslateSync IN");
3015     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
3016     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
3017     IMG_NAPI_CHECK_RET_D(argCount == NUM_2,
3018         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
3019         "TranslateSync failed"),
3020         IMAGE_LOGE("TranslateSync failed, invalid parameter"));
3021 
3022     if (napi_ok != napi_get_value_double(env, argValue[NUM_0], &x) ||
3023         napi_ok != napi_get_value_double(env, argValue[NUM_1], &y)) {
3024         IMAGE_LOGE("get arraybuffer info failed");
3025         return result;
3026     }
3027 
3028     PixelMapNapi* pixelMapNapi = nullptr;
3029     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
3030 
3031     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
3032     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
3033         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
3034         "Pixelmap has crossed threads . TranslateSync failed"),
3035         IMAGE_LOGE("Pixelmap has crossed threads . TranslateSync failed"));
3036 
3037     if (pixelMapNapi->nativePixelMap_ != nullptr) {
3038         pixelMapNapi->nativePixelMap_->translate(static_cast<float>(x), static_cast<float>(y));
3039     } else {
3040         IMAGE_LOGE("Null native ref");
3041     }
3042     return result;
3043 }
3044 
RotateExec(napi_env env,PixelMapAsyncContext * context)3045 static void RotateExec(napi_env env, PixelMapAsyncContext* context)
3046 {
3047     if (context == nullptr) {
3048         IMAGE_LOGE("Null context");
3049         return;
3050     }
3051     if (context->status == SUCCESS) {
3052         if (context->rPixelMap != nullptr) {
3053             context->rPixelMap->rotate(context->xArg);
3054             context->status = SUCCESS;
3055         } else {
3056             IMAGE_LOGE("Null native ref");
3057             context->status = ERR_IMAGE_INIT_ABNORMAL;
3058         }
3059     } else {
3060         IMAGE_LOGD("Rotate has failed. do nothing");
3061     }
3062 }
3063 
Rotate(napi_env env,napi_callback_info info)3064 napi_value PixelMapNapi::Rotate(napi_env env, napi_callback_info info)
3065 {
3066     NapiValues nVal;
3067     nVal.argc = NUM_2;
3068     napi_value argValue[NUM_2] = {0};
3069     nVal.argv = argValue;
3070     IMAGE_LOGD("Rotate IN");
3071     if (!prepareNapiEnv(env, info, &nVal)) {
3072         return nVal.result;
3073     }
3074     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
3075 
3076     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
3077         IMAGE_LOGE("Invalid args count");
3078         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
3079     } else {
3080         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->xArg))) {
3081             IMAGE_LOGE("Arg 0 type mismatch");
3082             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
3083         }
3084     }
3085     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
3086         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
3087     }
3088 
3089     if (nVal.context->callbackRef == nullptr) {
3090         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
3091     }
3092     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
3093         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Rotate failed",
3094         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "RotateGeneralError",
3095         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
3096         nVal.result);
3097     napi_value _resource = nullptr;
3098     napi_create_string_utf8(env, "Rotate", NAPI_AUTO_LENGTH, &_resource);
3099     nVal.status = napi_create_async_work(env, nullptr, _resource,
3100         [](napi_env env, void *data) {
3101             auto context = static_cast<PixelMapAsyncContext*>(data);
3102             RotateExec(env, context);
3103         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
3104 
3105     if (nVal.status == napi_ok) {
3106         nVal.status = napi_queue_async_work(env, nVal.context->work);
3107         if (nVal.status == napi_ok) {
3108             nVal.context.release();
3109         }
3110     }
3111     return nVal.result;
3112 }
3113 
RotateSync(napi_env env,napi_callback_info info)3114 napi_value PixelMapNapi::RotateSync(napi_env env, napi_callback_info info)
3115 {
3116     napi_value result = nullptr;
3117     napi_get_undefined(env, &result);
3118     napi_status napiStatus;
3119     uint32_t status = SUCCESS;
3120     napi_value thisVar = nullptr;
3121     size_t argCount = NUM_1;
3122     napi_value argValue[NUM_1] = {0};
3123     double angle = 0;
3124 
3125     IMAGE_LOGD("RotateSync IN");
3126     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
3127     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
3128     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
3129         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
3130         "RotateSync failed"),
3131         IMAGE_LOGE("RotateSync failed, invalid parameter"));
3132     napiStatus = napi_get_value_double(env, argValue[NUM_0], &angle);
3133     IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed"));
3134 
3135     PixelMapNapi* pixelMapNapi = nullptr;
3136     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
3137 
3138     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
3139     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
3140         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
3141         "Pixelmap has crossed threads . RotateSync failed"),
3142         IMAGE_LOGE("Pixelmap has crossed threads . RotateSync failed"));
3143 
3144     if (pixelMapNapi->nativePixelMap_ != nullptr) {
3145         pixelMapNapi->nativePixelMap_->rotate(static_cast<float>(angle));
3146     } else {
3147         IMAGE_LOGE("Null native ref");
3148     }
3149     return result;
3150 }
FlipExec(napi_env env,PixelMapAsyncContext * context)3151 static void FlipExec(napi_env env, PixelMapAsyncContext* context)
3152 {
3153     if (context == nullptr) {
3154         IMAGE_LOGE("Null context");
3155         return;
3156     }
3157     if (context->status == SUCCESS) {
3158         if (context->rPixelMap != nullptr) {
3159             context->rPixelMap->flip(context->xBarg, context->yBarg);
3160             context->status = SUCCESS;
3161         } else {
3162             IMAGE_LOGE("Null native ref");
3163             context->status = ERR_IMAGE_INIT_ABNORMAL;
3164         }
3165     } else {
3166         IMAGE_LOGD("Flip has failed. do nothing");
3167     }
3168 }
3169 
Flip(napi_env env,napi_callback_info info)3170 napi_value PixelMapNapi::Flip(napi_env env, napi_callback_info info)
3171 {
3172     NapiValues nVal;
3173     nVal.argc = NUM_3;
3174     napi_value argValue[NUM_3] = {0};
3175     nVal.argv = argValue;
3176     IMAGE_LOGD("Flip IN");
3177     if (!prepareNapiEnv(env, info, &nVal)) {
3178         return nVal.result;
3179     }
3180     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
3181 
3182     if (nVal.argc != NUM_2 && nVal.argc != NUM_3) {
3183         IMAGE_LOGE("Invalid args count");
3184         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
3185     } else {
3186         if (napi_ok != napi_get_value_bool(env, nVal.argv[NUM_0], &(nVal.context->xBarg))) {
3187             IMAGE_LOGE("Arg 0 type mismatch");
3188             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
3189         }
3190         if (napi_ok != napi_get_value_bool(env, nVal.argv[NUM_1], &(nVal.context->yBarg))) {
3191             IMAGE_LOGE("Arg 1 type mismatch");
3192             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
3193         }
3194     }
3195     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
3196         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
3197     }
3198 
3199     if (nVal.context->callbackRef == nullptr) {
3200         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
3201     }
3202     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
3203         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Flip failed",
3204         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "FlipGeneralError",
3205         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
3206         nVal.result);
3207     napi_value _resource = nullptr;
3208     napi_create_string_utf8(env, "Flip", NAPI_AUTO_LENGTH, &_resource);
3209     nVal.status = napi_create_async_work(env, nullptr, _resource,
3210         [](napi_env env, void *data) {
3211             auto context = static_cast<PixelMapAsyncContext*>(data);
3212             FlipExec(env, context);
3213         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
3214 
3215     if (nVal.status == napi_ok) {
3216         nVal.status = napi_queue_async_work(env, nVal.context->work);
3217         if (nVal.status == napi_ok) {
3218             nVal.context.release();
3219         }
3220     }
3221     return nVal.result;
3222 }
3223 
FlipSync(napi_env env,napi_callback_info info)3224 napi_value PixelMapNapi::FlipSync(napi_env env, napi_callback_info info)
3225 {
3226     napi_value result = nullptr;
3227     napi_get_undefined(env, &result);
3228     napi_status napiStatus;
3229     uint32_t status = SUCCESS;
3230     napi_value thisVar = nullptr;
3231     size_t argCount = NUM_2;
3232     napi_value argValue[NUM_2] = {0};
3233     bool xBarg = 0;
3234     bool yBarg = 0;
3235 
3236     IMAGE_LOGD("FlipSync IN");
3237     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
3238     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
3239     IMG_NAPI_CHECK_RET_D(argCount == NUM_2,
3240         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
3241         "FlipSync failed"),
3242         IMAGE_LOGE("FlipSync failed, invalid parameter"));
3243 
3244     if (napi_ok != napi_get_value_bool(env, argValue[NUM_0], &xBarg)) {
3245         IMAGE_LOGE("Arg 0 type mismatch");
3246         status = COMMON_ERR_INVALID_PARAMETER;
3247     }
3248     if (napi_ok != napi_get_value_bool(env, argValue[NUM_1], &yBarg)) {
3249         IMAGE_LOGE("Arg 1 type mismatch");
3250         status = COMMON_ERR_INVALID_PARAMETER;
3251     }
3252 
3253     IMG_NAPI_CHECK_RET_D(status == SUCCESS, result, IMAGE_LOGE("FlipSync failed, invalid parameter"));
3254 
3255     PixelMapNapi* pixelMapNapi = nullptr;
3256     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
3257 
3258     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
3259     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
3260         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
3261         "Pixelmap has crossed threads . FlipSync failed"),
3262         IMAGE_LOGE("Pixelmap has crossed threads . FlipSync failed"));
3263 
3264     if (pixelMapNapi->nativePixelMap_ != nullptr) {
3265         pixelMapNapi->nativePixelMap_->flip(xBarg, yBarg);
3266     } else {
3267         IMAGE_LOGE("Null native ref");
3268     }
3269     return result;
3270 }
3271 
CropExec(napi_env env,PixelMapAsyncContext * context)3272 static void CropExec(napi_env env, PixelMapAsyncContext* context)
3273 {
3274     if (context == nullptr) {
3275         IMAGE_LOGE("Null context");
3276         return;
3277     }
3278     if (context->status == SUCCESS) {
3279         if (context->rPixelMap != nullptr) {
3280             context->status = context->rPixelMap->crop(context->area.region);
3281         } else {
3282             IMAGE_LOGE("Null native ref");
3283             context->status = ERR_IMAGE_INIT_ABNORMAL;
3284         }
3285     } else {
3286         IMAGE_LOGD("Crop has failed. do nothing");
3287     }
3288 }
3289 
Crop(napi_env env,napi_callback_info info)3290 napi_value PixelMapNapi::Crop(napi_env env, napi_callback_info info)
3291 {
3292     NapiValues nVal;
3293     nVal.argc = NUM_2;
3294     napi_value argValue[NUM_2] = {0};
3295     nVal.argv = argValue;
3296     IMAGE_LOGD("Crop IN");
3297     if (!prepareNapiEnv(env, info, &nVal)) {
3298         return nVal.result;
3299     }
3300     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
3301 
3302     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
3303         IMAGE_LOGE("Invalid args count");
3304         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
3305     } else {
3306         if (!parseRegion(env, nVal.argv[NUM_0], &(nVal.context->area.region))) {
3307             IMAGE_LOGE("Region type mismatch");
3308             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
3309         }
3310     }
3311     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
3312         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
3313     }
3314 
3315     if (nVal.context->callbackRef == nullptr) {
3316         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
3317     }
3318     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
3319         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Crop failed",
3320         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "CropGeneralError",
3321         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
3322         nVal.result);
3323     napi_value _resource = nullptr;
3324     napi_create_string_utf8(env, "CropExec", NAPI_AUTO_LENGTH, &_resource);
3325     nVal.status = napi_create_async_work(env, nullptr, _resource,
3326         [](napi_env env, void *data) {
3327             auto context = static_cast<PixelMapAsyncContext*>(data);
3328             CropExec(env, context);
3329         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
3330 
3331     if (nVal.status == napi_ok) {
3332         nVal.status = napi_queue_async_work(env, nVal.context->work);
3333         if (nVal.status == napi_ok) {
3334             nVal.context.release();
3335         }
3336     }
3337     return nVal.result;
3338 }
3339 
CropSync(napi_env env,napi_callback_info info)3340 napi_value PixelMapNapi::CropSync(napi_env env, napi_callback_info info)
3341 {
3342     napi_value result = nullptr;
3343     napi_get_undefined(env, &result);
3344     napi_status napiStatus;
3345     uint32_t status = SUCCESS;
3346     napi_value thisVar = nullptr;
3347     size_t argCount = NUM_1;
3348     napi_value argValue[NUM_1] = {0};
3349     Rect region;
3350 
3351     IMAGE_LOGD("CropSync IN");
3352     IMG_JS_ARGS(env, info, napiStatus, argCount, argValue, thisVar);
3353     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to napi_get_cb_info"));
3354     IMG_NAPI_CHECK_RET_D(argCount == NUM_1,
3355         ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER,
3356         "CropSync failed"),
3357         IMAGE_LOGE("CropSync failed, invalid parameter"));
3358     if (!parseRegion(env, argValue[NUM_0], &region)) {
3359         IMAGE_LOGE("Region type mismatch");
3360         return result;
3361     }
3362 
3363     PixelMapNapi* pixelMapNapi = nullptr;
3364     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
3365 
3366     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
3367     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
3368         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
3369         "Pixelmap has crossed threads . CropSync failed"),
3370         IMAGE_LOGE("Pixelmap has crossed threads . CropSync failed"));
3371 
3372     if (pixelMapNapi->nativePixelMap_ != nullptr) {
3373         status = pixelMapNapi->nativePixelMap_->crop(region);
3374         if (status != SUCCESS) {
3375             IMAGE_LOGE("CropSync failed");
3376         }
3377     } else {
3378         IMAGE_LOGE("Null native ref");
3379     }
3380     return result;
3381 }
3382 
STATIC_COMPLETE_FUNC(ToSdr)3383 STATIC_COMPLETE_FUNC(ToSdr)
3384 {
3385     auto context = static_cast<PixelMapAsyncContext*>(data);
3386     if (context == nullptr) {
3387         IMAGE_LOGE("ToSdrComplete context is nullptr");
3388         return;
3389     }
3390     napi_value result[NUM_2] = {0};
3391     napi_value retVal;
3392     napi_value callback = nullptr;
3393     napi_get_undefined(env, &result[NUM_0]);
3394     napi_get_undefined(env, &result[NUM_1]);
3395 
3396     napi_handle_scope scope = nullptr;
3397     napi_open_handle_scope(env, &scope);
3398     if (scope == nullptr) {
3399         IMAGE_LOGE("ToSdrComplete scope is nullptr");
3400         return;
3401     }
3402     if (context->status == SUCCESS) {
3403         napi_value value = nullptr;
3404         napi_get_undefined(env, &value);
3405         result[NUM_1] = value;
3406     } else if (context->status == ERR_MEDIA_INVALID_OPERATION) {
3407         ImageNapiUtils::CreateErrorObj(env, result[NUM_0], context->status, "The pixelmap is not hdr.");
3408     } else if (context->status == IMAGE_RESULT_GET_SURFAC_FAILED) {
3409         ImageNapiUtils::CreateErrorObj(env, result[NUM_0], ERR_MEDIA_INVALID_OPERATION, "Alloc new memory failed.");
3410     } else if (context->status == ERR_RESOURCE_UNAVAILABLE) {
3411         ImageNapiUtils::CreateErrorObj(env, result[NUM_0], ERR_MEDIA_INVALID_OPERATION, "Pixelmap is not editable");
3412     } else {
3413         ImageNapiUtils::CreateErrorObj(env, result[NUM_0], ERR_MEDIA_INVALID_OPERATION, "Internal error.");
3414     }
3415     if (context->deferred) {
3416         if (context->status == SUCCESS) {
3417             napi_resolve_deferred(env, context->deferred, result[NUM_1]);
3418         } else {
3419             napi_reject_deferred(env, context->deferred, result[NUM_0]);
3420         }
3421     } else {
3422         napi_get_reference_value(env, context->callbackRef, &callback);
3423         napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
3424         napi_delete_reference(env, context->callbackRef);
3425     }
3426     napi_delete_async_work(env, context->work);
3427     napi_close_handle_scope(env, scope);
3428     delete context;
3429     context = nullptr;
3430 }
3431 
ToSdrExec(napi_env env,PixelMapAsyncContext * context)3432 static void ToSdrExec(napi_env env, PixelMapAsyncContext* context)
3433 {
3434     if (context == nullptr) {
3435         IMAGE_LOGE("ToSdrExec null context");
3436         return;
3437     }
3438     if (!context->nConstructor->GetPixelNapiEditable()) {
3439         IMAGE_LOGE("ToSdrExec pixelmap is not editable");
3440         context->status = ERR_RESOURCE_UNAVAILABLE;
3441         return;
3442     }
3443     if (context->status == SUCCESS) {
3444         if (context->rPixelMap != nullptr) {
3445             context->status = context->rPixelMap->ToSdr();
3446         } else {
3447             IMAGE_LOGE("ToSdrExec null native ref");
3448             context->status = ERR_IMAGE_INIT_ABNORMAL;
3449         }
3450     } else {
3451         IMAGE_LOGI("ToSdrExec has failed. Do nothing");
3452     }
3453 }
3454 
ToSdr(napi_env env,napi_callback_info info)3455 napi_value PixelMapNapi::ToSdr(napi_env env, napi_callback_info info)
3456 {
3457     NapiValues nVal;
3458     nVal.argc = NUM_1;
3459     napi_value argValue[NUM_1] = {0};
3460     nVal.argv = argValue;
3461     if (!prepareNapiEnv(env, info, &nVal)) {
3462         IMAGE_LOGI("ToSdr prepare napi env failed");
3463         return nVal.result;
3464     }
3465     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
3466     napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
3467     napi_value _resource = nullptr;
3468     napi_create_string_utf8(env, "ToSdrExec", NAPI_AUTO_LENGTH, &_resource);
3469     nVal.status = napi_create_async_work(env, nullptr, _resource,
3470         [](napi_env env, void* data) {
3471             auto context = static_cast<PixelMapAsyncContext*>(data);
3472             ToSdrExec(env, context);
3473         }, ToSdrComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
3474 
3475     if (nVal.status == napi_ok) {
3476         nVal.status = napi_queue_async_work(env, nVal.context->work);
3477         if (nVal.status == napi_ok) {
3478             nVal.context.release();
3479         }
3480     }
3481     return nVal.result;
3482 }
3483 
GetColorSpace(napi_env env,napi_callback_info info)3484 napi_value PixelMapNapi::GetColorSpace(napi_env env, napi_callback_info info)
3485 {
3486     NapiValues nVal;
3487     nVal.argc = NUM_0;
3488     IMAGE_LOGD("GetColorSpace IN");
3489     napi_get_undefined(env, &nVal.result);
3490     if (!prepareNapiEnv(env, info, &nVal)) {
3491         return ImageNapiUtils::ThrowExceptionError(
3492             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to unwrap context");
3493     }
3494     if (nVal.argc != NUM_0) {
3495         return ImageNapiUtils::ThrowExceptionError(
3496             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid args count");
3497     }
3498     IMG_NAPI_CHECK_RET_D(nVal.context->nConstructor->GetPixelNapiEditable(),
3499         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
3500         "Pixelmap has crossed threads . GetColorSpace failed"),
3501         IMAGE_LOGE("Pixelmap has crossed threads . GetColorSpace failed"));
3502 #ifdef IMAGE_COLORSPACE_FLAG
3503     if (nVal.context->nConstructor->nativePixelMap_ == nullptr) {
3504         return ImageNapiUtils::ThrowExceptionError(
3505             env, ERR_IMAGE_DATA_ABNORMAL, "Invalid native pixelmap");
3506     }
3507     auto grCS = nVal.context->nConstructor->nativePixelMap_->InnerGetGrColorSpacePtr();
3508     if (grCS == nullptr) {
3509         return ImageNapiUtils::ThrowExceptionError(
3510             env, ERR_IMAGE_DATA_UNSUPPORT, "No colorspace in pixelmap");
3511     }
3512     auto resultValue = ColorManager::CreateJsColorSpaceObject(env, grCS);
3513     nVal.result = reinterpret_cast<napi_value>(resultValue);
3514 #else
3515     return ImageNapiUtils::ThrowExceptionError(
3516         env, ERR_INVALID_OPERATION, "Unsupported operation");
3517 #endif
3518     return nVal.result;
3519 }
3520 
SetColorSpace(napi_env env,napi_callback_info info)3521 napi_value PixelMapNapi::SetColorSpace(napi_env env, napi_callback_info info)
3522 {
3523     NapiValues nVal;
3524     nVal.argc = NUM_1;
3525     napi_value argValue[NUM_1] = {0};
3526     nVal.argv = argValue;
3527     IMAGE_LOGD("SetColorSpace IN");
3528     napi_get_undefined(env, &nVal.result);
3529     if (!prepareNapiEnv(env, info, &nVal)) {
3530         return ImageNapiUtils::ThrowExceptionError(
3531             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to unwrap context");
3532     }
3533     if (nVal.argc != NUM_1) {
3534         return ImageNapiUtils::ThrowExceptionError(
3535             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid args count");
3536     }
3537     IMG_NAPI_CHECK_RET_D(nVal.context->nConstructor->GetPixelNapiEditable(),
3538         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
3539         "Pixelmap has crossed threads . SetColorSpace failed"),
3540         IMAGE_LOGE("Pixelmap has crossed threads . SetColorSpace failed"));
3541 #ifdef IMAGE_COLORSPACE_FLAG
3542     nVal.context->colorSpace = ColorManager::GetColorSpaceByJSObject(env, nVal.argv[NUM_0]);
3543     if (nVal.context->colorSpace == nullptr) {
3544         return ImageNapiUtils::ThrowExceptionError(
3545             env, ERR_IMAGE_INVALID_PARAMETER, "ColorSpace mismatch");
3546     }
3547     nVal.context->nConstructor->nativePixelMap_->InnerSetColorSpace(*(nVal.context->colorSpace));
3548 #else
3549     return ImageNapiUtils::ThrowExceptionError(
3550         env, ERR_INVALID_OPERATION, "Unsupported operation");
3551 #endif
3552     return nVal.result;
3553 }
3554 
Marshalling(napi_env env,napi_callback_info info)3555 napi_value PixelMapNapi::Marshalling(napi_env env, napi_callback_info info)
3556 {
3557 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
3558     NapiValues nVal;
3559     nVal.argc = NUM_1;
3560     napi_value argValue[NUM_1] = {0};
3561     nVal.argv = argValue;
3562     IMAGE_LOGD("Marshalling IN");
3563 
3564     if (!prepareNapiEnv(env, info, &nVal)) {
3565         return ImageNapiUtils::ThrowExceptionError(
3566             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to unwrap context");
3567     }
3568     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
3569     if (nVal.context->rPixelMap == nullptr) {
3570         return ImageNapiUtils::ThrowExceptionError(env, ERR_IPC, "marshalling pixel map to parcel failed.");
3571     }
3572     if (nVal.argc != NUM_0 && nVal.argc != NUM_1) {
3573         return ImageNapiUtils::ThrowExceptionError(
3574             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid args count");
3575     }
3576     NAPI_MessageSequence *napiSequence = nullptr;
3577     napi_get_cb_info(env, info, &nVal.argc, nVal.argv, nullptr, nullptr);
3578     napi_unwrap(env, nVal.argv[0], reinterpret_cast<void**>(&napiSequence));
3579     auto messageParcel = napiSequence->GetMessageParcel();
3580     if (messageParcel == nullptr) {
3581         return ImageNapiUtils::ThrowExceptionError(
3582             env, ERR_IPC, "marshalling pixel map to parcel failed.");
3583     }
3584     bool st = nVal.context->rPixelMap->Marshalling(*messageParcel);
3585     if (!st) {
3586         return ImageNapiUtils::ThrowExceptionError(
3587             env, ERR_IPC, "marshalling pixel map to parcel failed.");
3588     }
3589     return nVal.result;
3590 #else
3591     napi_value result = nullptr;
3592     return result;
3593 #endif
3594 }
3595 
ApplyColorSpaceExec(napi_env env,PixelMapAsyncContext * context)3596 static void ApplyColorSpaceExec(napi_env env, PixelMapAsyncContext* context)
3597 {
3598     if (context == nullptr) {
3599         IMAGE_LOGE("Null context");
3600         return;
3601     }
3602     if (context->status != SUCCESS) {
3603         IMAGE_LOGD("ApplyColorSpace has failed. do nothing");
3604         return;
3605     }
3606     if (context->rPixelMap == nullptr || context->colorSpace == nullptr) {
3607         context->status = ERR_IMAGE_INIT_ABNORMAL;
3608         IMAGE_LOGE("ApplyColorSpace Null native ref");
3609         return;
3610     }
3611     context->status = context->rPixelMap->ApplyColorSpace(*(context->colorSpace));
3612 }
3613 
ParseColorSpaceVal(napi_env env,napi_value val,PixelMapAsyncContext * context)3614 static void ParseColorSpaceVal(napi_env env, napi_value val, PixelMapAsyncContext* context)
3615 {
3616     if (context == nullptr) {
3617         IMAGE_LOGE("Null context");
3618         return;
3619     }
3620 
3621 #ifdef IMAGE_COLORSPACE_FLAG
3622     context->colorSpace = ColorManager::GetColorSpaceByJSObject(env, val);
3623     if (context->colorSpace == nullptr) {
3624         context->status = ERR_IMAGE_INVALID_PARAMETER;
3625     }
3626 #else
3627     Val.context->status = ERR_IMAGE_DATA_UNSUPPORT;
3628 #endif
3629 }
3630 
ApplyColorSpace(napi_env env,napi_callback_info info)3631 napi_value PixelMapNapi::ApplyColorSpace(napi_env env, napi_callback_info info)
3632 {
3633     NapiValues nVal;
3634     nVal.argc = NUM_2;
3635     napi_value argValue[NUM_2] = {0};
3636     nVal.argv = argValue;
3637     IMAGE_LOGD("ApplyColorSpace IN");
3638     if (!prepareNapiEnv(env, info, &nVal)) {
3639         return nVal.result;
3640     }
3641     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
3642 
3643     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
3644         IMAGE_LOGE("Invalid args count");
3645         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
3646     } else {
3647         ParseColorSpaceVal(env, nVal.argv[NUM_0], nVal.context.get());
3648     }
3649     if (nVal.argc >= NUM_1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
3650         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
3651     }
3652 
3653     if (nVal.context->callbackRef == nullptr) {
3654         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
3655     }
3656     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
3657         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . ApplyColorSpace failed",
3658         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "ApplyColorSpaceGeneralError",
3659         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
3660         nVal.result);
3661     napi_value _resource = nullptr;
3662     napi_create_string_utf8(env, "ApplyColorSpace", NAPI_AUTO_LENGTH, &_resource);
3663     nVal.status = napi_create_async_work(env, nullptr, _resource, [](napi_env env, void *data) {
3664             auto context = static_cast<PixelMapAsyncContext*>(data);
3665             ApplyColorSpaceExec(env, context);
3666         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
3667 
3668     if (nVal.status == napi_ok) {
3669         nVal.status = napi_queue_async_work(env, nVal.context->work);
3670         if (nVal.status == napi_ok) {
3671             nVal.context.release();
3672         }
3673     }
3674     return nVal.result;
3675 }
3676 
IsMatchFormatType(FormatType type,PixelFormat format)3677 static bool IsMatchFormatType(FormatType type, PixelFormat format)
3678 {
3679     if (type == FormatType::YUV) {
3680         switch (format) {
3681             case PixelFormat::NV21:
3682             case PixelFormat::NV12:
3683             case PixelFormat::YCBCR_P010:
3684             case PixelFormat::YCRCB_P010:{
3685                 return true;
3686             }
3687             default:{
3688                 return false;
3689             }
3690         }
3691     } else if (type == FormatType::RGB) {
3692         switch (format) {
3693             case PixelFormat::ARGB_8888:
3694             case PixelFormat::RGB_565:
3695             case PixelFormat::RGBA_8888:
3696             case PixelFormat::BGRA_8888:
3697             case PixelFormat::RGB_888:
3698             case PixelFormat::RGBA_F16:
3699             case PixelFormat::RGBA_1010102:{
3700                 return true;
3701             }
3702             default:{
3703                 return false;
3704             }
3705         }
3706     } else {
3707         return false;
3708     }
3709 }
3710 
STATIC_EXEC_FUNC(GeneralError)3711 STATIC_EXEC_FUNC(GeneralError)
3712 {
3713     if (data == nullptr) {
3714         IMAGE_LOGE("GeneralErrorExec invalid parameter: data is null");
3715         return;
3716     }
3717     auto context = static_cast<PixelMapAsyncContext*>(data);
3718     context->status = IMAGE_RESULT_CREATE_FORMAT_CONVERT_FAILED;
3719 }
3720 
TypeFormat(PixelFormat & pixelForamt)3721 static FormatType TypeFormat(PixelFormat &pixelForamt)
3722 {
3723     switch (pixelForamt) {
3724         case PixelFormat::ARGB_8888:
3725         case PixelFormat::RGB_565:
3726         case PixelFormat::RGBA_8888:
3727         case PixelFormat::BGRA_8888:
3728         case PixelFormat::RGB_888:
3729         case PixelFormat::RGBA_F16:
3730         case PixelFormat::RGBA_1010102:{
3731             return FormatType::RGB;
3732         }
3733         case PixelFormat::NV21:
3734         case PixelFormat::NV12:
3735         case PixelFormat::YCBCR_P010:
3736         case PixelFormat::YCRCB_P010:{
3737             return FormatType::YUV;
3738         }
3739         default:
3740             return FormatType::UNKNOWN;
3741     }
3742 }
3743 
GetNativePixelMapInfo(napi_env & env,PixelMapAsyncContext * context)3744 static uint32_t GetNativePixelMapInfo(napi_env &env, PixelMapAsyncContext* context)
3745 {
3746     if (context == nullptr) {
3747         IMAGE_LOGE("GetNativePixelMapInfo invalid parameter: context is null");
3748         return ERROR;
3749     }
3750 
3751     PixelFormat destPixelFormat = context->destFormat;
3752     std::shared_ptr<PixelMap> pixelMap = nullptr;
3753     IMG_NAPI_CHECK_BUILD_ERROR(IsMatchFormatType(context->dstFormatType, destPixelFormat),
3754         BuildContextError(env, context->error, "dest format is wrong!", ERR_IMAGE_INVALID_PARAMETER),
3755         context->status = ERR_IMAGE_INVALID_PARAMETER, ERR_IMAGE_INVALID_PARAMETER);
3756     IMG_NAPI_CHECK_BUILD_ERROR(IsMatchFormatType(context->srcFormatType, context->rPixelMap->GetPixelFormat()),
3757         BuildContextError(env, context->error, "source format is wrong!", ERR_IMAGE_INVALID_PARAMETER),
3758         context->status = ERR_IMAGE_INVALID_PARAMETER, ERR_IMAGE_INVALID_PARAMETER);
3759     return SUCCESS;
3760 }
3761 
GetNativeConvertInfo(napi_env & env,napi_callback_info & info,PixelMapAsyncContext * context)3762 static uint32_t GetNativeConvertInfo(napi_env &env, napi_callback_info &info, PixelMapAsyncContext* context)
3763 {
3764     if (context == nullptr) {
3765         IMAGE_LOGE("GetNativeConvertInfo invalid parameter: context is null");
3766         return ERROR;
3767     }
3768 
3769     napi_status status = napi_invalid_arg;
3770     napi_value thisVar = nullptr;
3771     size_t argc = NUM_1;
3772     napi_value argv[NUM_1] = {nullptr};
3773     IMG_JS_ARGS(env, info, status, argc, argv, thisVar);
3774     IMG_NAPI_CHECK_BUILD_ERROR(IMG_IS_OK(status),
3775         BuildContextError(env, context->error, "fail to napi_get_cb_info", ERROR), context->status = ERROR, ERROR);
3776     IMG_NAPI_CHECK_BUILD_ERROR(argc == NUM_1,
3777         BuildContextError(env, context->error, "incorrect number of parametersarguments!", ERR_IMAGE_INVALID_PARAMETER),
3778         context->status = ERR_IMAGE_INVALID_PARAMETER, ERR_IMAGE_INVALID_PARAMETER);
3779     napi_value constructor = nullptr;
3780     napi_value global = nullptr;
3781     napi_get_global(env, &global);
3782     status = napi_get_named_property(env, global, "PixelFormat", &constructor);
3783     IMG_NAPI_CHECK_BUILD_ERROR(IMG_IS_OK(status),
3784         BuildContextError(env, context->error, "Get PixelMapNapi property failed!", ERR_IMAGE_PROPERTY_NOT_EXIST),
3785         context->status = ERR_IMAGE_PROPERTY_NOT_EXIST, ERR_IMAGE_PROPERTY_NOT_EXIST);
3786 
3787     bool isPixelFormat = false;
3788     if (context->destFormat == PixelFormat::UNKNOWN) {
3789         isPixelFormat = false;
3790     } else {
3791         isPixelFormat = true;
3792     }
3793 
3794     if (isPixelFormat) {
3795         return GetNativePixelMapInfo(env, context);
3796     }
3797     IMG_NAPI_CHECK_BUILD_ERROR(false,
3798         BuildContextError(env, context->error, "wrong arguments!", ERR_IMAGE_INVALID_PARAMETER),
3799         context->status = ERR_IMAGE_INVALID_PARAMETER, ERR_IMAGE_INVALID_PARAMETER);
3800 }
3801 
Convert(napi_env & env,napi_callback_info & info,FormatType srcFormatType,std::string workName,PixelMapAsyncContext * context)3802 static napi_value Convert(napi_env &env, napi_callback_info &info, FormatType srcFormatType, std::string workName,
3803     PixelMapAsyncContext* context)
3804 {
3805     napi_value result = nullptr;
3806     napi_get_undefined(env, &result);
3807     napi_status status;
3808     if (context == nullptr) {
3809         return nullptr;
3810     }
3811     context->status = SUCCESS;
3812     context->srcFormatType = srcFormatType;
3813     uint32_t ret = GetNativeConvertInfo(env, info, context);
3814     napi_create_promise(env, &(context->deferred), &result);
3815     PixelMapAsyncContextPtr asyncContext = std::make_unique<PixelMapAsyncContext>(*context);
3816     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->error == nullptr,
3817         asyncContext->status = IMAGE_RESULT_CREATE_FORMAT_CONVERT_FAILED,
3818         IMG_CREATE_CREATE_ASYNC_WORK(env, status, (workName + "GeneralError").c_str(),
3819         GeneralErrorExec, GeneralErrorComplete, asyncContext, asyncContext->work),
3820         result);
3821 
3822     IMG_NAPI_CHECK_BUILD_ERROR(ret == SUCCESS,
3823         BuildContextError(env, asyncContext->error, "get native convert info failed!", ret),
3824         IMG_CREATE_CREATE_ASYNC_WORK(env, status, (workName + "GeneralError").c_str(),
3825         GeneralErrorExec, GeneralErrorComplete, asyncContext, asyncContext->work),
3826         result);
3827 
3828     context->status = ImageFormatConvert::ConvertImageFormat(context->rPixelMap, context->destFormat);
3829     if (context->status == SUCCESS) {
3830         result = PixelMapNapi::CreatePixelMap(env, context->rPixelMap);
3831         return result;
3832     }
3833     return result;
3834 }
3835 
YUVToRGB(napi_env env,napi_callback_info & info,PixelMapAsyncContext * context)3836 static napi_value YUVToRGB(napi_env env, napi_callback_info &info, PixelMapAsyncContext* context)
3837 {
3838     return Convert(env, info, FormatType::YUV, "YUVToRGB", context);
3839 }
3840 
RGBToYUV(napi_env env,napi_callback_info & info,PixelMapAsyncContext * context)3841 static napi_value RGBToYUV(napi_env env, napi_callback_info &info,  PixelMapAsyncContext* context)
3842 {
3843     return Convert(env, info, FormatType::RGB, "RGBToYUV", context);
3844 }
3845 
PixelFormatConvert(napi_env env,napi_callback_info & info,PixelMapAsyncContext * context)3846 static napi_value PixelFormatConvert(napi_env env, napi_callback_info &info, PixelMapAsyncContext* context)
3847 {
3848     if (context == nullptr) {
3849         IMAGE_LOGE("PixelFormatConvert invalid parameter: context is null");
3850         return nullptr;
3851     }
3852 
3853     napi_value result = nullptr;
3854     napi_create_promise(env, &(context->deferred), &result);
3855     PixelFormat dstFormat = context->destFormat;
3856 
3857     if (dstFormat != PixelFormat::UNKNOWN) {
3858         context->dstFormatType = TypeFormat(dstFormat);
3859         if (context->dstFormatType == FormatType::YUV &&
3860             (context->srcFormatType == FormatType::UNKNOWN || context->srcFormatType == FormatType::RGB)) {
3861             result = RGBToYUV(env, info, context);
3862         } else if ((context->dstFormatType == FormatType::RGB) &&
3863             (context->srcFormatType == FormatType::UNKNOWN || context->srcFormatType == FormatType::YUV)) {
3864             result = YUVToRGB(env, info, context);
3865         }
3866     }
3867     return result;
3868 }
3869 
ConvertPixelMapFormat(napi_env env,napi_callback_info info)3870 napi_value PixelMapNapi::ConvertPixelMapFormat(napi_env env, napi_callback_info info)
3871 {
3872     NapiValues nVal;
3873     napi_value argValue[NUM_2];
3874     size_t argc = NUM_2;
3875     nVal.argc = argc;
3876     nVal.argv = argValue;
3877 
3878     if (!prepareNapiEnv(env, info, &nVal)) {
3879         return nVal.result;
3880     }
3881     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
3882     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
3883         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
3884     }
3885 
3886     if (!nVal.context) {
3887         return nullptr;
3888     }
3889     napi_get_undefined(env, &nVal.result);
3890     if (nVal.argc != NUM_1) {
3891         IMAGE_LOGE("Invalid args count");
3892         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
3893     }
3894 
3895     if (nVal.context->callbackRef == nullptr) {
3896         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
3897     } else {
3898         napi_get_undefined(env, &(nVal.result));
3899     }
3900 
3901     napi_value jsArg = nVal.argv[0];
3902     int32_t pixelFormatInt;
3903     napi_get_value_int32(env, jsArg, &pixelFormatInt);
3904     nVal.context->destFormat = static_cast<PixelFormat>(pixelFormatInt);
3905 
3906     if (TypeFormat(nVal.context->destFormat) == FormatType::UNKNOWN) {
3907         napi_value errCode = nullptr;
3908         napi_create_int32(env, ERR_IMAGE_INVALID_PARAMETER, &errCode);
3909         napi_reject_deferred(env, nVal.context->deferred, errCode);
3910         IMAGE_LOGE("dstFormat is not support or invalid");
3911         return nVal.result;
3912     }
3913 
3914     nVal.result = PixelFormatConvert(env, info, nVal.context.get());
3915     nVal.context->nConstructor->nativePixelMap_ = nVal.context->rPixelMap;
3916     if (nVal.result == nullptr) {
3917         return nVal.result;
3918     }
3919     return nVal.result;
3920 }
3921 
SetTransferDetached(napi_env env,napi_callback_info info)3922 napi_value PixelMapNapi::SetTransferDetached(napi_env env, napi_callback_info info)
3923 {
3924     NapiValues nVal;
3925     napi_value argValue[NUM_1];
3926     nVal.argc = NUM_1;
3927     nVal.argv = argValue;
3928     napi_status status = napi_invalid_arg;
3929     napi_get_undefined(env, &nVal.result);
3930     if (!prepareNapiEnv(env, info, &nVal)) {
3931         return ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, "Fail to unwrap context");
3932     }
3933     bool detach;
3934     status = napi_get_value_bool(env, nVal.argv[NUM_0], &detach);
3935     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
3936         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
3937         "SetTransferDetached get detach failed"),
3938         IMAGE_LOGE("SetTransferDetached get detach failed"));
3939     nVal.context->nConstructor->SetTransferDetach(detach);
3940     return nVal.result;
3941 }
3942 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
3943 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
3944 enum HdrMetadataKey : uint32_t {
3945     HDR_METADATA_TYPE = 0,
3946     HDR_STATIC_METADATA,
3947     HDR_DYNAMIC_METADATA,
3948     HDR_GAINMAP_METADATA,
3949 };
3950 
3951 enum HdrMetadataType : uint32_t {
3952     NONE = 0,
3953     BASE,
3954     GAINMAP,
3955     ALTERNATE,
3956     INVALID,
3957 };
3958 
3959 static std::map<HdrMetadataType, CM_HDR_Metadata_Type> EtsMetadataMap = {
3960     {NONE, CM_METADATA_NONE},
3961     {BASE, CM_IMAGE_HDR_VIVID_DUAL},
3962     {GAINMAP, CM_METADATA_NONE},
3963     {ALTERNATE, CM_IMAGE_HDR_VIVID_SINGLE},
3964 };
3965 
3966 static std::map<CM_HDR_Metadata_Type, HdrMetadataType> MetadataEtsMap = {
3967     {CM_METADATA_NONE, NONE},
3968     {CM_IMAGE_HDR_VIVID_DUAL, BASE},
3969     {CM_IMAGE_HDR_VIVID_SINGLE, ALTERNATE},
3970 };
3971 
FloatToDouble(float val)3972 static double FloatToDouble(float val)
3973 {
3974     const double precision = 1000000.0;
3975     val *= precision;
3976     double result = static_cast<double>(val / precision);
3977     return result;
3978 }
3979 
CreateArrayDouble(napi_env env,napi_value & root,float value,int index)3980 static bool CreateArrayDouble(napi_env env, napi_value &root, float value, int index)
3981 {
3982     napi_value node = nullptr;
3983     if (!CREATE_NAPI_DOUBLE(FloatToDouble(value), node)) {
3984         return false;
3985     }
3986     if (napi_set_element(env, root, index, node) != napi_ok) {
3987         return false;
3988     }
3989     return true;
3990 }
3991 
CreateJsNumber(napi_env env,double value)3992 inline napi_value CreateJsNumber(napi_env env, double value)
3993 {
3994     napi_value result = nullptr;
3995     napi_create_double(env, value, &result);
3996     return result;
3997 }
3998 
CreateNapiDouble(napi_env env,napi_value & root,float value,std::string name)3999 static bool CreateNapiDouble(napi_env env, napi_value &root, float value, std::string name)
4000 {
4001     napi_value node = CreateJsNumber(env, FloatToDouble(value));
4002     if (napi_set_named_property(env, root, name.c_str(), node) != napi_ok) {
4003         return false;
4004     }
4005     return true;
4006 }
4007 
CreateNapiUint32(napi_env env,napi_value & root,int32_t value,std::string name)4008 static bool CreateNapiUint32(napi_env env, napi_value &root, int32_t value, std::string name)
4009 {
4010     napi_value node = nullptr;
4011     if (!CREATE_NAPI_INT32(value, node)) {
4012         return false;
4013     }
4014 
4015     if (napi_set_named_property(env, root, name.c_str(), node) != napi_ok) {
4016         return false;
4017     }
4018     return true;
4019 }
4020 
CreateNapiBool(napi_env env,napi_value & root,bool value,std::string name)4021 static bool CreateNapiBool(napi_env env, napi_value &root, bool value, std::string name)
4022 {
4023     napi_value node = nullptr;
4024     if (napi_get_boolean(env, value, &node) != napi_ok) {
4025         return false;
4026     }
4027     if (napi_set_named_property(env, root, name.c_str(), node) != napi_ok) {
4028         return false;
4029     }
4030     return true;
4031 }
BuildStaticMetadataNapi(napi_env env,HDI::Display::Graphic::Common::V1_0::HdrStaticMetadata & staticMetadata)4032 static napi_value BuildStaticMetadataNapi(napi_env env,
4033     HDI::Display::Graphic::Common::V1_0::HdrStaticMetadata &staticMetadata)
4034 {
4035     napi_value metadataValue = nullptr;
4036     napi_create_object(env, &metadataValue);
4037     napi_value displayPrimariesX = nullptr;
4038     napi_create_array_with_length(env, NUM_3, &displayPrimariesX);
4039     bool status = true;
4040     status &= CreateArrayDouble(env, displayPrimariesX, staticMetadata.smpte2086.displayPrimaryRed.x, NUM_0);
4041     status &= CreateArrayDouble(env, displayPrimariesX, staticMetadata.smpte2086.displayPrimaryGreen.x, NUM_1);
4042     status &= CreateArrayDouble(env, displayPrimariesX, staticMetadata.smpte2086.displayPrimaryBlue.x, NUM_2);
4043     status &= napi_set_named_property(env, metadataValue, "displayPrimariesX", displayPrimariesX) == napi_ok;
4044     napi_value displayPrimariesY = nullptr;
4045     napi_create_array_with_length(env, NUM_3, &displayPrimariesY);
4046     status &= CreateArrayDouble(env, displayPrimariesY, staticMetadata.smpte2086.displayPrimaryRed.y, NUM_0);
4047     status &= CreateArrayDouble(env, displayPrimariesY, staticMetadata.smpte2086.displayPrimaryGreen.y, NUM_1);
4048     status &= CreateArrayDouble(env, displayPrimariesY, staticMetadata.smpte2086.displayPrimaryBlue.y, NUM_2);
4049     status &= napi_set_named_property(env, metadataValue, "displayPrimariesY", displayPrimariesY) == napi_ok;
4050     status &= CreateNapiDouble(env, metadataValue, staticMetadata.smpte2086.whitePoint.x, "whitePointX");
4051     status &= CreateNapiDouble(env, metadataValue, staticMetadata.smpte2086.whitePoint.y, "whitePointY");
4052     status &= CreateNapiDouble(env, metadataValue, staticMetadata.smpte2086.maxLuminance, "maxLuminance");
4053     status &= CreateNapiDouble(env, metadataValue, staticMetadata.smpte2086.minLuminance, "minLuminance");
4054     status &= CreateNapiDouble(env, metadataValue,
4055         staticMetadata.cta861.maxContentLightLevel, "maxContentLightLevel");
4056     status &= CreateNapiDouble(env, metadataValue,
4057         staticMetadata.cta861.maxFrameAverageLightLevel, "maxFrameAverageLightLevel");
4058     if (!status) {
4059         IMAGE_LOGD("BuildStaticMetadataNapi failed");
4060     }
4061     return metadataValue;
4062 }
4063 
BuildGainmapChannel(napi_env env,napi_value & root,HDRVividExtendMetadata & gainmapMetadata,int index)4064 static bool BuildGainmapChannel(napi_env env, napi_value &root, HDRVividExtendMetadata & gainmapMetadata, int index)
4065 {
4066     bool status = true;
4067     status &= CreateNapiDouble(env, root,
4068         gainmapMetadata.metaISO.enhanceClippedThreholdMaxGainmap[index], "gainmapMax");
4069     status &= CreateNapiDouble(env, root,
4070         gainmapMetadata.metaISO.enhanceClippedThreholdMinGainmap[index], "gainmapMin");
4071     status &= CreateNapiDouble(env, root,
4072         gainmapMetadata.metaISO.enhanceMappingGamma[index], "gamma");
4073     status &= CreateNapiDouble(env, root,
4074         gainmapMetadata.metaISO.enhanceMappingBaselineOffset[index], "baseOffset");
4075     status &= CreateNapiDouble(env, root,
4076         gainmapMetadata.metaISO.enhanceMappingAlternateOffset[index], "alternateOffset");
4077     return status;
4078 }
4079 
BuildDynamicMetadataNapi(napi_env env,HDRVividExtendMetadata & gainmapMetadata)4080 static napi_value BuildDynamicMetadataNapi(napi_env env, HDRVividExtendMetadata &gainmapMetadata)
4081 {
4082     napi_value metadataValue = nullptr;
4083     napi_create_object(env, &metadataValue);
4084     bool status = true;
4085     status &= CreateNapiUint32(env, metadataValue, static_cast<int32_t>(
4086         gainmapMetadata.metaISO.writeVersion), "writerVersion");
4087     status &= CreateNapiUint32(env, metadataValue, static_cast<int32_t>(
4088         gainmapMetadata.metaISO.miniVersion), "miniVersion");
4089     status &= CreateNapiUint32(env, metadataValue, static_cast<int32_t>(
4090         gainmapMetadata.metaISO.gainmapChannelNum), "gainmapChannelCount");
4091     status &= CreateNapiBool(env, metadataValue, static_cast<bool>(
4092         gainmapMetadata.metaISO.useBaseColorFlag), "useBaseColorFlag");
4093     status &= CreateNapiDouble(env, metadataValue, gainmapMetadata.metaISO.baseHeadroom, "baseHeadroom");
4094     status &= CreateNapiDouble(env, metadataValue, gainmapMetadata.metaISO.alternateHeadroom, "alternateHeadroom");
4095     napi_value array = nullptr;
4096     napi_create_object(env, &array);
4097     for (uint32_t i = 0; i < NUM_3; i++) {
4098         napi_value gainmapChannel = nullptr;
4099         napi_create_object(env, &gainmapChannel);
4100         status &= BuildGainmapChannel(env, gainmapChannel, gainmapMetadata, i);
4101         napi_set_element(env, array, i, gainmapChannel);
4102     }
4103     napi_set_named_property(env, metadataValue, "channels", array);
4104     if (!status) {
4105         IMAGE_LOGD("BuildDynamicMetadataNapi failed");
4106     }
4107     return metadataValue;
4108 }
4109 
GetStaticMetadata(napi_env env,OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer,napi_value & metadataValue)4110 static napi_status GetStaticMetadata(napi_env env, OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer,
4111     napi_value &metadataValue)
4112 {
4113     HDI::Display::Graphic::Common::V1_0::HdrStaticMetadata staticMetadata;
4114     uint32_t vecSize = sizeof(HDI::Display::Graphic::Common::V1_0::HdrStaticMetadata);
4115     std::vector<uint8_t> staticData;
4116     if (!VpeUtils::GetSbStaticMetadata(surfaceBuffer, staticData) ||
4117         (staticData.size() != vecSize)) {
4118         IMAGE_LOGE("GetSbStaticMetadata failed");
4119         return napi_invalid_arg;
4120     }
4121     if (memcpy_s(&staticMetadata, vecSize, staticData.data(), staticData.size()) != EOK) {
4122         return napi_invalid_arg;
4123     }
4124     metadataValue = BuildStaticMetadataNapi(env, staticMetadata);
4125     return napi_ok;
4126 }
4127 
GetDynamicMetadata(napi_env env,OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer,napi_value & metadataValue)4128 static napi_status GetDynamicMetadata(napi_env env,
4129     OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer, napi_value &metadataValue)
4130 {
4131     std::vector<uint8_t> dynamicData;
4132     if (VpeUtils::GetSbDynamicMetadata(surfaceBuffer, dynamicData) && (dynamicData.size() > 0)) {
4133         napi_value result = nullptr;
4134         napi_get_undefined(env, &result);
4135         ImageNapiUtils::CreateArrayBuffer(env, dynamicData.data(), dynamicData.size(), &result);
4136         metadataValue = result;
4137         if (metadataValue == nullptr) {
4138             return napi_invalid_arg;
4139         }
4140         return napi_ok;
4141     }
4142     IMAGE_LOGE("GetSbDynamicMetadata failed");
4143     return napi_invalid_arg;
4144 }
4145 
GetMetadataType(napi_env env,OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer,napi_value & metadataValue)4146 static napi_status GetMetadataType(napi_env env,
4147     OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer, napi_value &metadataValue)
4148 {
4149     CM_HDR_Metadata_Type type;
4150     VpeUtils::GetSbMetadataType(surfaceBuffer, type);
4151     if (MetadataEtsMap.find(type) != MetadataEtsMap.end()) {
4152         int32_t value = static_cast<int32_t>(MetadataEtsMap[type]);
4153         std::vector<uint8_t> gainmapData;
4154         if (type == CM_HDR_Metadata_Type::CM_METADATA_NONE &&
4155             VpeUtils::GetSbDynamicMetadata(surfaceBuffer, gainmapData) &&
4156             gainmapData.size() == sizeof(HDRVividExtendMetadata)) {
4157             value = static_cast<int32_t>(HdrMetadataType::GAINMAP);
4158         }
4159         if (!CREATE_NAPI_INT32(value, metadataValue)) {
4160             return napi_invalid_arg;
4161         }
4162         return napi_ok;
4163     }
4164     IMAGE_LOGE("GetMetadataType failed");
4165     return napi_invalid_arg;
4166 }
4167 
BuildHdrMetadataValue(napi_env env,napi_value argv[],std::shared_ptr<PixelMap> pixelMap,napi_value & metadataValue)4168 static napi_status BuildHdrMetadataValue(napi_env env, napi_value argv[],
4169     std::shared_ptr<PixelMap> pixelMap, napi_value &metadataValue)
4170 {
4171     uint32_t metadataKey = 0;
4172     napi_get_value_uint32(env, argv[NUM_0], &metadataKey);
4173     OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer(
4174         reinterpret_cast<OHOS::SurfaceBuffer*>(pixelMap->GetFd()));
4175     switch (HdrMetadataKey(metadataKey)) {
4176         case HDR_METADATA_TYPE:
4177             return GetMetadataType(env, surfaceBuffer, metadataValue);
4178             break;
4179         case HDR_STATIC_METADATA:
4180             return GetStaticMetadata(env, surfaceBuffer, metadataValue);
4181             break;
4182         case HDR_DYNAMIC_METADATA:
4183             return GetDynamicMetadata(env, surfaceBuffer, metadataValue);
4184             break;
4185         case HDR_GAINMAP_METADATA:
4186             {
4187                 std::vector<uint8_t> gainmapData;
4188                 if (VpeUtils::GetSbDynamicMetadata(surfaceBuffer, gainmapData) &&
4189                     (gainmapData.size() == sizeof(HDRVividExtendMetadata))) {
4190                     HDRVividExtendMetadata &gainmapMetadata =
4191                         *(reinterpret_cast<HDRVividExtendMetadata*>(gainmapData.data()));
4192                     metadataValue = BuildDynamicMetadataNapi(env, gainmapMetadata);
4193                     return napi_ok;
4194                 }
4195                 IMAGE_LOGE("GetSbDynamicMetadata failed");
4196             }
4197             break;
4198         default:
4199             break;
4200     }
4201     return napi_invalid_arg;
4202 }
4203 
GetMetadata(napi_env env,napi_callback_info info)4204 napi_value PixelMapNapi::GetMetadata(napi_env env, napi_callback_info info)
4205 {
4206     NapiValues nVal;
4207     napi_value argValue[NUM_1];
4208     nVal.argc = NUM_1;
4209     nVal.argv = argValue;
4210     nVal.status = napi_invalid_arg;
4211     if (!prepareNapiEnv(env, info, &nVal) || !nVal.context || !nVal.context->nConstructor ||
4212         !nVal.context->nConstructor->nativePixelMap_) {
4213         return ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "Fail to unwrap context");
4214     }
4215     std::shared_ptr<PixelMap> pixelMap = nVal.context->nConstructor->nativePixelMap_;
4216     if (pixelMap->GetAllocatorType() != AllocatorType::DMA_ALLOC) {
4217         return ImageNapiUtils::ThrowExceptionError(env, ERR_DMA_NOT_EXIST, "Not DMA memory");
4218     }
4219 
4220     IMG_NAPI_CHECK_RET_D(nVal.context->nConstructor->GetPixelNapiEditable(),
4221         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
4222         "Pixelmap has crossed threads . GetMetadata failed"),
4223         IMAGE_LOGE("Pixelmap has crossed threads . GetMetadata failed"));
4224     nVal.status = BuildHdrMetadataValue(env, nVal.argv, pixelMap, nVal.result);
4225     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(nVal.status),
4226         ImageNapiUtils::ThrowExceptionError(env, ERR_MEMORY_COPY_FAILED,
4227         "BuildHdrMetadataValue failed"),
4228         IMAGE_LOGE("BuildHdrMetadataValue failed"));
4229     return nVal.result;
4230 }
4231 
ParseHdrMetadataType(napi_env env,napi_value & hdrMetadataType)4232 static HdrMetadataType ParseHdrMetadataType(napi_env env, napi_value &hdrMetadataType)
4233 {
4234     uint32_t type = 0;
4235     napi_get_value_uint32(env, hdrMetadataType, &type);
4236     if (type < HdrMetadataType::INVALID && type >= HdrMetadataType::NONE) {
4237         return HdrMetadataType(type);
4238     }
4239     return HdrMetadataType::INVALID;
4240 }
4241 
ParseArrayDoubleNode(napi_env env,napi_value & root,std::vector<float> & vec)4242 static bool ParseArrayDoubleNode(napi_env env, napi_value &root, std::vector<float> &vec)
4243 {
4244     uint32_t vecSize = 0;
4245     napi_get_array_length(env, root, &vecSize);
4246     if (vecSize > 0) {
4247         for (uint32_t i = 0; i < NUM_3; i++) {
4248             napi_value tempDiv = nullptr;
4249             napi_get_element(env, root, i, &tempDiv);
4250             double gamma = 0.0f;
4251             if (napi_get_value_double(env, tempDiv, &gamma) != napi_ok) {
4252                 IMAGE_LOGD("ParseArrayDoubleNode get value failed");
4253                 return false;
4254             }
4255             vec.emplace_back((float)gamma);
4256         }
4257         return true;
4258     }
4259     return false;
4260 }
4261 
ParseDoubleMetadataNode(napi_env env,napi_value & root,std::string name,float & value)4262 static bool ParseDoubleMetadataNode(napi_env env, napi_value &root,
4263     std::string name, float &value)
4264 {
4265     double ret = 0.0;
4266     if (!GET_DOUBLE_BY_NAME(root, name.c_str(), ret)) {
4267         IMAGE_LOGI("parse %{public}s failed", name.c_str());
4268         return false;
4269     }
4270     value = static_cast<float>(ret);
4271     return true;
4272 }
4273 
ParseStaticMetadata(napi_env env,napi_value & hdrStaticMetadata,std::vector<uint8_t> & staticMetadataVec)4274 static bool ParseStaticMetadata(napi_env env, napi_value &hdrStaticMetadata, std::vector<uint8_t> &staticMetadataVec)
4275 {
4276     HDI::Display::Graphic::Common::V1_0::HdrStaticMetadata staticMetadata{};
4277     napi_value displayX = nullptr;
4278     std::vector<float> displayPrimariesX;
4279     if (!GET_NODE_BY_NAME(hdrStaticMetadata, "displayPrimariesX", displayX)) {
4280         IMAGE_LOGI("parse displayPrimariesX failed");
4281     }
4282     if (!ParseArrayDoubleNode(env, displayX, displayPrimariesX)) {
4283         IMAGE_LOGI("parse array y failed");
4284     }
4285     std::vector<float> displayPrimariesY;
4286     napi_value displayY = nullptr;
4287     if (!GET_NODE_BY_NAME(hdrStaticMetadata, "displayPrimariesY", displayY)) {
4288         IMAGE_LOGI("parse displayPrimariesY failed");
4289     }
4290     if (!ParseArrayDoubleNode(env, displayY, displayPrimariesY)) {
4291         IMAGE_LOGI("parse array y failed");
4292     }
4293     staticMetadata.smpte2086.displayPrimaryRed.x = displayPrimariesX[NUM_0];
4294     staticMetadata.smpte2086.displayPrimaryRed.y = displayPrimariesY[NUM_0];
4295     staticMetadata.smpte2086.displayPrimaryGreen.x = displayPrimariesX[NUM_1];
4296     staticMetadata.smpte2086.displayPrimaryGreen.y = displayPrimariesY[NUM_1];
4297     staticMetadata.smpte2086.displayPrimaryBlue.x = displayPrimariesX[NUM_2];
4298     staticMetadata.smpte2086.displayPrimaryBlue.y = displayPrimariesY[NUM_2];
4299     ParseDoubleMetadataNode(env, hdrStaticMetadata, "whitePointX", staticMetadata.smpte2086.whitePoint.x);
4300     ParseDoubleMetadataNode(env, hdrStaticMetadata, "whitePointY", staticMetadata.smpte2086.whitePoint.y);
4301     ParseDoubleMetadataNode(env, hdrStaticMetadata, "maxLuminance", staticMetadata.smpte2086.maxLuminance);
4302     ParseDoubleMetadataNode(env, hdrStaticMetadata, "minLuminance", staticMetadata.smpte2086.minLuminance);
4303     ParseDoubleMetadataNode(env, hdrStaticMetadata, "maxContentLightLevel",
4304         staticMetadata.cta861.maxContentLightLevel);
4305     ParseDoubleMetadataNode(env, hdrStaticMetadata, "maxFrameAverageLightLevel",
4306         staticMetadata.cta861.maxFrameAverageLightLevel);
4307     uint32_t vecSize = sizeof(HDI::Display::Graphic::Common::V1_0::HdrStaticMetadata);
4308     if (memcpy_s(staticMetadataVec.data(), vecSize, &staticMetadata, vecSize) != EOK) {
4309         IMAGE_LOGI("staticMetadataVec memcpy failed");
4310         return false;
4311     }
4312     return true;
4313 }
4314 
ParseDynamicMetadata(napi_env env,napi_value & root,std::vector<uint8_t> & dynamicMetadataVec)4315 static bool ParseDynamicMetadata(napi_env env, napi_value &root, std::vector<uint8_t> &dynamicMetadataVec)
4316 {
4317     void *buffer = nullptr;
4318     size_t size;
4319     if (napi_get_arraybuffer_info(env, root, &buffer, &size) != napi_ok) {
4320         return false;
4321     }
4322     dynamicMetadataVec.resize(size);
4323     if (memcpy_s(dynamicMetadataVec.data(), size, buffer, size) != EOK) {
4324         return false;
4325     }
4326     return true;
4327 }
4328 
ParseGainmapChannel(napi_env env,napi_value & root,HDRVividExtendMetadata & extendMetadata,int index)4329 static bool ParseGainmapChannel(napi_env env, napi_value &root, HDRVividExtendMetadata &extendMetadata, int index)
4330 {
4331     if (!ParseDoubleMetadataNode(env, root, "gainmapMax",
4332         extendMetadata.metaISO.enhanceClippedThreholdMaxGainmap[index])) {
4333         return false;
4334     }
4335     if (!ParseDoubleMetadataNode(env, root, "gainmapMin",
4336         extendMetadata.metaISO.enhanceClippedThreholdMinGainmap[index])) {
4337         return false;
4338     }
4339     if (!ParseDoubleMetadataNode(env, root, "gamma", extendMetadata.metaISO.enhanceMappingGamma[index])) {
4340         return false;
4341     }
4342     if (!ParseDoubleMetadataNode(env, root, "baseOffset", extendMetadata.metaISO.enhanceMappingBaselineOffset[index])) {
4343         return false;
4344     }
4345     if (!ParseDoubleMetadataNode(env, root, "alternateOffset",
4346         extendMetadata.metaISO.enhanceMappingAlternateOffset[index])) {
4347         return false;
4348     }
4349     return true;
4350 }
4351 
ParseGainmapNode(napi_env env,napi_value & root,HDRVividExtendMetadata & extendMetadata)4352 static void ParseGainmapNode(napi_env env, napi_value &root, HDRVividExtendMetadata &extendMetadata)
4353 {
4354     uint32_t isoMetadata = 0;
4355     if (!GET_UINT32_BY_NAME(root, "writerVersion", isoMetadata)) {
4356         IMAGE_LOGI("ParseGainmapNode parse writerVersion failed");
4357     }
4358     extendMetadata.metaISO.writeVersion = static_cast<unsigned short>(isoMetadata);
4359     if (!GET_UINT32_BY_NAME(root, "miniVersion", isoMetadata)) {
4360         IMAGE_LOGI("ParseGainmapNode parse miniVersion failed");
4361     }
4362     extendMetadata.metaISO.miniVersion = static_cast<unsigned short>(isoMetadata);
4363     if (!GET_UINT32_BY_NAME(root, "gainmapChannelCount", isoMetadata)) {
4364         IMAGE_LOGI("ParseGainmapNode parse gainmapChannelCount failed");
4365     }
4366     extendMetadata.metaISO.gainmapChannelNum = static_cast<unsigned char>(isoMetadata);
4367     bool colorflag = false;
4368     if (!GET_BOOL_BY_NAME(root, "useBaseColorFlag", colorflag)) {
4369         IMAGE_LOGI("ParseGainmapNode parse useBaseColorFlag failed");
4370     }
4371     extendMetadata.metaISO.useBaseColorFlag = static_cast<unsigned char>(colorflag);
4372     if (!ParseDoubleMetadataNode(env, root, "baseHeadroom", extendMetadata.metaISO.baseHeadroom)) {
4373         return;
4374     }
4375     if (!ParseDoubleMetadataNode(env, root, "alternateHeadroom", extendMetadata.metaISO.alternateHeadroom)) {
4376         return;
4377     }
4378     napi_value gainmap = nullptr;
4379     if (!GET_NODE_BY_NAME(root, "channels", gainmap)) {
4380         return;
4381     }
4382     bool isArray = false;
4383     napi_is_array(env, gainmap, &isArray);
4384     if (gainmap == nullptr || !isArray) {
4385         return;
4386     }
4387     uint32_t vecSize = 0;
4388     napi_get_array_length(env, gainmap, &vecSize);
4389     if (vecSize <= 0) {
4390         return;
4391     }
4392     for (uint32_t i = 0; i < NUM_3; i++) {
4393         napi_value tempDiv = nullptr;
4394         napi_get_element(env, gainmap, i, &tempDiv);
4395         ParseGainmapChannel(env, tempDiv, extendMetadata, i);
4396     }
4397     return;
4398 }
4399 
ParseGainmapMetedata(napi_env env,OHOS::Media::PixelMap & pixelmap,napi_value & root,std::vector<uint8_t> & gainmapMetadataVec)4400 static bool ParseGainmapMetedata(napi_env env, OHOS::Media::PixelMap &pixelmap,
4401     napi_value &root, std::vector<uint8_t> &gainmapMetadataVec)
4402 {
4403     HDRVividExtendMetadata extendMetadata;
4404     #ifdef IMAGE_COLORSPACE_FLAG
4405     OHOS::ColorManager::ColorSpace colorSpace = pixelmap.InnerGetGrColorSpace();
4406     uint16_t SS = ColorUtils::GetPrimaries(colorSpace.GetColorSpaceName());
4407     #else
4408     uint16_t SS = 0;
4409     #endif
4410     extendMetadata.baseColorMeta.baseColorPrimary = SS;
4411     bool colorflag = false;
4412     if (GET_BOOL_BY_NAME(root, "useBaseColorFlag", colorflag)) {
4413         extendMetadata.gainmapColorMeta.combineColorPrimary = colorflag ? SS : (uint8_t)CM_BT2020_HLG_FULL;
4414         extendMetadata.gainmapColorMeta.enhanceDataColorModel = colorflag ? SS : (uint8_t)CM_BT2020_HLG_FULL;
4415         extendMetadata.gainmapColorMeta.alternateColorPrimary = (uint8_t)CM_BT2020_HLG_FULL;
4416     }
4417     ParseGainmapNode(env, root, extendMetadata);
4418     uint32_t vecSize = sizeof(HDRVividExtendMetadata);
4419     if (memcpy_s(gainmapMetadataVec.data(), vecSize, &extendMetadata, vecSize) != EOK) {
4420         IMAGE_LOGE("ParseGainmapMetedata memcpy failed");
4421         return false;
4422     }
4423     return true;
4424 }
4425 
SetStaticMetadata(napi_env env,napi_value hdrMetadataValue,OHOS::sptr<OHOS::SurfaceBuffer> & surfaceBuffer)4426 static napi_status SetStaticMetadata(napi_env env, napi_value hdrMetadataValue,
4427     OHOS::sptr<OHOS::SurfaceBuffer> &surfaceBuffer)
4428 {
4429     uint32_t vecSize = sizeof(HDI::Display::Graphic::Common::V1_0::HdrStaticMetadata);
4430     std::vector<uint8_t> metadataVec(vecSize);
4431     if (!ParseStaticMetadata(env, hdrMetadataValue, metadataVec)) {
4432         return napi_invalid_arg;
4433     }
4434     if (!VpeUtils::SetSbStaticMetadata(surfaceBuffer, metadataVec)) {
4435         IMAGE_LOGE("SetSbStaticMetadata failed");
4436         return napi_invalid_arg;
4437     }
4438     return napi_ok;
4439 }
4440 
ParseHdrMetadataValue(napi_env env,napi_value argv[],std::shared_ptr<PixelMap> pixelMap)4441 static napi_status ParseHdrMetadataValue(napi_env env, napi_value argv[],
4442     std::shared_ptr<PixelMap> pixelMap)
4443 {
4444     uint32_t metadataKey = 0;
4445     napi_get_value_uint32(env, argv[0], &metadataKey);
4446     napi_value &hdrMetadataValue = argv[NUM_1];
4447     OHOS::sptr<OHOS::SurfaceBuffer> surfaceBuffer(
4448         reinterpret_cast<OHOS::SurfaceBuffer*>(pixelMap->GetFd()));
4449     switch (HdrMetadataKey(metadataKey)) {
4450         case HDR_METADATA_TYPE:
4451             {
4452                 HdrMetadataType type = ParseHdrMetadataType(env, hdrMetadataValue);
4453                 if (EtsMetadataMap.find(type) != EtsMetadataMap.end()) {
4454                     VpeUtils::SetSbMetadataType(surfaceBuffer, EtsMetadataMap[type]);
4455                 } else {
4456                     IMAGE_LOGE("SetSbMetadataType failed");
4457                     return napi_invalid_arg;
4458                 }
4459             }
4460             break;
4461         case HDR_STATIC_METADATA:
4462             return SetStaticMetadata(env, hdrMetadataValue, surfaceBuffer);
4463             break;
4464         case HDR_DYNAMIC_METADATA:
4465             {
4466                 std::vector<uint8_t> dynamicMetadataVec;
4467                 if (!ParseDynamicMetadata(env, hdrMetadataValue, dynamicMetadataVec)) {
4468                     return napi_invalid_arg;
4469                 }
4470                 if (!VpeUtils::SetSbDynamicMetadata(surfaceBuffer, dynamicMetadataVec)) {
4471                     return napi_invalid_arg;
4472                 }
4473             }
4474             break;
4475         case HDR_GAINMAP_METADATA:
4476             {
4477                 std::vector<uint8_t> gainmapMetadataVec(sizeof(HDRVividExtendMetadata));
4478                 if (!ParseGainmapMetedata(env, *(pixelMap.get()), hdrMetadataValue, gainmapMetadataVec)) {
4479                     return napi_invalid_arg;
4480                 }
4481                 if (!VpeUtils::SetSbDynamicMetadata(surfaceBuffer, gainmapMetadataVec)) {
4482                     return napi_invalid_arg;
4483                 }
4484             }
4485             break;
4486         default:
4487             return napi_invalid_arg;
4488     }
4489     return napi_ok;
4490 }
4491 
SetMetadataSync(napi_env env,napi_callback_info info)4492 napi_value PixelMapNapi::SetMetadataSync(napi_env env, napi_callback_info info)
4493 {
4494     IMAGE_LOGD("SetMetadataSync IN");
4495     NapiValues nVal;
4496     nVal.argc = NUM_2;
4497     napi_value argValue[NUM_2] = {0};
4498     nVal.argv = argValue;
4499     nVal.status = napi_invalid_arg;
4500     napi_get_undefined(env, &nVal.result);
4501     if (!prepareNapiEnv(env, info, &nVal)) {
4502         return ImageNapiUtils::ThrowExceptionError(
4503             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to unwrap context");
4504     }
4505     if (nVal.argc != NUM_2) {
4506         return ImageNapiUtils::ThrowExceptionError(
4507             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid args count");
4508     }
4509     uint32_t metadataKey = 0;
4510     napi_get_value_uint32(env, argValue[NUM_0], &metadataKey);
4511     if (metadataKey != 0 && ImageNapiUtils::getType(env, argValue[NUM_1]) != napi_object) {
4512         return ImageNapiUtils::ThrowExceptionError(
4513             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid parameter");
4514     }
4515     std::shared_ptr<PixelMap> pixelMap = nVal.context->nConstructor->nativePixelMap_;
4516     if (pixelMap->GetAllocatorType() != AllocatorType::DMA_ALLOC) {
4517         return ImageNapiUtils::ThrowExceptionError(
4518             env, ERR_DMA_NOT_EXIST, "Not DMA memory");
4519     }
4520 
4521     IMG_NAPI_CHECK_RET_D(nVal.context->nConstructor->GetPixelNapiEditable(),
4522         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
4523         "Pixelmap has crossed threads . SetColorSpace failed"),
4524         IMAGE_LOGE("Pixelmap has crossed threads . SetColorSpace failed"));
4525     nVal.status = ParseHdrMetadataValue(env, nVal.argv, pixelMap);
4526     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(nVal.status),
4527         ImageNapiUtils::ThrowExceptionError(env, ERR_MEMORY_COPY_FAILED,
4528         "ParseHdrMetadataValue failed"),
4529         IMAGE_LOGE("ParseHdrMetadataValue failed"));
4530     return nVal.result;
4531 }
4532 
SetMetadata(napi_env env,napi_callback_info info)4533 napi_value PixelMapNapi::SetMetadata(napi_env env, napi_callback_info info)
4534 {
4535     IMAGE_LOGD("SetMetadataSync IN");
4536     NapiValues nVal;
4537     nVal.argc = NUM_2;
4538     napi_value argValue[NUM_2] = {0};
4539     nVal.argv = argValue;
4540     nVal.status = napi_ok;
4541     napi_status status;
4542     napi_get_undefined(env, &nVal.result);
4543     if (!prepareNapiEnv(env, info, &nVal)) {
4544         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
4545     }
4546     if (nVal.argc != NUM_2) {
4547         IMAGE_LOGE("Invalid args count");
4548         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
4549     }
4550     uint32_t metadataKey = 0;
4551     napi_get_value_uint32(env, argValue[NUM_0], &metadataKey);
4552     if (metadataKey != 0 && ImageNapiUtils::getType(env, argValue[NUM_1]) != napi_object) {
4553         IMAGE_LOGE("Invalid parameter");
4554         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
4555     }
4556     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
4557     if (nVal.context->rPixelMap->GetAllocatorType() != AllocatorType::DMA_ALLOC) {
4558         nVal.context->status = ERR_DMA_NOT_EXIST;
4559     }
4560     if (nVal.context->status == napi_ok) {
4561         nVal.status = ParseHdrMetadataValue(env, nVal.argv, nVal.context->rPixelMap);
4562         if (nVal.status != napi_ok) {
4563             nVal.context->status = ERR_MEMORY_COPY_FAILED;
4564         }
4565     }
4566     napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
4567     if (!nVal.context->nConstructor->GetPixelNapiEditable()) {
4568         nVal.context->status = ERR_RESOURCE_UNAVAILABLE;
4569         IMAGE_LOGE("Pixelmap has crossed threads . SetColorSpace failed");
4570     }
4571     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "SetMetadata",
4572         [](napi_env env, void *data) {
4573         }, EmptyResultComplete, nVal.context, nVal.context->work);
4574     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
4575         nullptr, IMAGE_LOGE("fail to create async work"));
4576     return nVal.result;
4577 }
4578 #else
SetMetadata(napi_env env,napi_callback_info info)4579 napi_value PixelMapNapi::SetMetadata(napi_env env, napi_callback_info info)
4580 {
4581     NapiValues nVal;
4582     napi_get_undefined(env, &nVal.result);
4583     return nVal.result;
4584 }
SetMetadataSync(napi_env env,napi_callback_info info)4585 napi_value PixelMapNapi::SetMetadataSync(napi_env env, napi_callback_info info)
4586 {
4587     NapiValues nVal;
4588     napi_get_undefined(env, &nVal.result);
4589     return nVal.result;
4590 }
GetMetadata(napi_env env,napi_callback_info info)4591 napi_value PixelMapNapi::GetMetadata(napi_env env, napi_callback_info info)
4592 {
4593     NapiValues nVal;
4594     napi_get_undefined(env, &nVal.result);
4595     return nVal.result;
4596 }
4597 #endif
4598 
release()4599 void PixelMapNapi::release()
4600 {
4601     if (!isRelease) {
4602         if (nativePixelMap_ != nullptr) {
4603             nativePixelMap_.reset();
4604         }
4605         isRelease = true;
4606     }
4607 }
4608 }  // namespace Media
4609 }  // namespace OHOS
4610