• 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_trace.h"
22 #include "log_tags.h"
23 #include "color_space_object_convertor.h"
24 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
25 #include "js_runtime_utils.h"
26 #include "napi_message_sequence.h"
27 #include "pixel_map_from_surface.h"
28 #endif
29 #include "hitrace_meter.h"
30 #include "pixel_map.h"
31 
32 #undef LOG_DOMAIN
33 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
34 
35 #undef LOG_TAG
36 #define LOG_TAG "PixelMapNapi"
37 
38 namespace {
39     constexpr uint32_t NUM_0 = 0;
40     constexpr uint32_t NUM_1 = 1;
41     constexpr uint32_t NUM_2 = 2;
42     constexpr uint32_t NUM_3 = 3;
43     constexpr uint32_t NUM_4 = 4;
44 }
45 
46 namespace OHOS {
47 namespace Media {
48 static const std::string CREATE_PIXEL_MAP_FROM_PARCEL = "createPixelMapFromParcel";
49 static const std::string MARSHALLING = "marshalling";
50 static const std::map<std::string, std::set<uint32_t>> ETS_API_ERROR_CODE = {
51     {CREATE_PIXEL_MAP_FROM_PARCEL, {62980096, 62980105, 62980115, 62980097,
52         62980177, 62980178, 62980179, 62980180, 62980246}},
53     {MARSHALLING, {62980115, 62980097, 62980096}}
54 };
55 static const std::string CLASS_NAME = "PixelMap";
56 static const std::int32_t NEW_INSTANCE_ARGC = 1;
57 thread_local napi_ref PixelMapNapi::sConstructor_ = nullptr;
58 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
59 NAPI_MessageSequence* napi_messageSequence = nullptr;
60 #endif
61 
62 static std::mutex pixelMapCrossThreadMutex_;
63 struct PositionArea {
64     void* pixels;
65     size_t size;
66     uint32_t offset;
67     uint32_t stride;
68     Rect region;
69 };
70 
71 struct PixelMapAsyncContext {
72     napi_env env;
73     napi_async_work work;
74     napi_deferred deferred;
75     napi_ref callbackRef;
76     napi_ref error = nullptr;
77     uint32_t status;
78     PixelMapNapi *nConstructor;
79     void* colorsBuffer;
80     size_t colorsBufferSize;
81     InitializationOptions opts;
82     PositionArea area;
83     std::shared_ptr<PixelMap> rPixelMap;
84     std::shared_ptr<PixelMap> alphaMap;
85     double alpha = -1;
86     uint32_t resultUint32;
87     ImageInfo imageInfo;
88     double xArg = 0;
89     double yArg = 0;
90     bool xBarg = false;
91     bool yBarg = false;
92     std::shared_ptr<OHOS::ColorManager::ColorSpace> colorSpace;
93     std::string surfaceId;
94 };
95 
96 class AgainstTransferGC {
97 public:
98     std::shared_ptr<PixelMap> pixelMap = nullptr;
~AgainstTransferGC()99     ~AgainstTransferGC()
100     {
101         pixelMap = nullptr;
102     }
103 };
104 
ParsePixlForamt(int32_t val)105 static PixelFormat ParsePixlForamt(int32_t val)
106 {
107     if (val <= static_cast<int32_t>(PixelFormat::CMYK)) {
108         return PixelFormat(val);
109     }
110 
111     return PixelFormat::UNKNOWN;
112 }
113 
ParseAlphaType(int32_t val)114 static AlphaType ParseAlphaType(int32_t val)
115 {
116     if (val <= static_cast<int32_t>(AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL)) {
117         return AlphaType(val);
118     }
119 
120     return AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
121 }
122 
ParseScaleMode(int32_t val)123 static ScaleMode ParseScaleMode(int32_t val)
124 {
125     if (val <= static_cast<int32_t>(ScaleMode::CENTER_CROP)) {
126         return ScaleMode(val);
127     }
128 
129     return ScaleMode::FIT_TARGET_SIZE;
130 }
131 
parseSize(napi_env env,napi_value root,Size * size)132 static bool parseSize(napi_env env, napi_value root, Size* size)
133 {
134     if (size == nullptr) {
135         return false;
136     }
137 
138     if (!GET_INT32_BY_NAME(root, "height", size->height)) {
139         return false;
140     }
141 
142     if (!GET_INT32_BY_NAME(root, "width", size->width)) {
143         return false;
144     }
145 
146     return true;
147 }
148 
parseInitializationOptions(napi_env env,napi_value root,InitializationOptions * opts)149 static bool parseInitializationOptions(napi_env env, napi_value root, InitializationOptions* opts)
150 {
151     uint32_t tmpNumber = 0;
152     napi_value tmpValue = nullptr;
153 
154     if (opts == nullptr) {
155         return false;
156     }
157 
158     if (!GET_BOOL_BY_NAME(root, "editable", opts->editable)) {
159         opts->editable = true;
160     }
161 
162     if (!GET_UINT32_BY_NAME(root, "alphaType", tmpNumber)) {
163         IMAGE_LOGI("no alphaType in initialization options");
164     }
165     opts->alphaType = ParseAlphaType(tmpNumber);
166 
167     tmpNumber = 0;
168     if (!GET_UINT32_BY_NAME(root, "pixelFormat", tmpNumber)) {
169         IMAGE_LOGI("no pixelFormat in initialization options");
170     }
171     opts->pixelFormat = ParsePixlForamt(tmpNumber);
172 
173     tmpNumber = 0;
174     if (!GET_UINT32_BY_NAME(root, "scaleMode", tmpNumber)) {
175         IMAGE_LOGI("no scaleMode in initialization options");
176     }
177     opts->scaleMode = ParseScaleMode(tmpNumber);
178 
179     if (!GET_NODE_BY_NAME(root, "size", tmpValue)) {
180         return false;
181     }
182 
183     if (!parseSize(env, tmpValue, &(opts->size))) {
184         return false;
185     }
186     return true;
187 }
188 
parseRegion(napi_env env,napi_value root,Rect * region)189 static bool parseRegion(napi_env env, napi_value root, Rect* region)
190 {
191     napi_value tmpValue = nullptr;
192 
193     if (region == nullptr) {
194         return false;
195     }
196 
197     if (!GET_INT32_BY_NAME(root, "x", region->left)) {
198         return false;
199     }
200 
201     if (!GET_INT32_BY_NAME(root, "y", region->top)) {
202         return false;
203     }
204 
205     if (!GET_NODE_BY_NAME(root, "size", tmpValue)) {
206         return false;
207     }
208 
209     if (!GET_INT32_BY_NAME(tmpValue, "height", region->height)) {
210         return false;
211     }
212 
213     if (!GET_INT32_BY_NAME(tmpValue, "width", region->width)) {
214         return false;
215     }
216 
217     return true;
218 }
219 
parsePositionArea(napi_env env,napi_value root,PositionArea * area)220 static bool parsePositionArea(napi_env env, napi_value root, PositionArea* area)
221 {
222     napi_value tmpValue = nullptr;
223 
224     if (area == nullptr) {
225         return false;
226     }
227 
228     if (!GET_BUFFER_BY_NAME(root, "pixels", area->pixels, area->size)) {
229         return false;
230     }
231 
232     if (!GET_UINT32_BY_NAME(root, "offset", area->offset)) {
233         return false;
234     }
235 
236     if (!GET_UINT32_BY_NAME(root, "stride", area->stride)) {
237         return false;
238     }
239 
240     if (!GET_NODE_BY_NAME(root, "region", tmpValue)) {
241         return false;
242     }
243 
244     if (!parseRegion(env, tmpValue, &(area->region))) {
245         return false;
246     }
247     return true;
248 }
249 
CommonCallbackRoutine(napi_env env,PixelMapAsyncContext * & asyncContext,const napi_value & valueParam)250 static void CommonCallbackRoutine(napi_env env, PixelMapAsyncContext* &asyncContext, const napi_value &valueParam)
251 {
252     napi_value result[NUM_2] = {0};
253     napi_value retVal;
254     napi_value callback = nullptr;
255 
256     napi_get_undefined(env, &result[NUM_0]);
257     napi_get_undefined(env, &result[NUM_1]);
258 
259     napi_handle_scope scope = nullptr;
260     napi_open_handle_scope(env, &scope);
261     if (scope == nullptr) {
262         return;
263     }
264 
265     if (asyncContext == nullptr) {
266         return;
267     }
268     if (asyncContext->status == SUCCESS) {
269         result[NUM_1] = valueParam;
270     } else if (asyncContext->error != nullptr) {
271         napi_get_reference_value(env, asyncContext->error, &result[NUM_0]);
272         napi_delete_reference(env, asyncContext->error);
273     } else {
274         napi_create_uint32(env, asyncContext->status, &result[NUM_0]);
275     }
276 
277     if (asyncContext->deferred) {
278         if (asyncContext->status == SUCCESS) {
279             napi_resolve_deferred(env, asyncContext->deferred, result[NUM_1]);
280         } else {
281             napi_reject_deferred(env, asyncContext->deferred, result[NUM_0]);
282         }
283     } else {
284         napi_get_reference_value(env, asyncContext->callbackRef, &callback);
285         napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
286         napi_delete_reference(env, asyncContext->callbackRef);
287     }
288 
289     napi_delete_async_work(env, asyncContext->work);
290     napi_close_handle_scope(env, scope);
291 
292     delete asyncContext;
293     asyncContext = nullptr;
294 }
295 
STATIC_COMPLETE_FUNC(EmptyResult)296 STATIC_COMPLETE_FUNC(EmptyResult)
297 {
298     napi_value result = nullptr;
299     napi_get_undefined(env, &result);
300 
301     auto context = static_cast<PixelMapAsyncContext*>(data);
302 
303     CommonCallbackRoutine(env, context, result);
304 }
305 
STATIC_COMPLETE_FUNC(GeneralError)306 STATIC_COMPLETE_FUNC(GeneralError)
307 {
308     napi_value result = nullptr;
309     napi_get_undefined(env, &result);
310     auto context = static_cast<PixelMapAsyncContext*>(data);
311     context->status = ERR_RESOURCE_UNAVAILABLE;
312     CommonCallbackRoutine(env, context, result);
313 }
314 
PixelMapNapi()315 PixelMapNapi::PixelMapNapi():env_(nullptr)
316 {
317     static std::atomic<uint32_t> currentId = 0;
318     uniqueId_ = currentId.fetch_add(1, std::memory_order_relaxed);
319 }
320 
~PixelMapNapi()321 PixelMapNapi::~PixelMapNapi()
322 {
323     release();
324 }
325 
DoInitAfter(napi_env env,napi_value exports,napi_value constructor,size_t property_count,const napi_property_descriptor * properties)326 static napi_value DoInitAfter(napi_env env,
327                               napi_value exports,
328                               napi_value constructor,
329                               size_t property_count,
330                               const napi_property_descriptor* properties)
331 {
332     napi_value global = nullptr;
333     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
334         napi_get_global(env, &global)),
335         nullptr, IMAGE_LOGE("Init:get global fail")
336     );
337 
338     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
339         napi_set_named_property(env, global, CLASS_NAME.c_str(), constructor)),
340         nullptr, IMAGE_LOGE("Init:set global named property fail")
341     );
342 
343     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
344         napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor)),
345         nullptr, IMAGE_LOGE("set named property fail")
346     );
347 
348     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
349         napi_define_properties(env, exports, property_count, properties)),
350         nullptr, IMAGE_LOGE("define properties fail")
351     );
352     return exports;
353 }
354 
Init(napi_env env,napi_value exports)355 napi_value PixelMapNapi::Init(napi_env env, napi_value exports)
356 {
357     napi_property_descriptor props[] = {
358         DECLARE_NAPI_FUNCTION("readPixelsToBuffer", ReadPixelsToBuffer),
359         DECLARE_NAPI_FUNCTION("readPixels", ReadPixels),
360         DECLARE_NAPI_FUNCTION("writePixels", WritePixels),
361         DECLARE_NAPI_FUNCTION("writeBufferToPixels", WriteBufferToPixels),
362         DECLARE_NAPI_FUNCTION("getImageInfo", GetImageInfo),
363         DECLARE_NAPI_FUNCTION("getBytesNumberPerRow", GetBytesNumberPerRow),
364         DECLARE_NAPI_FUNCTION("getPixelBytesNumber", GetPixelBytesNumber),
365         DECLARE_NAPI_FUNCTION("isSupportAlpha", IsSupportAlpha),
366         DECLARE_NAPI_FUNCTION("setAlphaAble", SetAlphaAble),
367         DECLARE_NAPI_FUNCTION("createAlphaPixelmap", CreateAlphaPixelmap),
368         DECLARE_NAPI_FUNCTION("getDensity", GetDensity),
369         DECLARE_NAPI_FUNCTION("setDensity", SetDensity),
370         DECLARE_NAPI_FUNCTION("opacity", SetAlpha),
371         DECLARE_NAPI_FUNCTION("release", Release),
372         DECLARE_NAPI_FUNCTION("scale", Scale),
373         DECLARE_NAPI_FUNCTION("translate", Translate),
374         DECLARE_NAPI_FUNCTION("rotate", Rotate),
375         DECLARE_NAPI_FUNCTION("flip", Flip),
376         DECLARE_NAPI_FUNCTION("crop", Crop),
377         DECLARE_NAPI_FUNCTION("getColorSpace", GetColorSpace),
378         DECLARE_NAPI_FUNCTION("setColorSpace", SetColorSpace),
379         DECLARE_NAPI_FUNCTION("applyColorSpace", ApplyColorSpace),
380         DECLARE_NAPI_FUNCTION("marshalling", Marshalling),
381         DECLARE_NAPI_FUNCTION("unmarshalling", Unmarshalling),
382         DECLARE_NAPI_GETTER("isEditable", GetIsEditable),
383         DECLARE_NAPI_GETTER("isStrideAlignment", GetIsStrideAlignment),
384     };
385 
386     napi_property_descriptor static_prop[] = {
387         DECLARE_NAPI_STATIC_FUNCTION("createPixelMap", CreatePixelMap),
388         DECLARE_NAPI_STATIC_FUNCTION("unmarshalling", Unmarshalling),
389         DECLARE_NAPI_STATIC_FUNCTION(CREATE_PIXEL_MAP_FROM_PARCEL.c_str(), CreatePixelMapFromParcel),
390 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
391         DECLARE_NAPI_STATIC_FUNCTION("createPixelMapFromSurface", CreatePixelMapFromSurface),
392 #endif
393     };
394 
395     napi_value constructor = nullptr;
396 
397     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
398         napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
399                           Constructor, nullptr, IMG_ARRAY_SIZE(props),
400                           props, &constructor)),
401         nullptr, IMAGE_LOGE("define class fail")
402     );
403 
404     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
405         napi_create_reference(env, constructor, 1, &sConstructor_)),
406         nullptr, IMAGE_LOGE("create reference fail")
407     );
408 
409     auto result = DoInitAfter(env, exports, constructor,
410         IMG_ARRAY_SIZE(static_prop), static_prop);
411 
412     IMAGE_LOGD("Init success");
413     return result;
414 }
415 
GetPixelMap(napi_env env,napi_value pixelmap)416 std::shared_ptr<PixelMap> PixelMapNapi::GetPixelMap(napi_env env, napi_value pixelmap)
417 {
418     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
419 
420     napi_status status = napi_unwrap(env, pixelmap, reinterpret_cast<void**>(&pixelMapNapi));
421     if (!IMG_IS_OK(status)) {
422         IMAGE_LOGE("GetPixelMap napi unwrap failed");
423         return nullptr;
424     }
425 
426     if (pixelMapNapi == nullptr) {
427         IMAGE_LOGE("GetPixelMap pixmapNapi is nullptr");
428         return nullptr;
429     }
430 
431     auto pixelmapNapiPtr = pixelMapNapi.release();
432     if (pixelmapNapiPtr == nullptr) {
433         IMAGE_LOGE("GetPixelMap pixelmapNapi is nullptr");
434         return nullptr;
435     }
436     return pixelmapNapiPtr->nativePixelMap_;
437 }
438 
GetPixelMap()439 std::shared_ptr<PixelMap>* PixelMapNapi::GetPixelMap()
440 {
441     return &nativePixelMap_;
442 }
443 
IsLockPixelMap()444 bool PixelMapNapi::IsLockPixelMap()
445 {
446     return (lockCount > 0);
447 }
448 
LockPixelMap()449 bool PixelMapNapi::LockPixelMap()
450 {
451     lockCount++;
452     return true;
453 }
454 
UnlockPixelMap()455 void PixelMapNapi::UnlockPixelMap()
456 {
457     if (lockCount > 0) {
458         lockCount--;
459     }
460 }
461 
OHOS_MEDIA_GetPixelMap(napi_env env,napi_value value)462 extern "C" __attribute__((visibility("default"))) void* OHOS_MEDIA_GetPixelMap(napi_env env, napi_value value)
463 {
464     PixelMapNapi *pixmapNapi = nullptr;
465     napi_unwrap(env, value, reinterpret_cast<void**>(&pixmapNapi));
466     if (pixmapNapi == nullptr) {
467         IMAGE_LOGE("pixmapNapi unwrapped is nullptr");
468         return nullptr;
469     }
470     return reinterpret_cast<void*>(pixmapNapi->GetPixelMap());
471 }
472 
OHOS_MEDIA_GetImageInfo(napi_env env,napi_value value,OhosPixelMapInfo * info)473 extern "C" __attribute__((visibility("default"))) int32_t OHOS_MEDIA_GetImageInfo(napi_env env, napi_value value,
474     OhosPixelMapInfo *info)
475 {
476     IMAGE_LOGD("GetImageInfo IN");
477 
478     if (info == nullptr) {
479         IMAGE_LOGE("info is nullptr");
480         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
481     }
482 
483     PixelMapNapi *pixmapNapi = nullptr;
484     napi_unwrap(env, value, reinterpret_cast<void**>(&pixmapNapi));
485     if (pixmapNapi == nullptr) {
486         IMAGE_LOGE("pixmapNapi unwrapped is nullptr");
487         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
488     }
489 
490     std::shared_ptr<PixelMap> pixelMap = pixmapNapi->GetPixelNapiInner();
491     if ((pixelMap == nullptr)) {
492         IMAGE_LOGE("pixelMap is nullptr");
493         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
494     }
495 
496     ImageInfo imageInfo;
497     pixelMap->GetImageInfo(imageInfo);
498     info->width = imageInfo.size.width;
499     info->height = imageInfo.size.height;
500     info->rowSize = pixelMap->GetRowStride();
501     info->pixelFormat = static_cast<int32_t>(imageInfo.pixelFormat);
502 
503     IMAGE_LOGD("GetImageInfo, w=%{public}u, h=%{public}u, r=%{public}u, f=%{public}d",
504         info->width, info->height, info->rowSize, info->pixelFormat);
505 
506     return OHOS_IMAGE_RESULT_SUCCESS;
507 }
508 
OHOS_MEDIA_AccessPixels(napi_env env,napi_value value,uint8_t ** addrPtr)509 extern "C" __attribute__((visibility("default"))) int32_t OHOS_MEDIA_AccessPixels(napi_env env, napi_value value,
510     uint8_t** addrPtr)
511 {
512     IMAGE_LOGI("AccessPixels IN");
513 
514     PixelMapNapi *pixmapNapi = nullptr;
515     napi_unwrap(env, value, reinterpret_cast<void**>(&pixmapNapi));
516     if (pixmapNapi == nullptr) {
517         IMAGE_LOGE("pixmapNapi unwrapped is nullptr");
518         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
519     }
520 
521     std::shared_ptr<PixelMap> pixelMap = pixmapNapi->GetPixelNapiInner();
522     if (pixelMap == nullptr) {
523         IMAGE_LOGE("pixelMap is nullptr");
524         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
525     }
526 
527     const uint8_t *constPixels = pixelMap->GetPixels();
528     if (constPixels == nullptr) {
529         IMAGE_LOGE("const pixels is nullptr");
530         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
531     }
532 
533     uint8_t *pixels = const_cast<uint8_t*>(constPixels);
534     if (pixels == nullptr) {
535         IMAGE_LOGE("pixels is nullptr");
536         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
537     }
538 
539     pixmapNapi->LockPixelMap();
540 
541     if (addrPtr != nullptr) {
542         *addrPtr = pixels;
543     }
544 
545     IMAGE_LOGD("AccessPixels OUT");
546     return OHOS_IMAGE_RESULT_SUCCESS;
547 }
548 
OHOS_MEDIA_UnAccessPixels(napi_env env,napi_value value)549 extern "C" __attribute__((visibility("default"))) int32_t OHOS_MEDIA_UnAccessPixels(napi_env env, napi_value value)
550 {
551     IMAGE_LOGD("UnAccessPixels IN");
552 
553     PixelMapNapi *pixmapNapi = nullptr;
554     napi_unwrap(env, value, reinterpret_cast<void**>(&pixmapNapi));
555     if (pixmapNapi == nullptr) {
556         IMAGE_LOGE("pixmapNapi unwrapped is nullptr");
557         return OHOS_IMAGE_RESULT_BAD_PARAMETER;
558     }
559 
560     pixmapNapi->UnlockPixelMap();
561 
562     return OHOS_IMAGE_RESULT_SUCCESS;
563 }
564 
DetachPixelMapFunc(napi_env env,void * value,void *)565 inline void *DetachPixelMapFunc(napi_env env, void *value, void *)
566 {
567     IMAGE_LOGD("DetachPixelMapFunc in");
568     if (value == nullptr) {
569         IMAGE_LOGE("DetachPixelMapFunc value is nullptr");
570         return value;
571     }
572     auto pixelNapi = reinterpret_cast<PixelMapNapi*>(value);
573     pixelNapi->setPixelNapiEditable(false);
574     AgainstTransferGC *data = new AgainstTransferGC();
575     data->pixelMap = pixelNapi->GetPixelNapiInner();
576     return reinterpret_cast<void*>(data);
577 }
578 
NewPixelNapiInstance(napi_env & env,napi_value & constructor,std::shared_ptr<PixelMap> & pixelMap,napi_value & result)579 static napi_status NewPixelNapiInstance(napi_env &env, napi_value &constructor,
580     std::shared_ptr<PixelMap> &pixelMap, napi_value &result)
581 {
582     napi_status status;
583     if (pixelMap == nullptr) {
584         status = napi_invalid_arg;
585         IMAGE_LOGE("NewPixelNapiInstance pixelMap is nullptr");
586         return status;
587     }
588     size_t argc = NEW_INSTANCE_ARGC;
589     napi_value argv[NEW_INSTANCE_ARGC] = { 0 };
590     napi_create_int32(env, pixelMap->GetUniqueId(), &argv[0]);
591     PixelMapContainer::GetInstance().Insert(pixelMap->GetUniqueId(), pixelMap);
592     status = napi_new_instance(env, constructor, argc, argv, &result);
593     return status;
594 }
595 
AttachPixelMapFunc(napi_env env,void * value,void *)596 napi_value AttachPixelMapFunc(napi_env env, void *value, void *)
597 {
598     if (value == nullptr) {
599         IMAGE_LOGE("attach value is nullptr");
600         return nullptr;
601     }
602     std::lock_guard<std::mutex> lock(pixelMapCrossThreadMutex_);
603 
604     napi_value result = nullptr;
605     if (value == nullptr) {
606         IMAGE_LOGE("attach value lock losed");
607         napi_get_undefined(env, &result);
608         return result;
609     }
610     AgainstTransferGC *data = reinterpret_cast<AgainstTransferGC*>(value);
611     std::shared_ptr<PixelMap> attachPixelMap = std::move(data->pixelMap);
612     delete data;
613     if (attachPixelMap == nullptr) {
614         IMAGE_LOGE("AttachPixelMapFunc attachPixelMap is nullptr");
615         napi_get_undefined(env, &result);
616         return result;
617     }
618     napi_value constructor = nullptr;
619     napi_status status;
620 
621     if (PixelMapNapi::GetConstructor() == nullptr) {
622         IMAGE_LOGI("PixelMapNapi::GetConstructor() is nullptr");
623         napi_value exports = nullptr;
624         napi_create_object(env, &exports);
625         PixelMapNapi::Init(env, exports);
626     }
627     napi_value globalValue;
628     napi_get_global(env, &globalValue);
629     status = napi_get_named_property(env, globalValue, CLASS_NAME.c_str(), &constructor);
630     if (!IMG_IS_OK(status)) {
631         IMAGE_LOGI("napi_get_named_property failed requireNapi in");
632         napi_value func;
633         napi_get_named_property(env, globalValue, "requireNapi", &func);
634 
635         napi_value imageInfo;
636         napi_create_string_utf8(env, "multimedia.image", NAPI_AUTO_LENGTH, &imageInfo);
637         napi_value funcArgv[1] = { imageInfo };
638         napi_value returnValue;
639         napi_call_function(env, globalValue, func, 1, funcArgv, &returnValue);
640         status = napi_get_named_property(env, globalValue, CLASS_NAME.c_str(), &constructor);
641         IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("napi_get_named_property error"));
642     }
643 
644     status = NewPixelNapiInstance(env, constructor, attachPixelMap, result);
645     if (!IMG_IS_OK(status)) {
646         IMAGE_LOGE("AttachPixelMapFunc napi_get_referencce_value failed");
647     }
648     return result;
649 }
650 
Constructor(napi_env env,napi_callback_info info)651 napi_value PixelMapNapi::Constructor(napi_env env, napi_callback_info info)
652 {
653     napi_value undefineVar = nullptr;
654     napi_get_undefined(env, &undefineVar);
655 
656     napi_status status;
657     napi_value thisVar = nullptr;
658     napi_get_undefined(env, &thisVar);
659     size_t argc = NEW_INSTANCE_ARGC;
660     napi_value argv[NEW_INSTANCE_ARGC] = { 0 };
661     IMAGE_LOGD("Constructor IN");
662     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
663     IMG_NAPI_CHECK_RET(IMG_IS_READY(status, thisVar), undefineVar);
664     uint32_t pixelMapId = 0;
665     napi_get_value_uint32(env, argv[0], &pixelMapId);
666     std::unique_ptr<PixelMapNapi> pPixelMapNapi = std::make_unique<PixelMapNapi>();
667 
668     IMG_NAPI_CHECK_RET(IMG_NOT_NULL(pPixelMapNapi), undefineVar);
669 
670     pPixelMapNapi->env_ = env;
671     if (PixelMapContainer::GetInstance().Find(pixelMapId)) {
672         pPixelMapNapi->nativePixelMap_ = PixelMapContainer::GetInstance()[pixelMapId];
673         IMAGE_LOGD("Constructor in napi_id:%{public}d, id:%{public}d",
674             pPixelMapNapi->GetUniqueId(), pPixelMapNapi->nativePixelMap_->GetUniqueId());
675     } else {
676         IMAGE_LOGE("Constructor nativePixelMap is nullptr");
677     }
678 
679     napi_coerce_to_native_binding_object(
680         env, thisVar, DetachPixelMapFunc, AttachPixelMapFunc, pPixelMapNapi.get(), nullptr);
681 
682     status = napi_wrap(env, thisVar, reinterpret_cast<void*>(pPixelMapNapi.get()),
683         PixelMapNapi::Destructor, nullptr, nullptr);
684     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), undefineVar, IMAGE_LOGE("Failure wrapping js to native napi"));
685 
686     pPixelMapNapi.release();
687     PixelMapContainer::GetInstance().Erase(pixelMapId);
688     return thisVar;
689 }
690 
Destructor(napi_env env,void * nativeObject,void * finalize)691 void PixelMapNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
692 {
693     if (nativeObject != nullptr) {
694         std::lock_guard<std::mutex> lock(pixelMapCrossThreadMutex_);
695         IMAGE_LOGD("Destructor pixelmapNapi");
696         delete reinterpret_cast<PixelMapNapi*>(nativeObject);
697         nativeObject = nullptr;
698     }
699 }
700 
BuildContextError(napi_env env,napi_ref & error,const std::string errMsg,const int32_t errCode)701 static void BuildContextError(napi_env env, napi_ref &error, const std::string errMsg, const int32_t errCode)
702 {
703     IMAGE_LOGE("%{public}s", errMsg.c_str());
704     napi_value tmpError;
705     ImageNapiUtils::CreateErrorObj(env, tmpError, errCode, errMsg);
706     napi_create_reference(env, tmpError, NUM_1, &(error));
707 }
708 
STATIC_EXEC_FUNC(CreatePixelMap)709 STATIC_EXEC_FUNC(CreatePixelMap)
710 {
711     auto context = static_cast<PixelMapAsyncContext*>(data);
712     auto colors = static_cast<uint32_t*>(context->colorsBuffer);
713     auto pixelmap = PixelMap::Create(colors, context->colorsBufferSize, context->opts);
714 
715     context->rPixelMap = std::move(pixelmap);
716 
717     if (IMG_NOT_NULL(context->rPixelMap)) {
718         context->status = SUCCESS;
719     } else {
720         context->status = ERROR;
721     }
722 }
723 
CreatePixelMapComplete(napi_env env,napi_status status,void * data)724 void PixelMapNapi::CreatePixelMapComplete(napi_env env, napi_status status, void *data)
725 {
726     napi_value constructor = nullptr;
727     napi_value result = nullptr;
728 
729     IMAGE_LOGD("CreatePixelMapComplete IN");
730     auto context = static_cast<PixelMapAsyncContext*>(data);
731 
732     status = napi_get_reference_value(env, sConstructor_, &constructor);
733 
734     if (IMG_IS_OK(status)) {
735         status = NewPixelNapiInstance(env, constructor, context->rPixelMap, result);
736     }
737 
738     if (!IMG_IS_OK(status)) {
739         context->status = ERROR;
740         IMAGE_LOGE("New instance could not be obtained");
741         napi_get_undefined(env, &result);
742     }
743 
744     CommonCallbackRoutine(env, context, result);
745 }
746 
CreatePixelMap(napi_env env,napi_callback_info info)747 napi_value PixelMapNapi::CreatePixelMap(napi_env env, napi_callback_info info)
748 {
749     if (PixelMapNapi::GetConstructor() == nullptr) {
750         napi_value exports = nullptr;
751         napi_create_object(env, &exports);
752         PixelMapNapi::Init(env, exports);
753     }
754 
755     napi_value result = nullptr;
756     napi_get_undefined(env, &result);
757 
758     int32_t refCount = 1;
759 
760     napi_status status;
761     napi_value thisVar = nullptr;
762     napi_value argValue[NUM_4] = {0};
763     size_t argCount = NUM_4;
764     IMAGE_LOGD("CreatePixelMap IN");
765 
766     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
767 
768     // we are static method!
769     // thisVar is nullptr here
770     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
771     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
772 
773     status = napi_get_arraybuffer_info(env, argValue[NUM_0], &(asyncContext->colorsBuffer),
774         &(asyncContext->colorsBufferSize));
775 
776     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("colors mismatch"));
777 
778     IMG_NAPI_CHECK_RET_D(parseInitializationOptions(env, argValue[1], &(asyncContext->opts)),
779         nullptr, IMAGE_LOGE("InitializationOptions mismatch"));
780 
781     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
782         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
783     }
784 
785     if (asyncContext->callbackRef == nullptr) {
786         napi_create_promise(env, &(asyncContext->deferred), &result);
787     } else {
788         napi_get_undefined(env, &result);
789     }
790 
791     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePixelMap",
792         CreatePixelMapExec, CreatePixelMapComplete, asyncContext, asyncContext->work);
793 
794     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
795         nullptr, IMAGE_LOGE("fail to create async work"));
796     return result;
797 }
798 
799 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
STATIC_EXEC_FUNC(CreatePixelMapFromSurface)800 STATIC_EXEC_FUNC(CreatePixelMapFromSurface)
801 {
802     auto context = static_cast<PixelMapAsyncContext*>(data);
803     IMAGE_LOGD("CreatePixelMapFromSurface id:%{public}s,area:%{public}d,%{public}d,%{public}d,%{public}d",
804         context->surfaceId.c_str(), context->area.region.left, context->area.region.top,
805         context->area.region.height, context->area.region.width);
806 
807     auto pixelMap = CreatePixelMapFromSurfaceId(std::stoull(context->surfaceId), context->area.region);
808     context->rPixelMap = std::move(pixelMap);
809 
810     if (IMG_NOT_NULL(context->rPixelMap)) {
811         context->status = SUCCESS;
812     } else {
813         context->status = ERR_IMAGE_INVALID_PARAMETER;
814     }
815 }
816 
CreatePixelMapFromSurfaceComplete(napi_env env,napi_status status,void * data)817 void PixelMapNapi::CreatePixelMapFromSurfaceComplete(napi_env env, napi_status status, void *data)
818 {
819     napi_value constructor = nullptr;
820     napi_value result = nullptr;
821 
822     IMAGE_LOGD("CreatePixelMapFromSurface IN");
823     auto context = static_cast<PixelMapAsyncContext*>(data);
824     status = napi_get_reference_value(env, sConstructor_, &constructor);
825     if (IMG_IS_OK(status)) {
826         status = NewPixelNapiInstance(env, constructor, context->rPixelMap, result);
827     }
828 
829     if (!IMG_IS_OK(status)) {
830         context->status = ERR_IMAGE_PIXELMAP_CREATE_FAILED;
831         IMAGE_LOGE("New instance could not be obtained");
832         napi_get_undefined(env, &result);
833     }
834 
835     CommonCallbackRoutine(env, context, result);
836 }
837 
setSurfaceId(const char * surfaceId,std::string & dst)838 void setSurfaceId(const char *surfaceId, std::string &dst)
839 {
840     dst = surfaceId;
841 }
842 
GetStringArgument(napi_env env,napi_value value)843 static std::string GetStringArgument(napi_env env, napi_value value)
844 {
845     std::string strValue = "";
846     size_t bufLength = 0;
847     napi_status status = napi_get_value_string_utf8(env, value, nullptr, NUM_0, &bufLength);
848     if (status == napi_ok && bufLength > NUM_0 && bufLength < PATH_MAX) {
849         char *buffer = reinterpret_cast<char *>(malloc((bufLength + NUM_1) * sizeof(char)));
850         if (buffer == nullptr) {
851             IMAGE_LOGE("No memory");
852             return strValue;
853         }
854 
855         status = napi_get_value_string_utf8(env, value, buffer, bufLength + NUM_1, &bufLength);
856         if (status == napi_ok) {
857             IMAGE_LOGD("Get Success");
858             strValue.assign(buffer, 0, bufLength + NUM_1);
859         }
860         if (buffer != nullptr) {
861             free(buffer);
862             buffer = nullptr;
863         }
864     }
865     return strValue;
866 }
867 
CreatePixelMapFromSurface(napi_env env,napi_callback_info info)868 napi_value PixelMapNapi::CreatePixelMapFromSurface(napi_env env, napi_callback_info info)
869 {
870     napi_value globalValue;
871     napi_get_global(env, &globalValue);
872     napi_value func;
873     napi_get_named_property(env, globalValue, "requireNapi", &func);
874 
875     napi_value imageInfo;
876     napi_create_string_utf8(env, "multimedia.image", NAPI_AUTO_LENGTH, &imageInfo);
877     napi_value funcArgv[1] = { imageInfo };
878     napi_value returnValue;
879     napi_call_function(env, globalValue, func, 1, funcArgv, &returnValue);
880 
881     napi_value result = nullptr;
882     napi_get_undefined(env, &result);
883     int32_t refCount = 1;
884     napi_status status;
885     napi_value thisVar = nullptr;
886     napi_value argValue[NUM_4] = {0};
887     size_t argCount = NUM_4;
888     IMAGE_LOGD("CreatePixelMapFromSurface IN");
889     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
890     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
891     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
892     asyncContext->surfaceId = GetStringArgument(env, argValue[NUM_0]);
893     bool ret = parseRegion(env, argValue[NUM_1], &(asyncContext->area.region));
894     IMAGE_LOGD("CreatePixelMapFromSurface get data: %{public}d", ret);
895     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
896         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
897     }
898     if (asyncContext->callbackRef == nullptr) {
899         napi_create_promise(env, &(asyncContext->deferred), &result);
900     } else {
901         napi_get_undefined(env, &result);
902     }
903     IMG_NAPI_CHECK_BUILD_ERROR(ret,
904         BuildContextError(env, asyncContext->error, "image invalid parameter", ERR_IMAGE_GET_DATA_ABNORMAL),
905         IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePixelMapFromSurfaceGeneralError",
906         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
907         result);
908     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreatePixelMapFromSurface",
909         CreatePixelMapFromSurfaceExec, CreatePixelMapFromSurfaceComplete, asyncContext, asyncContext->work);
910     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
911         nullptr, IMAGE_LOGE("fail to create async work"));
912     return result;
913 }
914 #endif
915 
CreatePixelMap(napi_env env,std::shared_ptr<PixelMap> pixelmap)916 napi_value PixelMapNapi::CreatePixelMap(napi_env env, std::shared_ptr<PixelMap> pixelmap)
917 {
918     if (PixelMapNapi::GetConstructor() == nullptr) {
919         napi_value exports = nullptr;
920         napi_create_object(env, &exports);
921         PixelMapNapi::Init(env, exports);
922     }
923 
924     napi_value constructor = nullptr;
925     napi_value result = nullptr;
926     napi_status status;
927 
928     IMAGE_LOGD("CreatePixelMap IN");
929     status = napi_get_reference_value(env, sConstructor_, &constructor);
930 
931     if (IMG_IS_OK(status)) {
932         status = NewPixelNapiInstance(env, constructor, pixelmap, result);
933     }
934 
935     if (!IMG_IS_OK(status)) {
936         IMAGE_LOGE("CreatePixelMap | New instance could not be obtained");
937         napi_get_undefined(env, &result);
938     }
939 
940     return result;
941 }
942 
STATIC_EXEC_FUNC(Unmarshalling)943 STATIC_EXEC_FUNC(Unmarshalling)
944 {
945 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
946     auto context = static_cast<PixelMapAsyncContext*>(data);
947 
948     auto messageParcel = napi_messageSequence->GetMessageParcel();
949     auto pixelmap = PixelMap::Unmarshalling(*messageParcel);
950     std::unique_ptr<OHOS::Media::PixelMap> pixelmap_ptr(pixelmap);
951 
952     context->rPixelMap = std::move(pixelmap_ptr);
953 
954     if (IMG_NOT_NULL(context->rPixelMap)) {
955         context->status = SUCCESS;
956     } else {
957         context->status = ERROR;
958     }
959 #endif
960 }
961 
UnmarshallingComplete(napi_env env,napi_status status,void * data)962 void PixelMapNapi::UnmarshallingComplete(napi_env env, napi_status status, void *data)
963 {
964     napi_value constructor = nullptr;
965     napi_value result = nullptr;
966 
967     IMAGE_LOGD("UnmarshallingComplete IN");
968     auto context = static_cast<PixelMapAsyncContext*>(data);
969 
970     status = napi_get_reference_value(env, sConstructor_, &constructor);
971     if (IMG_IS_OK(status)) {
972         status = NewPixelNapiInstance(env, constructor, context->rPixelMap, result);
973     }
974 
975     if (!IMG_IS_OK(status)) {
976         context->status = ERROR;
977         IMAGE_LOGE("New instance could not be obtained");
978         napi_get_undefined(env, &result);
979     }
980 
981     CommonCallbackRoutine(env, context, result);
982 }
983 
Unmarshalling(napi_env env,napi_callback_info info)984 napi_value PixelMapNapi::Unmarshalling(napi_env env, napi_callback_info info)
985 {
986 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
987     if (PixelMapNapi::GetConstructor() == nullptr) {
988         napi_value exports = nullptr;
989         napi_create_object(env, &exports);
990         PixelMapNapi::Init(env, exports);
991     }
992     napi_value result = nullptr;
993     napi_get_undefined(env, &result);
994 
995     int32_t refCount = 1;
996 
997     napi_status status;
998     napi_value thisVar = nullptr;
999     napi_value argValue[NUM_4] = {0};
1000     size_t argCount = NUM_4;
1001     IMAGE_LOGD("Unmarshalling IN");
1002 
1003     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1004 
1005     // we are static method!
1006     // thisVar is nullptr here
1007     if (!IMG_IS_OK(status)) {
1008         return ImageNapiUtils::ThrowExceptionError(
1009             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to napi_get_cb_info");
1010     }
1011     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1012 
1013     if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1014         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1015     }
1016 
1017     napi_unwrap(env, argValue[NUM_0], (void **)&napi_messageSequence);
1018 
1019     if (asyncContext->callbackRef == nullptr) {
1020         napi_create_promise(env, &(asyncContext->deferred), &result);
1021     } else {
1022         napi_get_undefined(env, &result);
1023     }
1024 
1025     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "Unmarshalling",
1026         UnmarshallingExec, UnmarshallingComplete, asyncContext, asyncContext->work);
1027 
1028     if (!IMG_IS_OK(status)) {
1029         return ImageNapiUtils::ThrowExceptionError(
1030             env, ERROR, "Fail to create async work");
1031     }
1032     return result;
1033 #else
1034     napi_value result = nullptr;
1035     return result;
1036 #endif
1037 }
1038 
ThrowExceptionError(napi_env env,const std::string & tag,const std::uint32_t & code,const std::string & info)1039 napi_value PixelMapNapi::ThrowExceptionError(napi_env env,
1040     const std::string &tag, const std::uint32_t &code, const std::string &info)
1041 {
1042     auto errNode = ETS_API_ERROR_CODE.find(tag);
1043     if (errNode != ETS_API_ERROR_CODE.end() &&
1044         errNode->second.find(code) != errNode->second.end()) {
1045         return ImageNapiUtils::ThrowExceptionError(env, code, info);
1046     }
1047     return ImageNapiUtils::ThrowExceptionError(env, ERROR, "Operation failed");
1048 }
1049 
CreatePixelMapFromParcel(napi_env env,napi_callback_info info)1050 napi_value PixelMapNapi::CreatePixelMapFromParcel(napi_env env, napi_callback_info info)
1051 #if defined(IOS_PLATFORM) || defined(A_PLATFORM)
1052 {
1053     napi_value result = nullptr;
1054     return result;
1055 }
1056 #else
1057 {
1058     if (PixelMapNapi::GetConstructor() == nullptr) {
1059         napi_value exports = nullptr;
1060         napi_create_object(env, &exports);
1061         PixelMapNapi::Init(env, exports);
1062     }
1063     napi_value result = nullptr;
1064     napi_get_undefined(env, &result);
1065     napi_status status;
1066     napi_value thisVar = nullptr;
1067     napi_value argValue[NUM_1] = {0};
1068     size_t argCount = NUM_1;
1069     IMAGE_LOGD("CreatePixelMapFromParcel IN");
1070     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1071     if (!IMG_IS_OK(status) || argCount != NUM_1) {
1072         return PixelMapNapi::ThrowExceptionError(env,
1073             CREATE_PIXEL_MAP_FROM_PARCEL, ERR_IMAGE_INVALID_PARAMETER, "Fail to napi_get_cb_info");
1074     }
1075     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1076     napi_unwrap(env, argValue[NUM_0], (void **)&napi_messageSequence);
1077     auto messageParcel = napi_messageSequence->GetMessageParcel();
1078     if (messageParcel == nullptr) {
1079         return PixelMapNapi::ThrowExceptionError(env,
1080             CREATE_PIXEL_MAP_FROM_PARCEL, ERR_IPC, "get pacel failed");
1081     }
1082     PIXEL_MAP_ERR error;
1083     auto pixelmap = PixelMap::Unmarshalling(*messageParcel, error);
1084     if (!IMG_NOT_NULL(pixelmap)) {
1085         return PixelMapNapi::ThrowExceptionError(env,
1086             CREATE_PIXEL_MAP_FROM_PARCEL, error.errorCode, error.errorInfo);
1087     }
1088     std::shared_ptr<OHOS::Media::PixelMap> pixelPtr(pixelmap);
1089     napi_value constructor = nullptr;
1090     status = napi_get_reference_value(env, sConstructor_, &constructor);
1091     if (IMG_IS_OK(status)) {
1092         status = NewPixelNapiInstance(env, constructor, pixelPtr, result);
1093     }
1094     if (!IMG_IS_OK(status)) {
1095         IMAGE_LOGE("New instance could not be obtained");
1096         return PixelMapNapi::ThrowExceptionError(env,
1097             CREATE_PIXEL_MAP_FROM_PARCEL, ERR_IMAGE_NAPI_ERROR, "New instance could not be obtained");
1098     }
1099     return result;
1100 }
1101 #endif
1102 
GetIsEditable(napi_env env,napi_callback_info info)1103 napi_value PixelMapNapi::GetIsEditable(napi_env env, napi_callback_info info)
1104 {
1105     napi_value result = nullptr;
1106     napi_get_undefined(env, &result);
1107 
1108     napi_status status;
1109     napi_value thisVar = nullptr;
1110     size_t argCount = 0;
1111     IMAGE_LOGD("GetIsEditable IN");
1112 
1113     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1114 
1115     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1116 
1117     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
1118     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1119 
1120     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1121 
1122     if (pixelMapNapi->nativePixelMap_ == nullptr) {
1123         return result;
1124     }
1125     bool isEditable = pixelMapNapi->nativePixelMap_->IsEditable();
1126 
1127     napi_get_boolean(env, isEditable, &result);
1128     pixelMapNapi.release();
1129 
1130     return result;
1131 }
1132 
GetIsStrideAlignment(napi_env env,napi_callback_info info)1133 napi_value PixelMapNapi::GetIsStrideAlignment(napi_env env, napi_callback_info info)
1134 {
1135     napi_value result = nullptr;
1136     napi_get_undefined(env, &result);
1137 
1138     napi_status status;
1139     napi_value thisVar = nullptr;
1140     size_t argCount = 0;
1141     IMAGE_LOGD("GetIsStrideAlignment IN");
1142 
1143     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1144 
1145     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1146 
1147     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
1148     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1149 
1150     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi),
1151         result, IMAGE_LOGE("fail to unwrap context"));
1152 
1153     if (pixelMapNapi->nativePixelMap_ == nullptr) {
1154         return result;
1155     }
1156     bool isDMA = pixelMapNapi->nativePixelMap_->IsStrideAlignment();
1157     napi_get_boolean(env, isDMA, &result);
1158     pixelMapNapi.release();
1159     return result;
1160 }
1161 
ReadPixelsToBuffer(napi_env env,napi_callback_info info)1162 napi_value PixelMapNapi::ReadPixelsToBuffer(napi_env env, napi_callback_info info)
1163 {
1164     ImageTrace imageTrace("PixelMapNapi::ReadPixelsToBuffer");
1165     napi_value result = nullptr;
1166     napi_get_undefined(env, &result);
1167 
1168     int32_t refCount = 1;
1169     napi_status status;
1170     napi_value thisVar = nullptr;
1171     napi_value argValue[NUM_2] = {0};
1172     size_t argCount = NUM_2;
1173 
1174     IMAGE_LOGD("ReadPixelsToBuffer IN");
1175     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1176 
1177     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1178 
1179     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1180     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1181 
1182     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1183         nullptr, IMAGE_LOGE("fail to unwrap context"));
1184     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1185 
1186     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1187         nullptr, IMAGE_LOGE("empty native pixelmap"));
1188 
1189     status = napi_get_arraybuffer_info(env, argValue[NUM_0],
1190             &(asyncContext->colorsBuffer), &(asyncContext->colorsBufferSize));
1191 
1192     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("colors mismatch"));
1193 
1194     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1195         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1196     }
1197 
1198     if (asyncContext->callbackRef == nullptr) {
1199         napi_create_promise(env, &(asyncContext->deferred), &result);
1200     } else {
1201         napi_get_undefined(env, &result);
1202     }
1203 
1204     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1205         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . ReadPixelsToBuffer failed",
1206         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ReadPixelsToBufferGeneralError",
1207         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1208         result);
1209     IMG_CREATE_CREATE_ASYNC_WORK_WITH_QOS(env, status, "ReadPixelsToBuffer",
1210         [](napi_env env, void *data)
1211         {
1212             auto context = static_cast<PixelMapAsyncContext*>(data);
1213             context->status = context->rPixelMap->ReadPixels(
1214                 context->colorsBufferSize, static_cast<uint8_t*>(context->colorsBuffer));
1215         }, EmptyResultComplete, asyncContext, asyncContext->work, napi_qos_user_initiated);
1216 
1217     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1218         nullptr, IMAGE_LOGE("fail to create async work"));
1219     return result;
1220 }
1221 
ReadPixels(napi_env env,napi_callback_info info)1222 napi_value PixelMapNapi::ReadPixels(napi_env env, napi_callback_info info)
1223 {
1224     napi_value result = nullptr;
1225     napi_get_undefined(env, &result);
1226 
1227     int32_t refCount = 1;
1228     napi_status status;
1229     napi_value thisVar = nullptr;
1230     napi_value argValue[NUM_2] = {0};
1231     size_t argCount = NUM_2;
1232 
1233     IMAGE_LOGD("ReadPixels IN");
1234     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1235 
1236     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1237 
1238     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1239     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1240 
1241     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1242         nullptr, IMAGE_LOGE("fail to unwrap context"));
1243 
1244     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1245 
1246     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1247         nullptr, IMAGE_LOGE("empty native pixelmap"));
1248 
1249     IMG_NAPI_CHECK_RET_D(parsePositionArea(env, argValue[NUM_0], &(asyncContext->area)),
1250         nullptr, IMAGE_LOGE("fail to parse position area"));
1251 
1252     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1253         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1254     }
1255 
1256     if (asyncContext->callbackRef == nullptr) {
1257         napi_create_promise(env, &(asyncContext->deferred), &result);
1258     } else {
1259         napi_get_undefined(env, &result);
1260     }
1261 
1262     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1263         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . ReadPixels failed",
1264         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ReadPixelsGeneralError",
1265         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1266         result);
1267     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ReadPixels",
1268         [](napi_env env, void *data)
1269         {
1270             auto context = static_cast<PixelMapAsyncContext*>(data);
1271             auto area = context->area;
1272             context->status = context->rPixelMap->ReadPixels(
1273                 area.size, area.offset, area.stride, area.region, static_cast<uint8_t*>(area.pixels));
1274         }, EmptyResultComplete, asyncContext, asyncContext->work);
1275 
1276     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1277         nullptr, IMAGE_LOGE("fail to create async work"));
1278     return result;
1279 }
1280 
WritePixels(napi_env env,napi_callback_info info)1281 napi_value PixelMapNapi::WritePixels(napi_env env, napi_callback_info info)
1282 {
1283     napi_value result = nullptr;
1284     napi_get_undefined(env, &result);
1285 
1286     int32_t refCount = 1;
1287     napi_status status;
1288     napi_value thisVar = nullptr;
1289     napi_value argValue[NUM_2] = {0};
1290     size_t argCount = NUM_2;
1291 
1292     IMAGE_LOGD("WritePixels IN");
1293     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1294 
1295     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1296 
1297     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1298     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1299 
1300     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1301         nullptr, IMAGE_LOGE("fail to unwrap context"));
1302     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1303 
1304     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1305         nullptr, IMAGE_LOGE("empty native pixelmap"));
1306 
1307     IMG_NAPI_CHECK_RET_D(parsePositionArea(env, argValue[NUM_0], &(asyncContext->area)),
1308         nullptr, IMAGE_LOGE("fail to parse position area"));
1309 
1310     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1311         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1312     }
1313 
1314     if (asyncContext->callbackRef == nullptr) {
1315         napi_create_promise(env, &(asyncContext->deferred), &result);
1316     } else {
1317         napi_get_undefined(env, &result);
1318     }
1319     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1320         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . WritePixels failed",
1321         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WritePixelsGeneralError",
1322         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1323         result);
1324     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WritePixels",
1325         [](napi_env env, void *data)
1326         {
1327             auto context = static_cast<PixelMapAsyncContext*>(data);
1328             auto area = context->area;
1329             context->status = context->rPixelMap->WritePixels(
1330                 static_cast<uint8_t*>(area.pixels), area.size, area.offset, area.stride, area.region);
1331         }, EmptyResultComplete, asyncContext, asyncContext->work);
1332 
1333     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1334         nullptr, IMAGE_LOGE("fail to create async work"));
1335     return result;
1336 }
1337 
WriteBufferToPixels(napi_env env,napi_callback_info info)1338 napi_value PixelMapNapi::WriteBufferToPixels(napi_env env, napi_callback_info info)
1339 {
1340     ImageTrace imageTrace("PixelMapNapi::WriteBufferToPixels");
1341     napi_value result = nullptr;
1342     napi_get_undefined(env, &result);
1343 
1344     int32_t refCount = 1;
1345     napi_status status;
1346     napi_value thisVar = nullptr;
1347     napi_value argValue[NUM_2] = {0};
1348     size_t argCount = NUM_2;
1349 
1350     IMAGE_LOGD("WriteBufferToPixels IN");
1351     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1352 
1353     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1354 
1355     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1356     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1357 
1358     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1359         nullptr, IMAGE_LOGE("fail to unwrap context"));
1360     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1361 
1362     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1363         nullptr, IMAGE_LOGE("empty native pixelmap"));
1364     status = napi_get_arraybuffer_info(env, argValue[NUM_0],
1365         &(asyncContext->colorsBuffer), &(asyncContext->colorsBufferSize));
1366 
1367     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1368         nullptr, IMAGE_LOGE("fail to get buffer info"));
1369 
1370     if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1371         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1372     }
1373 
1374     if (asyncContext->callbackRef == nullptr) {
1375         napi_create_promise(env, &(asyncContext->deferred), &result);
1376     } else {
1377         napi_get_undefined(env, &result);
1378     }
1379     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1380         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . WriteBufferToPixels failed",
1381         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WriteBufferToPixelsGeneralError",
1382         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1383         result);
1384     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "WriteBufferToPixels",
1385         [](napi_env env, void *data)
1386         {
1387             auto context = static_cast<PixelMapAsyncContext*>(data);
1388             context->status = context->rPixelMap->WritePixels(static_cast<uint8_t*>(context->colorsBuffer),
1389                 context->colorsBufferSize);
1390         }, EmptyResultComplete, asyncContext, asyncContext->work);
1391 
1392     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1393         nullptr, IMAGE_LOGE("fail to create async work"));
1394     return result;
1395 }
1396 
STATIC_COMPLETE_FUNC(GetImageInfo)1397 STATIC_COMPLETE_FUNC(GetImageInfo)
1398 {
1399     IMAGE_LOGD("[PixelMap]GetImageInfoComplete IN");
1400     napi_value result = nullptr;
1401     napi_create_object(env, &result);
1402     auto context = static_cast<PixelMapAsyncContext*>(data);
1403     napi_value size = nullptr;
1404     napi_create_object(env, &size);
1405     napi_value sizeWith = nullptr;
1406     napi_create_int32(env, context->imageInfo.size.width, &sizeWith);
1407     napi_set_named_property(env, size, "width", sizeWith);
1408     napi_value sizeHeight = nullptr;
1409     napi_create_int32(env, context->imageInfo.size.height, &sizeHeight);
1410     napi_set_named_property(env, size, "height", sizeHeight);
1411     napi_set_named_property(env, result, "size", size);
1412     napi_value pixelFormatValue = nullptr;
1413     napi_create_int32(env, static_cast<int32_t>(context->imageInfo.pixelFormat), &pixelFormatValue);
1414     napi_set_named_property(env, result, "pixelFormat", pixelFormatValue);
1415     napi_value colorSpaceValue = nullptr;
1416     napi_create_int32(env, static_cast<int32_t>(context->imageInfo.colorSpace), &colorSpaceValue);
1417     napi_set_named_property(env, result, "colorSpace", colorSpaceValue);
1418     napi_value alphaTypeValue = nullptr;
1419     napi_create_int32(env, static_cast<int32_t>(context->imageInfo.alphaType), &alphaTypeValue);
1420     napi_set_named_property(env, result, "alphaType", alphaTypeValue);
1421     napi_value densityValue = nullptr;
1422     napi_create_int32(env, static_cast<int32_t>(context->imageInfo.baseDensity), &densityValue);
1423     napi_set_named_property(env, result, "density", densityValue);
1424     napi_value strideValue = nullptr;
1425     napi_create_int32(env, static_cast<int32_t>(context->rPixelMap->GetRowStride()), &strideValue);
1426     napi_set_named_property(env, result, "stride", strideValue);
1427     if (!IMG_IS_OK(status)) {
1428         context->status = ERROR;
1429         IMAGE_LOGE("napi_create_int32 failed!");
1430         napi_get_undefined(env, &result);
1431     } else {
1432         context->status = SUCCESS;
1433     }
1434     IMAGE_LOGD("[PixelMap]GetImageInfoComplete OUT");
1435     CommonCallbackRoutine(env, context, result);
1436 }
GetImageInfo(napi_env env,napi_callback_info info)1437 napi_value PixelMapNapi::GetImageInfo(napi_env env, napi_callback_info info)
1438 {
1439     napi_value result = nullptr;
1440     napi_get_undefined(env, &result);
1441     int32_t refCount = 1;
1442     napi_status status;
1443     napi_value thisVar = nullptr;
1444     napi_value argValue[NUM_1] = {0};
1445     size_t argCount = 1;
1446     IMAGE_LOGD("GetImageInfo IN");
1447     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1448     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1449     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1450     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1451     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1452         nullptr, IMAGE_LOGE("fail to unwrap context"));
1453     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1454     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1455         nullptr, IMAGE_LOGE("empty native pixelmap"));
1456     if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1457         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1458     }
1459     if (asyncContext->callbackRef == nullptr) {
1460         napi_create_promise(env, &(asyncContext->deferred), &result);
1461     } else {
1462         napi_get_undefined(env, &result);
1463     }
1464     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1465         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . GetImageInfo failed",
1466         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageInfoGeneralError",
1467         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1468         result);
1469     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageInfo",
1470         [](napi_env env, void *data)
1471         {
1472             auto context = static_cast<PixelMapAsyncContext*>(data);
1473             context->rPixelMap->GetImageInfo(context->imageInfo);
1474             context->status = SUCCESS;
1475         }, GetImageInfoComplete, asyncContext, asyncContext->work);
1476     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1477         nullptr, IMAGE_LOGE("fail to create async work"));
1478     return result;
1479 }
1480 
GetBytesNumberPerRow(napi_env env,napi_callback_info info)1481 napi_value PixelMapNapi::GetBytesNumberPerRow(napi_env env, napi_callback_info info)
1482 {
1483     ImageTrace imageTrace("PixelMapNapi::GetBytesNumberPerRow");
1484     napi_value result = nullptr;
1485     napi_get_undefined(env, &result);
1486 
1487     napi_status status;
1488     napi_value thisVar = nullptr;
1489     size_t argCount = 0;
1490 
1491     IMAGE_LOGD("GetBytesNumberPerRow IN");
1492     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1493 
1494     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1495 
1496     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
1497     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1498 
1499     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1500     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1501         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1502         "Pixelmap has crossed threads . GetBytesNumberPerRow failed"),
1503         IMAGE_LOGE("Pixelmap has crossed threads . GetBytesNumberPerRow failed"));
1504 
1505     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1506         uint32_t rowBytes = pixelMapNapi->nativePixelMap_->GetRowBytes();
1507         status = napi_create_int32(env, rowBytes, &result);
1508         if (!IMG_IS_OK(status)) {
1509             IMAGE_LOGE("napi_create_int32 failed!");
1510         }
1511     } else {
1512         IMAGE_LOGE("native pixelmap is nullptr!");
1513     }
1514     pixelMapNapi.release();
1515     return result;
1516 }
1517 
GetPixelBytesNumber(napi_env env,napi_callback_info info)1518 napi_value PixelMapNapi::GetPixelBytesNumber(napi_env env, napi_callback_info info)
1519 {
1520     ImageTrace imageTrace("PixelMapNapi::GetPixelBytesNumber");
1521     napi_value result = nullptr;
1522     napi_get_undefined(env, &result);
1523 
1524     napi_status status;
1525     napi_value thisVar = nullptr;
1526     size_t argCount = 0;
1527 
1528     IMAGE_LOGD("GetPixelBytesNumber IN");
1529     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1530 
1531     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1532 
1533     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
1534     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1535 
1536     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1537     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1538         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1539         "Pixelmap has crossed threads . GetPixelBytesNumber failed"),
1540         IMAGE_LOGE("Pixelmap has crossed threads . GetPixelBytesNumber failed"));
1541 
1542     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1543         uint32_t byteCount = pixelMapNapi->nativePixelMap_->GetByteCount();
1544         status = napi_create_int32(env, byteCount, &result);
1545         if (!IMG_IS_OK(status)) {
1546             IMAGE_LOGE("napi_create_int32 failed!");
1547         }
1548     } else {
1549         IMAGE_LOGE("native pixelmap is nullptr!");
1550     }
1551     pixelMapNapi.release();
1552     return result;
1553 }
1554 
IsSupportAlpha(napi_env env,napi_callback_info info)1555 napi_value PixelMapNapi::IsSupportAlpha(napi_env env, napi_callback_info info)
1556 {
1557     napi_value result = nullptr;
1558     napi_get_undefined(env, &result);
1559 
1560     napi_status status;
1561     napi_value thisVar = nullptr;
1562     size_t argCount = NUM_0;
1563 
1564     IMAGE_LOGD("IsSupportAlpha IN");
1565     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1566 
1567     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1568 
1569     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
1570     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1571 
1572     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1573     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1574         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1575         "Pixelmap has crossed threads . IsSupportAlpha failed"),
1576         IMAGE_LOGE("Pixelmap has crossed threads . IsSupportAlpha failed"));
1577 
1578     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1579         AlphaType alphaType = pixelMapNapi->nativePixelMap_->GetAlphaType();
1580         bool isSupportAlpha = !(alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
1581         status = napi_get_boolean(env, isSupportAlpha, &result);
1582         if (!IMG_IS_OK(status)) {
1583             IMAGE_LOGE("napi_create_bool failed!");
1584         }
1585     } else {
1586         IMAGE_LOGE("native pixelmap is nullptr!");
1587     }
1588     pixelMapNapi.release();
1589     return result;
1590 }
1591 
SetAlphaAble(napi_env env,napi_callback_info info)1592 napi_value PixelMapNapi::SetAlphaAble(napi_env env, napi_callback_info info)
1593 {
1594     napi_value result = nullptr;
1595     napi_get_undefined(env, &result);
1596 
1597     napi_status status;
1598     napi_value thisVar = nullptr;
1599     napi_value argValue[NUM_1] = {0};
1600     size_t argCount = NUM_1;
1601     bool isAlphaAble = false;
1602 
1603     IMAGE_LOGD("SetAlphaAble IN");
1604     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1605 
1606     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1607     NAPI_ASSERT(env, argCount > NUM_0, "Invalid input");
1608     NAPI_ASSERT(env, ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_boolean, "Invalid input type");
1609     NAPI_ASSERT(env, napi_get_value_bool(env, argValue[NUM_0], &isAlphaAble) == napi_ok, "Parse input error");
1610 
1611     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
1612     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1613 
1614     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1615     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1616         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1617         "Pixelmap has crossed threads . SetAlphaAble failed"),
1618         IMAGE_LOGE("Pixelmap has crossed threads . SetAlphaAble failed"));
1619     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1620         AlphaType alphaType = pixelMapNapi->nativePixelMap_->GetAlphaType();
1621         if (isAlphaAble && (alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
1622             pixelMapNapi->nativePixelMap_->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_PREMUL);
1623         } else if ((!isAlphaAble) && !(alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE)) {
1624             pixelMapNapi->nativePixelMap_->SetAlphaType(AlphaType::IMAGE_ALPHA_TYPE_OPAQUE);
1625         }
1626     } else {
1627         IMAGE_LOGE("native pixelmap is nullptr!");
1628     }
1629     pixelMapNapi.release();
1630     return result;
1631 }
1632 
CreateAlphaPixelmapComplete(napi_env env,napi_status status,void * data)1633 static void CreateAlphaPixelmapComplete(napi_env env, napi_status status, void *data)
1634 {
1635     napi_value result = nullptr;
1636     napi_get_undefined(env, &result);
1637     auto context = static_cast<PixelMapAsyncContext*>(data);
1638 
1639     if (context->alphaMap != nullptr) {
1640         result = PixelMapNapi::CreatePixelMap(env, context->alphaMap);
1641         context->status = SUCCESS;
1642     } else {
1643         context->status = ERROR;
1644     }
1645     CommonCallbackRoutine(env, context, result);
1646 }
1647 
CreateAlphaPixelmap(napi_env env,napi_callback_info info)1648 napi_value PixelMapNapi::CreateAlphaPixelmap(napi_env env, napi_callback_info info)
1649 {
1650     napi_value result = nullptr;
1651     napi_get_undefined(env, &result);
1652     int32_t refCount = 1;
1653     napi_status status;
1654     napi_value thisVar = nullptr;
1655     napi_value argValue[NUM_1] = {0};
1656     size_t argCount = 1;
1657     IMAGE_LOGD("CreateAlphaPixelmap IN");
1658     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1659     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1660     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1661     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1662     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1663         nullptr, IMAGE_LOGE("fail to unwrap context"));
1664     asyncContext->rPixelMap = asyncContext->nConstructor->nativePixelMap_;
1665     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPixelMap),
1666         nullptr, IMAGE_LOGE("empty native pixelmap"));
1667     if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1668         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1669     }
1670     if (asyncContext->callbackRef == nullptr) {
1671         napi_create_promise(env, &(asyncContext->deferred), &result);
1672     } else {
1673         napi_get_undefined(env, &result);
1674     }
1675     IMG_NAPI_CHECK_BUILD_ERROR(asyncContext->nConstructor->GetPixelNapiEditable(),
1676         BuildContextError(env, asyncContext->error, "pixelmap has crossed threads . CreateAlphaPixelmap failed",
1677         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateAlphaPixelmapGeneralError",
1678         [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work),
1679         result);
1680     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateAlphaPixelmap",
1681         [](napi_env env, void *data)
1682         {
1683             auto context = static_cast<PixelMapAsyncContext*>(data);
1684             InitializationOptions opts;
1685             opts.pixelFormat = PixelFormat::ALPHA_8;
1686             auto tmpPixelMap = PixelMap::Create(*(context->rPixelMap), opts);
1687             context->alphaMap = std::move(tmpPixelMap);
1688             context->status = SUCCESS;
1689         }, CreateAlphaPixelmapComplete, asyncContext, asyncContext->work);
1690     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1691         nullptr, IMAGE_LOGE("fail to create async work"));
1692     return result;
1693 }
1694 
GetDensity(napi_env env,napi_callback_info info)1695 napi_value PixelMapNapi::GetDensity(napi_env env, napi_callback_info info)
1696 {
1697     napi_value result = nullptr;
1698     napi_get_undefined(env, &result);
1699 
1700     napi_status status;
1701     napi_value thisVar = nullptr;
1702     size_t argCount = 0;
1703 
1704     IMAGE_LOGD("GetDensity IN");
1705     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
1706 
1707     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1708 
1709     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
1710     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1711 
1712     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1713     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1714         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1715         "Pixelmap has crossed threads . GetDensity failed"),
1716         IMAGE_LOGE("Pixelmap has crossed threads . GetDensity failed"));
1717 
1718     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1719         uint32_t baseDensity = pixelMapNapi->nativePixelMap_->GetBaseDensity();
1720         status = napi_create_int32(env, baseDensity, &result);
1721         if (!IMG_IS_OK(status)) {
1722             IMAGE_LOGE("napi_create_int32 failed!");
1723         }
1724     } else {
1725         IMAGE_LOGE("native pixelmap is nullptr!");
1726     }
1727     pixelMapNapi.release();
1728     return result;
1729 }
1730 
SetDensity(napi_env env,napi_callback_info info)1731 napi_value PixelMapNapi::SetDensity(napi_env env, napi_callback_info info)
1732 {
1733     napi_value result = nullptr;
1734     napi_get_undefined(env, &result);
1735 
1736     napi_status status;
1737     napi_value thisVar = nullptr;
1738     napi_value argValue[NUM_1] = {0};
1739     size_t argCount = NUM_1;
1740     uint32_t density = 0;
1741 
1742     IMAGE_LOGD("SetDensity IN");
1743     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1744     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
1745 
1746     NAPI_ASSERT(env,
1747         (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_number),
1748         "Density input mismatch");
1749     NAPI_ASSERT(env, napi_get_value_uint32(env, argValue[NUM_0], &density) == napi_ok, "Could not parse density");
1750 
1751     std::unique_ptr<PixelMapNapi> pixelMapNapi = nullptr;
1752     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi));
1753 
1754     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pixelMapNapi), result, IMAGE_LOGE("fail to unwrap context"));
1755     IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(),
1756         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
1757         "Pixelmap has crossed threads . SetDensity failed"),
1758         IMAGE_LOGE("Pixelmap has crossed threads . SetDensity failed"));
1759     if (pixelMapNapi->nativePixelMap_ != nullptr) {
1760         ImageInfo imageinfo;
1761         pixelMapNapi->nativePixelMap_->GetImageInfo(imageinfo);
1762         imageinfo.baseDensity = density;
1763         pixelMapNapi->nativePixelMap_->SetImageInfo(imageinfo, true);
1764     } else {
1765         IMAGE_LOGE("native pixelmap is nullptr!");
1766     }
1767     pixelMapNapi.release();
1768     return result;
1769 }
1770 
Release(napi_env env,napi_callback_info info)1771 napi_value PixelMapNapi::Release(napi_env env, napi_callback_info info)
1772 {
1773     napi_value result = nullptr;
1774     napi_get_undefined(env, &result);
1775 
1776     int32_t refCount = 1;
1777     napi_status status;
1778     napi_value thisVar = nullptr;
1779     napi_value argValue[1] = {0};
1780     size_t argCount = 1;
1781 
1782     IMAGE_LOGD("Release IN");
1783     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1784 
1785     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1786 
1787     std::unique_ptr<PixelMapAsyncContext> asyncContext = std::make_unique<PixelMapAsyncContext>();
1788     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
1789 
1790     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
1791         nullptr, IMAGE_LOGE("fail to unwrap context"));
1792 
1793     if (argCount == 1 && ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1794         napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1795     }
1796 
1797     if (asyncContext->callbackRef == nullptr) {
1798         napi_create_promise(env, &(asyncContext->deferred), &result);
1799     } else {
1800         napi_get_undefined(env, &result);
1801     }
1802     if (asyncContext->nConstructor->IsLockPixelMap()) {
1803         asyncContext->status = ERROR;
1804     } else {
1805         if (asyncContext->nConstructor->nativePixelMap_ != nullptr) {
1806             IMAGE_LOGD("Release in napi_id:%{public}d, id:%{public}d",
1807                 asyncContext->nConstructor->GetUniqueId(),
1808                 asyncContext->nConstructor->nativePixelMap_->GetUniqueId());
1809             asyncContext->nConstructor->nativePixelMap_.reset();
1810         }
1811         asyncContext->status = SUCCESS;
1812     }
1813     IMG_CREATE_CREATE_ASYNC_WORK_WITH_QOS(env, status, "Release",
1814         [](napi_env env, void *data)
1815         {
1816             uint32_t executeId = static_cast<uint32_t>(ImageNapiUtils::GetNowTimeMicroSeconds());
1817             IMAGE_LOGI("PixelMap Release, id: %{public}u", executeId);
1818         }, EmptyResultComplete, asyncContext, asyncContext->work, napi_qos_user_initiated);
1819 
1820     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1821         nullptr, IMAGE_LOGE("fail to create async work"));
1822     return result;
1823 }
1824 
1825 struct NapiValues {
1826     napi_status status;
1827     napi_value thisVar = nullptr;
1828     napi_value result = nullptr;
1829     napi_value* argv = nullptr;
1830     size_t argc;
1831     int32_t refCount = 1;
1832     std::unique_ptr<PixelMapAsyncContext> context;
1833 };
1834 
prepareNapiEnv(napi_env env,napi_callback_info info,struct NapiValues * nVal)1835 static bool prepareNapiEnv(napi_env env, napi_callback_info info, struct NapiValues* nVal)
1836 {
1837     napi_get_undefined(env, &(nVal->result));
1838     nVal->status = napi_get_cb_info(env, info, &(nVal->argc), nVal->argv, &(nVal->thisVar), nullptr);
1839     if (nVal->status != napi_ok) {
1840         IMAGE_LOGE("fail to napi_get_cb_info");
1841         return false;
1842     }
1843     nVal->context = std::make_unique<PixelMapAsyncContext>();
1844     nVal->status = napi_unwrap(env, nVal->thisVar, reinterpret_cast<void**>(&(nVal->context->nConstructor)));
1845     if (nVal->status != napi_ok) {
1846         IMAGE_LOGE("fail to unwrap context");
1847         return false;
1848     }
1849     nVal->context->status = SUCCESS;
1850     return true;
1851 }
1852 
SetAlphaExec(napi_env env,PixelMapAsyncContext * context)1853 static void SetAlphaExec(napi_env env, PixelMapAsyncContext* context)
1854 {
1855     if (context == nullptr) {
1856         IMAGE_LOGE("Null context");
1857         return;
1858     }
1859     if (context->status == SUCCESS) {
1860         if (context->rPixelMap != nullptr) {
1861             context->status = context->rPixelMap->SetAlpha(
1862                 static_cast<float>(context->alpha));
1863         } else {
1864             IMAGE_LOGE("Null native ref");
1865             context->status = ERR_IMAGE_INIT_ABNORMAL;
1866         }
1867     } else {
1868         IMAGE_LOGD("Scale has failed. do nothing");
1869     }
1870 }
1871 
SetAlpha(napi_env env,napi_callback_info info)1872 napi_value PixelMapNapi::SetAlpha(napi_env env, napi_callback_info info)
1873 {
1874     NapiValues nVal;
1875     nVal.argc = NUM_2;
1876     napi_value argValue[NUM_2] = {0};
1877     nVal.argv = argValue;
1878 
1879     IMAGE_LOGD("SetAlpha IN");
1880     if (!prepareNapiEnv(env, info, &nVal)) {
1881         return nVal.result;
1882     }
1883     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
1884 
1885     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
1886         IMAGE_LOGE("Invalid args count %{public}zu", nVal.argc);
1887         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
1888     } else {
1889         if (napi_ok !=
1890             napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->alpha))) {
1891             IMAGE_LOGE("Arg 0 type mismatch");
1892             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
1893         }
1894     }
1895     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
1896         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
1897     }
1898 
1899     if (nVal.context->callbackRef == nullptr) {
1900         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
1901     }
1902     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
1903         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . SetAlpha failed",
1904         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "SetAlphaGeneralError",
1905         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
1906         nVal.result);
1907     napi_value _resource = nullptr;
1908     napi_create_string_utf8(env, "SetAlpha", NAPI_AUTO_LENGTH, &_resource);
1909     nVal.status = napi_create_async_work(env, nullptr, _resource,
1910         [](napi_env env, void *data)
1911         {
1912             auto context = static_cast<PixelMapAsyncContext*>(data);
1913             SetAlphaExec(env, context);
1914         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
1915 
1916     if (nVal.status == napi_ok) {
1917         nVal.status = napi_queue_async_work(env, nVal.context->work);
1918         if (nVal.status == napi_ok) {
1919             nVal.context.release();
1920         }
1921     }
1922     return nVal.result;
1923 }
1924 
ScaleExec(napi_env env,PixelMapAsyncContext * context)1925 static void ScaleExec(napi_env env, PixelMapAsyncContext* context)
1926 {
1927     if (context == nullptr) {
1928         IMAGE_LOGE("Null context");
1929         return;
1930     }
1931     if (context->status == SUCCESS) {
1932         if (context->rPixelMap != nullptr) {
1933             context->rPixelMap->scale(static_cast<float>(context->xArg), static_cast<float>(context->yArg));
1934             context->status = SUCCESS;
1935         } else {
1936             IMAGE_LOGE("Null native ref");
1937             context->status = ERR_IMAGE_INIT_ABNORMAL;
1938         }
1939     } else {
1940         IMAGE_LOGD("Scale has failed. do nothing");
1941     }
1942 }
1943 
Scale(napi_env env,napi_callback_info info)1944 napi_value PixelMapNapi::Scale(napi_env env, napi_callback_info info)
1945 {
1946     NapiValues nVal;
1947     nVal.argc = NUM_3;
1948     napi_value argValue[NUM_3] = {0};
1949     nVal.argv = argValue;
1950     IMAGE_LOGD("Scale IN");
1951     if (!prepareNapiEnv(env, info, &nVal)) {
1952         return nVal.result;
1953     }
1954     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
1955 
1956     if (nVal.argc != NUM_2 && nVal.argc != NUM_3) {
1957         IMAGE_LOGE("Invalid args count %{public}zu", nVal.argc);
1958         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
1959     } else {
1960         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->xArg))) {
1961             IMAGE_LOGE("Arg 0 type mismatch");
1962             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
1963         }
1964         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_1], &(nVal.context->yArg))) {
1965             IMAGE_LOGE("Arg 1 type mismatch");
1966             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
1967         }
1968     }
1969     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
1970         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
1971     }
1972 
1973     if (nVal.context->callbackRef == nullptr) {
1974         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
1975     }
1976     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
1977         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Scale failed",
1978         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "ScaleGeneralError",
1979         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
1980         nVal.result);
1981     napi_value _resource = nullptr;
1982     napi_create_string_utf8(env, "Scale", NAPI_AUTO_LENGTH, &_resource);
1983     nVal.status = napi_create_async_work(env, nullptr, _resource,
1984         [](napi_env env, void *data)
1985         {
1986             auto context = static_cast<PixelMapAsyncContext*>(data);
1987             ScaleExec(env, context);
1988         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
1989 
1990     if (nVal.status == napi_ok) {
1991         nVal.status = napi_queue_async_work_with_qos(env, nVal.context->work, napi_qos_user_initiated);
1992         if (nVal.status == napi_ok) {
1993             nVal.context.release();
1994         }
1995     }
1996     return nVal.result;
1997 }
1998 
TranslateExec(napi_env env,PixelMapAsyncContext * context)1999 static void TranslateExec(napi_env env, PixelMapAsyncContext* context)
2000 {
2001     if (context == nullptr) {
2002         IMAGE_LOGE("Null context");
2003         return;
2004     }
2005     if (context->status == SUCCESS) {
2006         if (context->rPixelMap != nullptr) {
2007             context->rPixelMap->translate(static_cast<float>(context->xArg), static_cast<float>(context->yArg));
2008             context->status = SUCCESS;
2009         } else {
2010             IMAGE_LOGE("Null native ref");
2011             context->status = ERR_IMAGE_INIT_ABNORMAL;
2012         }
2013     } else {
2014         IMAGE_LOGD("Translate has failed. do nothing");
2015     }
2016 }
2017 
Translate(napi_env env,napi_callback_info info)2018 napi_value PixelMapNapi::Translate(napi_env env, napi_callback_info info)
2019 {
2020     NapiValues nVal;
2021     nVal.argc = NUM_3;
2022     napi_value argValue[NUM_3] = {0};
2023     nVal.argv = argValue;
2024     IMAGE_LOGD("Translate IN");
2025     if (!prepareNapiEnv(env, info, &nVal)) {
2026         return nVal.result;
2027     }
2028     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2029 
2030     if (nVal.argc != NUM_2 && nVal.argc != NUM_3) {
2031         IMAGE_LOGE("Invalid args count");
2032         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2033     } else {
2034         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->xArg))) {
2035             IMAGE_LOGE("Arg 0 type mismatch");
2036             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2037         }
2038         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_1], &(nVal.context->yArg))) {
2039             IMAGE_LOGE("Arg 1 type mismatch");
2040             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2041         }
2042     }
2043     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2044         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2045     }
2046 
2047     if (nVal.context->callbackRef == nullptr) {
2048         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2049     }
2050     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2051         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Translate failed",
2052         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "TranslateGeneralError",
2053         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2054         nVal.result);
2055     napi_value _resource = nullptr;
2056     napi_create_string_utf8(env, "Translate", NAPI_AUTO_LENGTH, &_resource);
2057     nVal.status = napi_create_async_work(env, nullptr, _resource,
2058         [](napi_env env, void *data)
2059         {
2060             auto context = static_cast<PixelMapAsyncContext*>(data);
2061             TranslateExec(env, context);
2062         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2063 
2064     if (nVal.status == napi_ok) {
2065         nVal.status = napi_queue_async_work(env, nVal.context->work);
2066         if (nVal.status == napi_ok) {
2067             nVal.context.release();
2068         }
2069     }
2070     return nVal.result;
2071 }
2072 
RotateExec(napi_env env,PixelMapAsyncContext * context)2073 static void RotateExec(napi_env env, PixelMapAsyncContext* context)
2074 {
2075     if (context == nullptr) {
2076         IMAGE_LOGE("Null context");
2077         return;
2078     }
2079     if (context->status == SUCCESS) {
2080         if (context->rPixelMap != nullptr) {
2081             context->rPixelMap->rotate(context->xArg);
2082             context->status = SUCCESS;
2083         } else {
2084             IMAGE_LOGE("Null native ref");
2085             context->status = ERR_IMAGE_INIT_ABNORMAL;
2086         }
2087     } else {
2088         IMAGE_LOGD("Rotate has failed. do nothing");
2089     }
2090 }
2091 
Rotate(napi_env env,napi_callback_info info)2092 napi_value PixelMapNapi::Rotate(napi_env env, napi_callback_info info)
2093 {
2094     NapiValues nVal;
2095     nVal.argc = NUM_2;
2096     napi_value argValue[NUM_2] = {0};
2097     nVal.argv = argValue;
2098     IMAGE_LOGD("Rotate IN");
2099     if (!prepareNapiEnv(env, info, &nVal)) {
2100         return nVal.result;
2101     }
2102     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2103 
2104     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
2105         IMAGE_LOGE("Invalid args count");
2106         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2107     } else {
2108         if (napi_ok != napi_get_value_double(env, nVal.argv[NUM_0], &(nVal.context->xArg))) {
2109             IMAGE_LOGE("Arg 0 type mismatch");
2110             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2111         }
2112     }
2113     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2114         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2115     }
2116 
2117     if (nVal.context->callbackRef == nullptr) {
2118         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2119     }
2120     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2121         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Rotate failed",
2122         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "RotateGeneralError",
2123         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2124         nVal.result);
2125     napi_value _resource = nullptr;
2126     napi_create_string_utf8(env, "Rotate", NAPI_AUTO_LENGTH, &_resource);
2127     nVal.status = napi_create_async_work(env, nullptr, _resource,
2128         [](napi_env env, void *data)
2129         {
2130             auto context = static_cast<PixelMapAsyncContext*>(data);
2131             RotateExec(env, context);
2132         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2133 
2134     if (nVal.status == napi_ok) {
2135         nVal.status = napi_queue_async_work(env, nVal.context->work);
2136         if (nVal.status == napi_ok) {
2137             nVal.context.release();
2138         }
2139     }
2140     return nVal.result;
2141 }
2142 
FlipExec(napi_env env,PixelMapAsyncContext * context)2143 static void FlipExec(napi_env env, PixelMapAsyncContext* context)
2144 {
2145     if (context == nullptr) {
2146         IMAGE_LOGE("Null context");
2147         return;
2148     }
2149     if (context->status == SUCCESS) {
2150         if (context->rPixelMap != nullptr) {
2151             context->rPixelMap->flip(context->xBarg, context->yBarg);
2152             context->status = SUCCESS;
2153         } else {
2154             IMAGE_LOGE("Null native ref");
2155             context->status = ERR_IMAGE_INIT_ABNORMAL;
2156         }
2157     } else {
2158         IMAGE_LOGD("Flip has failed. do nothing");
2159     }
2160 }
2161 
Flip(napi_env env,napi_callback_info info)2162 napi_value PixelMapNapi::Flip(napi_env env, napi_callback_info info)
2163 {
2164     NapiValues nVal;
2165     nVal.argc = NUM_3;
2166     napi_value argValue[NUM_3] = {0};
2167     nVal.argv = argValue;
2168     IMAGE_LOGD("Flip IN");
2169     if (!prepareNapiEnv(env, info, &nVal)) {
2170         return nVal.result;
2171     }
2172     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2173 
2174     if (nVal.argc != NUM_2 && nVal.argc != NUM_3) {
2175         IMAGE_LOGE("Invalid args count");
2176         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2177     } else {
2178         if (napi_ok != napi_get_value_bool(env, nVal.argv[NUM_0], &(nVal.context->xBarg))) {
2179             IMAGE_LOGE("Arg 0 type mismatch");
2180             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2181         }
2182         if (napi_ok != napi_get_value_bool(env, nVal.argv[NUM_1], &(nVal.context->yBarg))) {
2183             IMAGE_LOGE("Arg 1 type mismatch");
2184             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2185         }
2186     }
2187     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2188         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2189     }
2190 
2191     if (nVal.context->callbackRef == nullptr) {
2192         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2193     }
2194     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2195         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Flip failed",
2196         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "FlipGeneralError",
2197         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2198         nVal.result);
2199     napi_value _resource = nullptr;
2200     napi_create_string_utf8(env, "Flip", NAPI_AUTO_LENGTH, &_resource);
2201     nVal.status = napi_create_async_work(env, nullptr, _resource,
2202         [](napi_env env, void *data)
2203         {
2204             auto context = static_cast<PixelMapAsyncContext*>(data);
2205             FlipExec(env, context);
2206         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2207 
2208     if (nVal.status == napi_ok) {
2209         nVal.status = napi_queue_async_work(env, nVal.context->work);
2210         if (nVal.status == napi_ok) {
2211             nVal.context.release();
2212         }
2213     }
2214     return nVal.result;
2215 }
2216 
CropExec(napi_env env,PixelMapAsyncContext * context)2217 static void CropExec(napi_env env, PixelMapAsyncContext* context)
2218 {
2219     if (context == nullptr) {
2220         IMAGE_LOGE("Null context");
2221         return;
2222     }
2223     if (context->status == SUCCESS) {
2224         if (context->rPixelMap != nullptr) {
2225             context->status = context->rPixelMap->crop(context->area.region);
2226         } else {
2227             IMAGE_LOGE("Null native ref");
2228             context->status = ERR_IMAGE_INIT_ABNORMAL;
2229         }
2230     } else {
2231         IMAGE_LOGD("Crop has failed. do nothing");
2232     }
2233 }
2234 
Crop(napi_env env,napi_callback_info info)2235 napi_value PixelMapNapi::Crop(napi_env env, napi_callback_info info)
2236 {
2237     NapiValues nVal;
2238     nVal.argc = NUM_2;
2239     napi_value argValue[NUM_2] = {0};
2240     nVal.argv = argValue;
2241     IMAGE_LOGD("Crop IN");
2242     if (!prepareNapiEnv(env, info, &nVal)) {
2243         return nVal.result;
2244     }
2245     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2246 
2247     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
2248         IMAGE_LOGE("Invalid args count");
2249         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2250     } else {
2251         if (!parseRegion(env, nVal.argv[NUM_0], &(nVal.context->area.region))) {
2252             IMAGE_LOGE("Region type mismatch");
2253             nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2254         }
2255     }
2256     if (nVal.argc >= 1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2257         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2258     }
2259 
2260     if (nVal.context->callbackRef == nullptr) {
2261         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2262     }
2263     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2264         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . Crop failed",
2265         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "CropGeneralError",
2266         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2267         nVal.result);
2268     napi_value _resource = nullptr;
2269     napi_create_string_utf8(env, "CropExec", NAPI_AUTO_LENGTH, &_resource);
2270     nVal.status = napi_create_async_work(env, nullptr, _resource,
2271         [](napi_env env, void *data)
2272         {
2273             auto context = static_cast<PixelMapAsyncContext*>(data);
2274             CropExec(env, context);
2275         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2276 
2277     if (nVal.status == napi_ok) {
2278         nVal.status = napi_queue_async_work(env, nVal.context->work);
2279         if (nVal.status == napi_ok) {
2280             nVal.context.release();
2281         }
2282     }
2283     return nVal.result;
2284 }
2285 
GetColorSpace(napi_env env,napi_callback_info info)2286 napi_value PixelMapNapi::GetColorSpace(napi_env env, napi_callback_info info)
2287 {
2288     NapiValues nVal;
2289     nVal.argc = NUM_0;
2290     IMAGE_LOGD("GetColorSpace IN");
2291     napi_get_undefined(env, &nVal.result);
2292     if (!prepareNapiEnv(env, info, &nVal)) {
2293         return ImageNapiUtils::ThrowExceptionError(
2294             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to unwrap context");
2295     }
2296     if (nVal.argc != NUM_0) {
2297         return ImageNapiUtils::ThrowExceptionError(
2298             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid args count");
2299     }
2300     IMG_NAPI_CHECK_RET_D(nVal.context->nConstructor->GetPixelNapiEditable(),
2301         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2302         "Pixelmap has crossed threads . GetColorSpace failed"),
2303         IMAGE_LOGE("Pixelmap has crossed threads . GetColorSpace failed"));
2304 #ifdef IMAGE_COLORSPACE_FLAG
2305     if (nVal.context->nConstructor->nativePixelMap_ == nullptr) {
2306         return ImageNapiUtils::ThrowExceptionError(
2307             env, ERR_IMAGE_DATA_ABNORMAL, "Invalid native pixelmap");
2308     }
2309     auto grCS = nVal.context->nConstructor->nativePixelMap_->InnerGetGrColorSpacePtr();
2310     if (grCS == nullptr) {
2311         return ImageNapiUtils::ThrowExceptionError(
2312             env, ERR_IMAGE_DATA_UNSUPPORT, "No colorspace in pixelmap");
2313     }
2314     auto resultValue = ColorManager::CreateJsColorSpaceObject(env, grCS);
2315     nVal.result = reinterpret_cast<napi_value>(resultValue);
2316 #else
2317     return ImageNapiUtils::ThrowExceptionError(
2318         env, ERR_INVALID_OPERATION, "Unsupported operation");
2319 #endif
2320     return nVal.result;
2321 }
2322 
SetColorSpace(napi_env env,napi_callback_info info)2323 napi_value PixelMapNapi::SetColorSpace(napi_env env, napi_callback_info info)
2324 {
2325     NapiValues nVal;
2326     nVal.argc = NUM_1;
2327     napi_value argValue[NUM_1] = {0};
2328     nVal.argv = argValue;
2329     IMAGE_LOGD("SetColorSpace IN");
2330     napi_get_undefined(env, &nVal.result);
2331     if (!prepareNapiEnv(env, info, &nVal)) {
2332         return ImageNapiUtils::ThrowExceptionError(
2333             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to unwrap context");
2334     }
2335     if (nVal.argc != NUM_1) {
2336         return ImageNapiUtils::ThrowExceptionError(
2337             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid args count");
2338     }
2339     IMG_NAPI_CHECK_RET_D(nVal.context->nConstructor->GetPixelNapiEditable(),
2340         ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE,
2341         "Pixelmap has crossed threads . SetColorSpace failed"),
2342         IMAGE_LOGE("Pixelmap has crossed threads . SetColorSpace failed"));
2343 #ifdef IMAGE_COLORSPACE_FLAG
2344     nVal.context->colorSpace = ColorManager::GetColorSpaceByJSObject(env, nVal.argv[NUM_0]);
2345     if (nVal.context->colorSpace == nullptr) {
2346         return ImageNapiUtils::ThrowExceptionError(
2347             env, ERR_IMAGE_INVALID_PARAMETER, "ColorSpace mismatch");
2348     }
2349     nVal.context->nConstructor->nativePixelMap_->InnerSetColorSpace(*(nVal.context->colorSpace));
2350 #else
2351     return ImageNapiUtils::ThrowExceptionError(
2352         env, ERR_INVALID_OPERATION, "Unsupported operation");
2353 #endif
2354     return nVal.result;
2355 }
2356 
Marshalling(napi_env env,napi_callback_info info)2357 napi_value PixelMapNapi::Marshalling(napi_env env, napi_callback_info info)
2358 {
2359 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
2360     NapiValues nVal;
2361     nVal.argc = NUM_1;
2362     napi_value argValue[NUM_1] = {0};
2363     nVal.argv = argValue;
2364     IMAGE_LOGD("Marshalling IN");
2365 
2366     if (!prepareNapiEnv(env, info, &nVal)) {
2367         return ImageNapiUtils::ThrowExceptionError(
2368             env, ERR_IMAGE_INVALID_PARAMETER, "Fail to unwrap context");
2369     }
2370     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2371     if (nVal.argc != NUM_0 && nVal.argc != NUM_1) {
2372         return ImageNapiUtils::ThrowExceptionError(
2373             env, ERR_IMAGE_INVALID_PARAMETER, "Invalid args count");
2374     }
2375     NAPI_MessageSequence *napiSequence = nullptr;
2376     napi_get_cb_info(env, info, &nVal.argc, nVal.argv, nullptr, nullptr);
2377     napi_unwrap(env, nVal.argv[0], reinterpret_cast<void**>(&napiSequence));
2378     auto messageParcel = napiSequence->GetMessageParcel();
2379     bool st = nVal.context->rPixelMap->Marshalling(*messageParcel);
2380     if (!st) {
2381         return ImageNapiUtils::ThrowExceptionError(
2382             env, ERR_IPC, "marshalling pixel map to parcel failed.");
2383     }
2384     return nVal.result;
2385 #else
2386     napi_value result = nullptr;
2387     return result;
2388 #endif
2389 }
2390 
ApplyColorSpaceExec(napi_env env,PixelMapAsyncContext * context)2391 static void ApplyColorSpaceExec(napi_env env, PixelMapAsyncContext* context)
2392 {
2393     if (context == nullptr) {
2394         IMAGE_LOGE("Null context");
2395         return;
2396     }
2397     if (context->status != SUCCESS) {
2398         IMAGE_LOGD("ApplyColorSpace has failed. do nothing");
2399         return;
2400     }
2401     if (context->rPixelMap == nullptr || context->colorSpace == nullptr) {
2402         context->status = ERR_IMAGE_INIT_ABNORMAL;
2403         IMAGE_LOGE("ApplyColorSpace Null native ref");
2404         return;
2405     }
2406     context->status = context->rPixelMap->ApplyColorSpace(*(context->colorSpace));
2407 }
2408 
ParseColorSpaceVal(napi_env env,napi_value val,PixelMapAsyncContext * context)2409 static void ParseColorSpaceVal(napi_env env, napi_value val, PixelMapAsyncContext* context)
2410 {
2411     if (context == nullptr) {
2412         IMAGE_LOGE("Null context");
2413         return;
2414     }
2415 
2416 #ifdef IMAGE_COLORSPACE_FLAG
2417     context->colorSpace = ColorManager::GetColorSpaceByJSObject(env, val);
2418     if (context->colorSpace == nullptr) {
2419         context->status = ERR_IMAGE_INVALID_PARAMETER;
2420     }
2421 #else
2422     Val.context->status = ERR_IMAGE_DATA_UNSUPPORT;
2423 #endif
2424 }
2425 
ApplyColorSpace(napi_env env,napi_callback_info info)2426 napi_value PixelMapNapi::ApplyColorSpace(napi_env env, napi_callback_info info)
2427 {
2428     NapiValues nVal;
2429     nVal.argc = NUM_2;
2430     napi_value argValue[NUM_2] = {0};
2431     nVal.argv = argValue;
2432     IMAGE_LOGD("ApplyColorSpace IN");
2433     if (!prepareNapiEnv(env, info, &nVal)) {
2434         return nVal.result;
2435     }
2436     nVal.context->rPixelMap = nVal.context->nConstructor->nativePixelMap_;
2437 
2438     if (nVal.argc != NUM_1 && nVal.argc != NUM_2) {
2439         IMAGE_LOGE("Invalid args count");
2440         nVal.context->status = ERR_IMAGE_INVALID_PARAMETER;
2441     } else {
2442         ParseColorSpaceVal(env, nVal.argv[NUM_0], nVal.context.get());
2443     }
2444     if (nVal.argc >= NUM_1 && ImageNapiUtils::getType(env, nVal.argv[nVal.argc - 1]) == napi_function) {
2445         napi_create_reference(env, nVal.argv[nVal.argc - 1], nVal.refCount, &(nVal.context->callbackRef));
2446     }
2447 
2448     if (nVal.context->callbackRef == nullptr) {
2449         napi_create_promise(env, &(nVal.context->deferred), &(nVal.result));
2450     }
2451     IMG_NAPI_CHECK_BUILD_ERROR(nVal.context->nConstructor->GetPixelNapiEditable(),
2452         BuildContextError(env, nVal.context->error, "pixelmap has crossed threads . ApplyColorSpace failed",
2453         ERR_RESOURCE_UNAVAILABLE), IMG_CREATE_CREATE_ASYNC_WORK(env, nVal.status, "ApplyColorSpaceGeneralError",
2454         [](napi_env env, void *data) {}, GeneralErrorComplete, nVal.context, nVal.context->work),
2455         nVal.result);
2456     napi_value _resource = nullptr;
2457     napi_create_string_utf8(env, "ApplyColorSpace", NAPI_AUTO_LENGTH, &_resource);
2458     nVal.status = napi_create_async_work(env, nullptr, _resource, [](napi_env env, void *data) {
2459             auto context = static_cast<PixelMapAsyncContext*>(data);
2460             ApplyColorSpaceExec(env, context);
2461         }, EmptyResultComplete, static_cast<void*>(nVal.context.get()), &(nVal.context->work));
2462 
2463     if (nVal.status == napi_ok) {
2464         nVal.status = napi_queue_async_work(env, nVal.context->work);
2465         if (nVal.status == napi_ok) {
2466             nVal.context.release();
2467         }
2468     }
2469     return nVal.result;
2470 }
2471 
release()2472 void PixelMapNapi::release()
2473 {
2474     if (!isRelease) {
2475         if (nativePixelMap_ != nullptr) {
2476             nativePixelMap_.reset();
2477         }
2478         isRelease = true;
2479     }
2480 }
2481 }  // namespace Media
2482 }  // namespace OHOS
2483