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