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