• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "picture_napi.h"
17 #include "media_errors.h"
18 #include "image_log.h"
19 #include "image_napi_utils.h"
20 #include "image_napi.h"
21 #include "pixel_map_napi.h"
22 #include "auxiliary_picture_napi.h"
23 #include "auxiliary_picture.h"
24 #include "napi_message_sequence.h"
25 #include "metadata.h"
26 #include "metadata_napi.h"
27 #include "image_common.h"
28 
29 #undef LOG_DOMAIN
30 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
31 
32 #undef LOG_TAG
33 #define LOG_TAG "PictureNapi"
34 
35 namespace {
36     constexpr uint32_t NUM_0 = 0;
37     constexpr uint32_t NUM_1 = 1;
38     constexpr uint32_t NUM_2 = 2;
39 }
40 
41 namespace OHOS {
42 namespace Media {
43 static const std::string CREATE_PICTURE_FROM_PARCEL = "createPictureFromParcel";
44 static const std::map<std::string, std::set<uint32_t>> ETS_API_ERROR_CODE = {
45     {CREATE_PICTURE_FROM_PARCEL, {62980096, 62980105, 62980115, 62980097,
46         62980177, 62980178, 62980179, 62980180, 62980246}}
47 };
48 static const std::string CLASS_NAME = "Picture";
49 thread_local napi_ref PictureNapi::sConstructor_ = nullptr;
50 thread_local std::shared_ptr<Picture> PictureNapi::sPicture_ = nullptr;
51 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
52 NAPI_MessageSequence* messageSequence = nullptr;
53 #endif
54 
55 struct PictureAsyncContext {
56     napi_env env;
57     napi_async_work work;
58     napi_deferred deferred;
59     napi_ref callbackRef;
60     napi_ref error = nullptr;
61     uint32_t status;
62     std::shared_ptr<Picture> rPicture;
63     PictureNapi *nConstructor;
64     std::shared_ptr<PixelMap> rPixelMap;
65     std::shared_ptr<PixelMap> rHdrPixelMap;
66     MetadataNapi *metadataNapi;
67     std::shared_ptr<ImageMetadata> imageMetadata;
68     MetadataType metadataType = MetadataType::EXIF;
69 };
70 
71 using PictureAsyncContextPtr = std::unique_ptr<PictureAsyncContext>;
72 
73 napi_ref PictureNapi::auxiliaryPictureTypeRef_ = nullptr;
74 napi_ref PictureNapi::metadataTypeRef_ = nullptr;
75 napi_ref PictureNapi::gifPropertyKeyRef_ = nullptr;
76 
77 struct PictureEnum {
78     std::string name;
79     int32_t numVal;
80     std::string strVal;
81 };
82 
83 static std::vector<struct PictureEnum> auxiliaryPictureTypeMap = {
84     {"GAINMAP", static_cast<uint32_t>(AuxiliaryPictureType::GAINMAP), ""},
85     {"DEPTH_MAP", static_cast<uint32_t>(AuxiliaryPictureType::DEPTH_MAP), ""},
86     {"UNREFOCUS_MAP", static_cast<uint32_t>(AuxiliaryPictureType::UNREFOCUS_MAP), ""},
87     {"LINEAR_MAP", static_cast<uint32_t>(AuxiliaryPictureType::LINEAR_MAP), ""},
88     {"FRAGMENT_MAP", static_cast<uint32_t>(AuxiliaryPictureType::FRAGMENT_MAP), ""},
89 };
90 
91 static std::vector<struct PictureEnum> metadataTypeMap = {
92     {"EXIF_METADATA", static_cast<uint32_t>(MetadataType::EXIF), ""},
93     {"FRAGMENT_METADATA", static_cast<uint32_t>(MetadataType::FRAGMENT), ""},
94     {"GIF_METADATA", static_cast<uint32_t>(MetadataType::GIF), ""},
95 };
96 
97 static std::vector<struct PictureEnum> gifPropertyKeyMap = {
98     {"GIF_DELAY_TIME", 0, "GifDelayTime"},
99     {"GIF_DISPOSAL_TYPE", 0, "GifDisposalType"},
100 };
101 
102 struct NapiValues {
103     napi_status status;
104     napi_value thisVar = nullptr;
105     napi_value result = nullptr;
106     napi_value* argv = nullptr;
107     size_t argc;
108     int32_t refCount = 1;
109     std::unique_ptr<PictureAsyncContext> context;
110 };
111 
CreateEnumTypeObject(napi_env env,napi_valuetype type,napi_ref * ref,std::vector<struct PictureEnum> pictureEnumMap)112 static napi_value CreateEnumTypeObject(napi_env env,
113     napi_valuetype type, napi_ref* ref, std::vector<struct PictureEnum> pictureEnumMap)
114 {
115     napi_value result = nullptr;
116     napi_status status;
117     std::string propName;
118     status = napi_create_object(env, &result);
119     if (status == napi_ok) {
120         for (auto imgEnum : pictureEnumMap) {
121             napi_value enumNapiValue = nullptr;
122             if (type == napi_string) {
123                 status = napi_create_string_utf8(env, imgEnum.strVal.c_str(),
124                     NAPI_AUTO_LENGTH, &enumNapiValue);
125             } else if (type == napi_number) {
126                 status = napi_create_int32(env, imgEnum.numVal, &enumNapiValue);
127             } else {
128                 IMAGE_LOGE("Unsupported type %{public}d!", type);
129                 break;
130             }
131             if (status == napi_ok && enumNapiValue != nullptr) {
132                 status = napi_set_named_property(env, result, imgEnum.name.c_str(), enumNapiValue);
133             }
134             if (status != napi_ok) {
135                 IMAGE_LOGE("Failed to add named prop!");
136                 break;
137             }
138         }
139 
140         if (status == napi_ok) {
141             int32_t refCount = 1;
142             status = napi_create_reference(env, result, refCount, ref);
143             if (status == napi_ok) {
144                 return result;
145             }
146         }
147     }
148     IMAGE_LOGE("CreateEnumTypeObject is Failed!");
149     napi_get_undefined(env, &result);
150     return result;
151 }
152 
CommonCallbackRoutine(napi_env env,PictureAsyncContext * & asyncContext,const napi_value & valueParam)153 static void CommonCallbackRoutine(napi_env env, PictureAsyncContext* &asyncContext, const napi_value &valueParam)
154 {
155     napi_value result[NUM_2] = {0};
156 
157     napi_get_undefined(env, &result[NUM_0]);
158     napi_get_undefined(env, &result[NUM_1]);
159 
160     napi_handle_scope scope = nullptr;
161     napi_open_handle_scope(env, &scope);
162     if (scope == nullptr) {
163         return;
164     }
165 
166     if (asyncContext == nullptr) {
167         napi_close_handle_scope(env, scope);
168         return;
169     }
170     if (asyncContext->status == SUCCESS) {
171         result[NUM_1] = valueParam;
172     } else if (asyncContext->error != nullptr) {
173         napi_get_reference_value(env, asyncContext->error, &result[NUM_0]);
174         napi_delete_reference(env, asyncContext->error);
175     } else {
176         napi_create_uint32(env, asyncContext->status, &result[NUM_0]);
177     }
178 
179     if (asyncContext->deferred) {
180         if (asyncContext->status == SUCCESS) {
181             napi_resolve_deferred(env, asyncContext->deferred, result[NUM_1]);
182         } else {
183             napi_reject_deferred(env, asyncContext->deferred, result[NUM_0]);
184         }
185     }
186 
187     napi_delete_async_work(env, asyncContext->work);
188     napi_close_handle_scope(env, scope);
189 
190     delete asyncContext;
191     asyncContext = nullptr;
192 }
193 
ParserImageType(napi_env env,napi_value argv)194 static ImageType ParserImageType(napi_env env, napi_value argv)
195 {
196     napi_value constructor = nullptr;
197     napi_value global = nullptr;
198     bool isInstance = false;
199     napi_status ret = napi_invalid_arg;
200 
201     ret = napi_get_global(env, &global);
202     if (ret != napi_ok) {
203         IMAGE_LOGI("Get global failed!");
204         return ImageType::TYPE_UNKNOWN;
205     }
206 
207     ret = napi_get_named_property(env, global, "PixelMap", &constructor);
208     if (ret != napi_ok) {
209         IMAGE_LOGI("Get PixelMapNapi property failed!");
210     }
211 
212     ret = napi_instanceof(env, argv, constructor, &isInstance);
213     if (ret == napi_ok && isInstance) {
214         return ImageType::TYPE_PIXEL_MAP;
215     }
216 
217     IMAGE_LOGI("InValued type!");
218     return ImageType::TYPE_UNKNOWN;
219 }
220 
prepareNapiEnv(napi_env env,napi_callback_info info,struct NapiValues * nVal)221 static bool prepareNapiEnv(napi_env env, napi_callback_info info, struct NapiValues* nVal)
222 {
223     napi_get_undefined(env, &(nVal->result));
224     nVal->status = napi_get_cb_info(env, info, &(nVal->argc), nVal->argv, &(nVal->thisVar), nullptr);
225     if (nVal->status != napi_ok) {
226         IMAGE_LOGE("Fail to napi_get_cb_info");
227         return false;
228     }
229     nVal->context = std::make_unique<PictureAsyncContext>();
230     nVal->status = napi_unwrap(env, nVal->thisVar, reinterpret_cast<void**>(&(nVal->context->nConstructor)));
231     if (nVal->status != napi_ok) {
232         IMAGE_LOGE("Fail to unwrap context");
233         return false;
234     }
235     nVal->context->status = SUCCESS;
236     return true;
237 }
238 
PictureNapi()239 PictureNapi::PictureNapi():env_(nullptr)
240 {
241     static std::atomic<uint32_t> currentId = 0;
242     uniqueId_ = currentId.fetch_add(1, std::memory_order_relaxed);
243 }
244 
~PictureNapi()245 PictureNapi::~PictureNapi()
246 {
247     release();
248 }
249 
Init(napi_env env,napi_value exports)250 napi_value PictureNapi::Init(napi_env env, napi_value exports)
251 {
252     napi_property_descriptor props[] = {
253         DECLARE_NAPI_FUNCTION("getMainPixelmap", GetMainPixelmap),
254         DECLARE_NAPI_FUNCTION("getHdrComposedPixelmap", GetHdrComposedPixelMap),
255         DECLARE_NAPI_FUNCTION("getGainmapPixelmap", GetGainmapPixelmap),
256         DECLARE_NAPI_FUNCTION("getAuxiliaryPicture", GetAuxiliaryPicture),
257         DECLARE_NAPI_FUNCTION("setAuxiliaryPicture", SetAuxiliaryPicture),
258         DECLARE_NAPI_FUNCTION("release", Release),
259         DECLARE_NAPI_FUNCTION("marshalling", Marshalling),
260         DECLARE_NAPI_FUNCTION("getMetadata", GetMetadata),
261         DECLARE_NAPI_FUNCTION("setMetadata", SetMetadata),
262     };
263     napi_property_descriptor static_prop[] = {
264         DECLARE_NAPI_STATIC_FUNCTION("createPicture", CreatePicture),
265         DECLARE_NAPI_STATIC_FUNCTION("createPictureFromParcel", CreatePictureFromParcel),
266         DECLARE_NAPI_STATIC_FUNCTION("createPictureByHdrAndSdrPixelMap", CreatePictureByHdrAndSdrPixelMap),
267         DECLARE_NAPI_PROPERTY("AuxiliaryPictureType", CreateEnumTypeObject(env, napi_number,
268             &auxiliaryPictureTypeRef_, auxiliaryPictureTypeMap)),
269         DECLARE_NAPI_PROPERTY("MetadataType", CreateEnumTypeObject(env, napi_number,
270             &metadataTypeRef_, metadataTypeMap)),
271         DECLARE_NAPI_PROPERTY("GifPropertyKey", CreateEnumTypeObject(env, napi_string,
272             &gifPropertyKeyRef_, gifPropertyKeyMap)),
273     };
274 
275     napi_value constructor = nullptr;
276 
277     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
278         napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr, IMG_ARRAY_SIZE(props),
279         props, &constructor)), nullptr, IMAGE_LOGE("define class fail")
280     );
281 
282     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_create_reference(env, constructor, 1, &sConstructor_)),
283         nullptr, IMAGE_LOGE("create reference fail")
284     );
285 
286     napi_value global = nullptr;
287     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_global(env, &global)), nullptr, IMAGE_LOGE("Init:get global fail"));
288 
289     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
290         napi_set_named_property(env, global, CLASS_NAME.c_str(), constructor)),
291         nullptr, IMAGE_LOGE("Init:set global named property fail")
292     );
293 
294     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
295         napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor)),
296         nullptr, IMAGE_LOGE("set named property fail")
297     );
298 
299     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
300         napi_define_properties(env, exports, IMG_ARRAY_SIZE(static_prop), static_prop)),
301         nullptr, IMAGE_LOGE("define properties fail")
302     );
303 
304     IMAGE_LOGD("Init success");
305     return exports;
306 }
307 
Constructor(napi_env env,napi_callback_info info)308 napi_value PictureNapi::Constructor(napi_env env, napi_callback_info info)
309 {
310     napi_value undefineVar = nullptr;
311     napi_get_undefined(env, &undefineVar);
312 
313     napi_status status;
314     napi_value thisVar = nullptr;
315     napi_get_undefined(env, &thisVar);
316     IMAGE_LOGD("Constructor IN");
317     status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
318     IMG_NAPI_CHECK_RET(IMG_IS_READY(status, thisVar), undefineVar);
319     std::unique_ptr<PictureNapi> pPictureNapi = std::make_unique<PictureNapi>();
320     if (pPictureNapi != nullptr) {
321         pPictureNapi->env_ = env;
322         pPictureNapi->nativePicture_ = std::move(sPicture_);
323         if (pPictureNapi->nativePicture_ == nullptr) {
324             IMAGE_LOGE("Failed to set nativePicture_ with null. Maybe a reentrancy error");
325         }
326         status = napi_wrap(env, thisVar, reinterpret_cast<void *>(pPictureNapi.release()),
327                            PictureNapi::Destructor, nullptr, nullptr);
328         if (status != napi_ok) {
329             IMAGE_LOGE("Failure wrapping js to native napi");
330             return undefineVar;
331         }
332     }
333     return thisVar;
334 }
335 
Destructor(napi_env env,void * nativeObject,void * finalize)336 void PictureNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
337 {
338     if (nativeObject != nullptr) {
339         IMAGE_LOGD("Destructor PictureNapi");
340         delete reinterpret_cast<PictureNapi*>(nativeObject);
341         nativeObject = nullptr;
342     }
343 }
344 
CreatePicture(napi_env env,std::shared_ptr<Picture> & picture)345 napi_value PictureNapi::CreatePicture(napi_env env, std::shared_ptr<Picture> &picture)
346 {
347     if (sConstructor_ == nullptr) {
348         napi_value exports = nullptr;
349         napi_create_object(env, &exports);
350         PictureNapi::Init(env, exports);
351     }
352     napi_value constructor = nullptr;
353     napi_value result = nullptr;
354     napi_status status = napi_get_reference_value(env, sConstructor_, &constructor);
355     if (IMG_IS_OK(status)) {
356         if (picture != nullptr) {
357             sPicture_ = std::move(picture);
358             status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
359         } else {
360             status = napi_invalid_arg;
361             IMAGE_LOGE("New PictureNapi Instance picture is nullptr");
362             napi_get_undefined(env, &result);
363         }
364     }
365     if (!IMG_IS_OK(status)) {
366         IMAGE_LOGE("CreatePicture | New instance could not be obtained");
367         napi_get_undefined(env, &result);
368     }
369     return result;
370 }
371 
ParseAuxiliaryPictureType(int32_t val)372 static AuxiliaryPictureType ParseAuxiliaryPictureType(int32_t val)
373 {
374     if (val >= static_cast<int32_t>(AuxiliaryPictureType::GAINMAP)
375         && val<= static_cast<int32_t>(AuxiliaryPictureType::FRAGMENT_MAP)) {
376         return AuxiliaryPictureType(val);
377     }
378 
379     return AuxiliaryPictureType::NONE;
380 }
381 
PreparePicNapiEnv(napi_env env)382 static void PreparePicNapiEnv(napi_env env)
383 {
384     napi_value globalValue;
385     napi_get_global(env, &globalValue);
386     napi_value func;
387     napi_get_named_property(env, globalValue, "requireNapi", &func);
388 
389     napi_value picture;
390     napi_create_string_utf8(env, "multimedia.image", NAPI_AUTO_LENGTH, &picture);
391     napi_value funcArgv[NUM_1] = { picture };
392     napi_value returnValue;
393     napi_call_function(env, globalValue, func, NUM_1, funcArgv, &returnValue);
394 }
395 
CreatePictureNapi(napi_env env,napi_value * result)396 int32_t PictureNapi::CreatePictureNapi(napi_env env, napi_value* result)
397 {
398     napi_value constructor = nullptr;
399     napi_status status = napi_ok;
400     PreparePicNapiEnv(env);
401 
402     status = napi_get_reference_value(env, sConstructor_, &constructor);
403     if (status == napi_ok && constructor != nullptr) {
404         status = napi_new_instance(env, constructor, NUM_0, nullptr, result);
405     }
406 
407     if (status != napi_ok || result == nullptr) {
408         IMAGE_LOGE("CreatePictureNapi new instance failed");
409         napi_get_undefined(env, result);
410         return ERR_IMAGE_DATA_ABNORMAL;
411     }
412     return SUCCESS;
413 }
414 
SetNativePicture(std::shared_ptr<Picture> picture)415 void PictureNapi::SetNativePicture(std::shared_ptr<Picture> picture)
416 {
417     nativePicture_ = picture;
418 }
419 
GetAuxiliaryPicture(napi_env env,napi_callback_info info)420 napi_value PictureNapi::GetAuxiliaryPicture(napi_env env, napi_callback_info info)
421 {
422     napi_value result = nullptr;
423     napi_get_undefined(env, &result);
424     napi_status status;
425     napi_value thisVar = nullptr;
426     napi_value argValue[NUM_1] = {0};
427     size_t argCount = NUM_1;
428     uint32_t auxiType = 0;
429 
430     IMAGE_LOGD("GetAuxiliaryPicture IN");
431     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
432     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to arg info"));
433     PictureNapi* pictureNapi = nullptr;
434     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pictureNapi));
435     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pictureNapi), result, IMAGE_LOGE("fail to unwrap PictureNapi"));
436     status = napi_get_value_uint32(env, argValue[NUM_0], &auxiType);
437     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
438         "Fail to get auxiliary picture type!"), IMAGE_LOGE("Fail to get auxiliary picture type."));
439     AuxiliaryPictureType type = ParseAuxiliaryPictureType(auxiType);
440     if (type == AuxiliaryPictureType::NONE) {
441         return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
442             "The type does not match the auxiliary picture type!");
443     }
444 
445     if (pictureNapi->nativePicture_ != nullptr) {
446         auto auxiliaryPic = pictureNapi->nativePicture_->GetAuxiliaryPicture(type);
447         if (auxiliaryPic != nullptr) {
448             result = AuxiliaryPictureNapi::CreateAuxiliaryPicture(env, std::move(auxiliaryPic));
449         } else {
450             IMAGE_LOGE("native auxiliary picture is nullptr!");
451         }
452     } else {
453         IMAGE_LOGE("native picture is nullptr!");
454     }
455     return result;
456 }
457 
GetPicture(napi_env env,napi_value picture)458 std::shared_ptr<Picture> PictureNapi::GetPicture(napi_env env, napi_value picture)
459 {
460     PictureNapi *pictureNapi = nullptr;
461     napi_status status = napi_unwrap(env, picture, reinterpret_cast<void**>(&pictureNapi));
462     if (!IMG_IS_OK(status)) {
463         IMAGE_LOGE("GetPicture napi unwrap failed");
464         return nullptr;
465     }
466     if (pictureNapi == nullptr) {
467         IMAGE_LOGE("GetPixelMap pixmapNapi is nullptr");
468         return nullptr;
469     }
470     return pictureNapi->nativePicture_;
471 }
472 
SetAuxiliaryPicture(napi_env env,napi_callback_info info)473 napi_value PictureNapi::SetAuxiliaryPicture(napi_env env, napi_callback_info info)
474 {
475     napi_value result = nullptr;
476     napi_get_undefined(env, &result);
477     napi_status status;
478     napi_value thisVar = nullptr;
479     napi_value argValue[NUM_2] = {0};
480     size_t argCount = NUM_2;
481     uint32_t auxiType = 0;
482 
483     IMAGE_LOGD("SetAuxiliaryPictureSync IN");
484     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
485     PictureNapi* pictureNapi = nullptr;
486     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pictureNapi));
487     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pictureNapi), result, IMAGE_LOGE("fail to unwrap PictureNapi"));
488 
489     status = napi_get_value_uint32(env, argValue[NUM_0], &auxiType);
490     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
491         "Fail to get auxiliary picture type!"), IMAGE_LOGE("Fail to get auxiliary picture Type"));
492     AuxiliaryPictureType type = ParseAuxiliaryPictureType(auxiType);
493     if (type == AuxiliaryPictureType::NONE) {
494         return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
495             "The type does not match the auxiliary picture type!");
496     }
497 
498     AuxiliaryPictureNapi* auxiliaryPictureNapi = nullptr;
499     status = napi_unwrap(env, argValue[NUM_1], reinterpret_cast<void**>(&auxiliaryPictureNapi));
500     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pictureNapi),
501         ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Fail to unwrap AuxiliaryPictureNapi!"),
502         IMAGE_LOGE("Fail to unwrap AuxiliaryPictureNapi"));
503 
504     if (pictureNapi->nativePicture_ != nullptr) {
505         auto auxiliaryPicturePtr = auxiliaryPictureNapi->GetNativeAuxiliaryPic();
506         if (auxiliaryPicturePtr != nullptr) {
507             if (type != auxiliaryPicturePtr->GetAuxiliaryPictureInfo().auxiliaryPictureType) {
508                 return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
509                     "The type does not match the auxiliary picture type!");
510             } else {
511                 pictureNapi->nativePicture_->SetAuxiliaryPicture(auxiliaryPicturePtr);
512             }
513         } else {
514             return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
515                 "Native auxiliary picture is nullptr!");
516         }
517     } else {
518         IMAGE_LOGE("native picture is nullptr!");
519     }
520 
521     return result;
522 }
523 
STATIC_EXEC_FUNC(CreatePicture)524 STATIC_EXEC_FUNC(CreatePicture)
525 {
526     IMAGE_LOGD("CreatePictureEX IN");
527     auto context = static_cast<PictureAsyncContext*>(data);
528     auto picture = Picture::Create(context->rPixelMap);
529     context->rPicture = std::move(picture);
530     IMAGE_LOGD("CreatePictureEX OUT");
531     if (IMG_NOT_NULL(context->rPicture)) {
532         context->status = SUCCESS;
533     } else {
534         context->status = ERR_MEDIA_UNSUPPORT_OPERATION;
535     }
536 }
537 
CreatePicture(napi_env env,napi_callback_info info)538 napi_value PictureNapi::CreatePicture(napi_env env, napi_callback_info info)
539 {
540     IMAGE_LOGD("CreatePicture IN");
541     if (sConstructor_ == nullptr) {
542         napi_value exports = nullptr;
543         napi_create_object(env, &exports);
544         PictureNapi::Init(env, exports);
545     }
546     napi_value result = nullptr;
547     napi_get_undefined(env, &result);
548     napi_value constructor = nullptr;
549     napi_status status;
550     napi_value thisVar = nullptr;
551     napi_value argValue[NUM_1] = {0};
552     size_t argCount = NUM_1;
553     IMAGE_LOGD("CreatePicture IN");
554     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
555     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
556         "Invalid args"), IMAGE_LOGE("fail to napi_get_cb_info"));
557     IMG_NAPI_CHECK_RET_D(argCount == NUM_1, ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
558         "Invalid args count"), IMAGE_LOGE("Invalid args count %{public}zu", argCount));
559     std::unique_ptr<PictureAsyncContext> asyncContext = std::make_unique<PictureAsyncContext>();
560     if (ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP) {
561         asyncContext->rPixelMap = PixelMapNapi::GetPixelMap(env, argValue[NUM_0]);
562         if (asyncContext->rPixelMap == nullptr) {
563             return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Get arg pixelmap failed");
564         }
565     } else {
566         return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Input image type mismatch");
567     }
568     CreatePictureExec(env, static_cast<void*>((asyncContext).get()));
569     status = napi_get_reference_value(env, sConstructor_, &constructor);
570     if (IMG_IS_OK(status)) {
571         sPicture_ = std::move(asyncContext->rPicture);
572         status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
573     }
574     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to create picture sync"));
575     IMAGE_LOGD("CreatePicture OUT");
576     return result;
577 }
578 
STATIC_EXEC_FUNC(CreatePictureByHdrAndSdrPixelMap)579 STATIC_EXEC_FUNC(CreatePictureByHdrAndSdrPixelMap)
580 {
581     IMAGE_LOGD("CreatePictureByHdrAndSdrPixelMapEX IN");
582     auto context = static_cast<PictureAsyncContext*>(data);
583     auto picture = Picture::CreatePictureByHdrAndSdrPixelMap(context->rHdrPixelMap, context->rPixelMap);
584     context->rPicture = std::move(picture);
585     IMAGE_LOGD("CreatePictureByHdrAndSdrPixelMapEX OUT");
586     if (IMG_NOT_NULL(context->rPicture)) {
587         context->status = SUCCESS;
588     } else {
589         context->status = ERROR;
590     }
591 }
592 
CreatePictureByHdrAndSdrPixelMap(napi_env env,napi_callback_info info)593 napi_value PictureNapi::CreatePictureByHdrAndSdrPixelMap(napi_env env, napi_callback_info info)
594 {
595     IMAGE_LOGD("CreatePictureByHdrAndSdrPixelMap IN");
596     if (sConstructor_ == nullptr) {
597         napi_value exports = nullptr;
598         napi_create_object(env, &exports);
599         PictureNapi::Init(env, exports);
600     }
601     napi_value result = nullptr;
602     napi_get_undefined(env, &result);
603     napi_value constructor = nullptr;
604     napi_status status;
605     napi_value thisVar = nullptr;
606     napi_value argValue[NUM_2] = {0};
607     size_t argCount = NUM_2;
608     IMAGE_LOGD("CreatePictureByHdrAndSdrPixelMap IN");
609     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
610     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
611         "Invalid args"), IMAGE_LOGE("fail to napi_get_cb_info"));
612     IMG_NAPI_CHECK_RET_D(argCount == NUM_2, ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
613         "Invalid args count"), IMAGE_LOGE("Invalid args count %{public}zu", argCount));
614     std::unique_ptr<PictureAsyncContext> asyncContext = std::make_unique<PictureAsyncContext>();
615     if (ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP) {
616         asyncContext->rHdrPixelMap = PixelMapNapi::GetPixelMap(env, argValue[NUM_0]);
617         if (asyncContext->rHdrPixelMap == nullptr) {
618             return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Get arg hdr Pixelmap failed");
619         }
620     } else {
621         return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Input hdr image type mismatch");
622     }
623     if (ParserImageType(env, argValue[NUM_1]) == ImageType::TYPE_PIXEL_MAP) {
624         asyncContext->rPixelMap = PixelMapNapi::GetPixelMap(env, argValue[NUM_1]);
625         if (asyncContext->rPixelMap == nullptr) {
626             return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Get arg sdr Pixelmap failed");
627         }
628     } else {
629         return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Input sdr image type mismatch");
630     }
631     CreatePictureByHdrAndSdrPixelMapExec(env, static_cast<void*>((asyncContext).get()));
632     status = napi_get_reference_value(env, sConstructor_, &constructor);
633     if (IMG_IS_OK(status)) {
634         sPicture_ = std::move(asyncContext->rPicture);
635         status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
636     }
637     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to create picture sync"));
638     IMAGE_LOGD("CreatePictureByHdrAndSdrPixelMap OUT");
639     return result;
640 }
641 
ThrowExceptionError(napi_env env,const std::string & tag,const std::uint32_t & code,const std::string & info)642 napi_value PictureNapi::ThrowExceptionError(napi_env env,
643     const std::string &tag, const std::uint32_t &code, const std::string &info)
644 {
645     auto errNode = ETS_API_ERROR_CODE.find(tag);
646     if (errNode != ETS_API_ERROR_CODE.end() &&
647         errNode->second.find(code) != errNode->second.end()) {
648         return ImageNapiUtils::ThrowExceptionError(env, code, info);
649     }
650     return ImageNapiUtils::ThrowExceptionError(env, ERROR, "Operation failed");
651 }
652 
CreatePictureFromParcel(napi_env env,napi_callback_info info)653 napi_value PictureNapi::CreatePictureFromParcel(napi_env env, napi_callback_info info)
654 {
655     if (sConstructor_ == nullptr) {
656         napi_value exports = nullptr;
657         napi_create_object(env, &exports);
658         PictureNapi::Init(env, exports);
659     }
660     napi_value result = nullptr;
661     napi_get_undefined(env, &result);
662     napi_status status;
663     napi_value thisVar = nullptr;
664     napi_value argValue[NUM_1] = {0};
665     size_t argCount = NUM_1;
666     IMAGE_LOGD("Call CreatePictureFromParcel");
667     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
668     if (!IMG_IS_OK(status) || argCount != NUM_1) {
669         return PictureNapi::ThrowExceptionError(env,
670             CREATE_PICTURE_FROM_PARCEL, IMAGE_BAD_PARAMETER, "Fail to napi_get_cb_info");
671     }
672     napi_unwrap(env, argValue[NUM_0], (void **)&messageSequence);
673     if (messageSequence == nullptr) {
674         return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Fail to unwrap messageSequence");
675     }
676     auto messageParcel = messageSequence->GetMessageParcel();
677     if (messageParcel == nullptr) {
678         return ImageNapiUtils::ThrowExceptionError(env, ERR_IPC, "Get parcel failed");
679     }
680     PICTURE_ERR error;
681     auto picture = Picture::Unmarshalling(*messageParcel, error);
682     if (!IMG_NOT_NULL(picture)) {
683         return ImageNapiUtils::ThrowExceptionError(env, ERR_IPC, "Unmarshalling picture failed");
684     }
685     std::shared_ptr<OHOS::Media::Picture> picturePtr(picture);
686     sPicture_ = std::move(picturePtr);
687     napi_value constructor = nullptr;
688     status = napi_get_reference_value(env, sConstructor_, &constructor);
689     if (IMG_IS_OK(status)) {
690         if (sPicture_ == nullptr) {
691             status = napi_invalid_arg;
692             IMAGE_LOGE("NewPictureNapiInstance picture is nullptr");
693         } else {
694             status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
695         }
696     }
697     if (!IMG_IS_OK(status)) {
698         IMAGE_LOGE("New instance could not be obtained");
699         return PictureNapi::ThrowExceptionError(env,
700             CREATE_PICTURE_FROM_PARCEL, ERR_IMAGE_NAPI_ERROR, "New instance could not be obtained");
701     }
702     return result;
703 }
GetMainPixelmap(napi_env env,napi_callback_info info)704 napi_value PictureNapi::GetMainPixelmap(napi_env env, napi_callback_info info)
705 {
706     NapiValues nVal;
707     napi_get_undefined(env, &nVal.result);
708     nVal.argc = NUM_0;
709     IMG_JS_ARGS(env, info, nVal.status, nVal.argc, nullptr, nVal.thisVar);
710     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(nVal.status), nVal.result, IMAGE_LOGE("Fail to arg info"));
711 
712     PictureNapi* pictureNapi = nullptr;
713     nVal.status = napi_unwrap(env, nVal.thisVar, reinterpret_cast<void**>(&pictureNapi));
714 
715     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(nVal.status, pictureNapi), nVal.result, IMAGE_LOGE("Fail to unwrap context"));
716 
717     if (pictureNapi->nativePicture_ != nullptr) {
718         auto pixelmap = pictureNapi->nativePicture_->GetMainPixel();
719         nVal.result = PixelMapNapi::CreatePixelMap(env, pixelmap);
720     } else {
721         IMAGE_LOGE("Native picture is nullptr!");
722     }
723     return nVal.result;
724 }
725 
Release(napi_env env,napi_callback_info info)726 napi_value PictureNapi::Release(napi_env env, napi_callback_info info)
727 {
728     NapiValues nVal;
729     nVal.result = nullptr;
730     napi_get_undefined(env, &nVal.result);
731     nVal.argc = NUM_0;
732     IMG_JS_ARGS(env, info, nVal.status, nVal.argc, nullptr, nVal.thisVar);
733     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(nVal.status), nVal.result, IMAGE_LOGE("Fail to arg info"));
734 
735     PictureNapi *picturenapi = nullptr;
736     nVal.status = napi_remove_wrap(env, nVal.thisVar, reinterpret_cast<void**>(&picturenapi));
737 
738     return nVal.result;
739 }
740 
Marshalling(napi_env env,napi_callback_info info)741 napi_value PictureNapi::Marshalling(napi_env env, napi_callback_info info)
742 {
743 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
744     NapiValues nVal;
745     nVal.argc = NUM_1;
746     napi_value argValue[NUM_1] = {0};
747     nVal.argv = argValue;
748     if (!prepareNapiEnv(env, info, &nVal)) {
749         return ImageNapiUtils::ThrowExceptionError(
750             env, IMAGE_BAD_PARAMETER, "Fail to unwrap context");
751     }
752     nVal.context->rPicture = nVal.context->nConstructor->nativePicture_;
753     if (nVal.argc != NUM_0 && nVal.argc != NUM_1) {
754         return ImageNapiUtils::ThrowExceptionError(
755             env, IMAGE_BAD_PARAMETER, "Invalid args count");
756     }
757     NAPI_MessageSequence *napiSequence = nullptr;
758     napi_get_cb_info(env, info, &nVal.argc, nVal.argv, nullptr, nullptr);
759     napi_unwrap(env, nVal.argv[0], reinterpret_cast<void**>(&napiSequence));
760     if (napiSequence == nullptr) {
761         return ImageNapiUtils::ThrowExceptionError(
762             env, IMAGE_BAD_PARAMETER, "Marshalling picture napi_unwrap failed.");
763     }
764     auto messageParcel = napiSequence->GetMessageParcel();
765     if (messageParcel == nullptr) {
766         return ImageNapiUtils::ThrowExceptionError(
767             env, ERR_IPC, "Marshalling picture to parcel failed.");
768     }
769     bool st = nVal.context->rPicture->Marshalling(*messageParcel);
770     if (!st) {
771         return ImageNapiUtils::ThrowExceptionError(
772             env, ERR_IPC, "Marshalling picture to parcel failed.");
773     }
774     return nVal.result;
775 #else
776     return napi_value(nullptr);
777 #endif
778 }
779 
CreateHDRComposedPixelmapComplete(napi_env env,napi_status status,void * data)780 static void CreateHDRComposedPixelmapComplete(napi_env env, napi_status status, void *data)
781 {
782     napi_value result = nullptr;
783     napi_get_undefined(env, &result);
784     auto context = static_cast<PictureAsyncContext*>(data);
785 
786     if (context->rPixelMap != nullptr) {
787         result = PixelMapNapi::CreatePixelMap(env, context->rPixelMap);
788         context->status = SUCCESS;
789     } else {
790         context->status = ERROR;
791     }
792     CommonCallbackRoutine(env, context, result);
793 }
794 
GetHdrComposedPixelMap(napi_env env,napi_callback_info info)795 napi_value PictureNapi::GetHdrComposedPixelMap(napi_env env, napi_callback_info info)
796 {
797     napi_value result = nullptr;
798     napi_get_undefined(env, &result);
799 
800     napi_status status;
801     napi_value thisVar = nullptr;
802     size_t argCount = NUM_0;
803 
804     IMAGE_LOGD("GetHdrComposedPixelMap IN");
805     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
806 
807     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("Fail to napi_get_cb_info"));
808 
809     std::unique_ptr<PictureAsyncContext> asyncContext = std::make_unique<PictureAsyncContext>();
810     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
811     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor), result,
812                          IMAGE_LOGE("Fail to napi_unwrap context"));
813     asyncContext->rPicture = asyncContext->nConstructor->nativePicture_;
814     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPicture),
815         nullptr, IMAGE_LOGE("Empty native pixelmap"));
816     if (asyncContext->rPicture->GetAuxiliaryPicture(AuxiliaryPictureType::GAINMAP) == nullptr) {
817         return ImageNapiUtils::ThrowExceptionError(env, IMAGE_UNSUPPORTED_OPERATION, "There is no GAINMAP");
818     }
819     if (asyncContext->rPicture->GetMainPixel()->GetAllocatorType() != AllocatorType::DMA_ALLOC) {
820         return ImageNapiUtils::ThrowExceptionError(env, IMAGE_UNSUPPORTED_OPERATION, "Unsupported operations");
821     }
822     napi_create_promise(env, &(asyncContext->deferred), &result);
823 
824     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetHdrComposedPixelMap",
825         [](napi_env env, void *data) {
826             auto context = static_cast<PictureAsyncContext*>(data);
827             auto tmpixel = context->rPicture->GetHdrComposedPixelMap();
828             context->rPixelMap = std::move(tmpixel);
829             context->status = SUCCESS;
830         }, CreateHDRComposedPixelmapComplete, asyncContext, asyncContext->work);
831     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
832         nullptr, IMAGE_LOGE("Fail to create async work"));
833 
834     return result;
835 }
836 
GetGainmapPixelmap(napi_env env,napi_callback_info info)837 napi_value PictureNapi::GetGainmapPixelmap(napi_env env, napi_callback_info info)
838 {
839     NapiValues nVal;
840     napi_get_undefined(env, &nVal.result);
841     IMAGE_LOGD("GetGainmapPixelmap");
842     nVal.argc = NUM_0;
843     IMG_JS_ARGS(env, info, nVal.status, nVal.argc, nullptr, nVal.thisVar);
844     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(nVal.status), nVal.result, IMAGE_LOGE("Parameter acquisition failed"));
845 
846     PictureNapi* pictureNapi = nullptr;
847     nVal.status = napi_unwrap(env, nVal.thisVar, reinterpret_cast<void**>(&pictureNapi));
848     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(nVal.status, pictureNapi),
849         nVal.result, IMAGE_LOGE("Failed to retrieve native pointer"));
850 
851     if (pictureNapi->nativePicture_ != nullptr) {
852         auto gainpixelmap = pictureNapi->nativePicture_->GetGainmapPixelMap();
853         nVal.result = PixelMapNapi::CreatePixelMap(env, gainpixelmap);
854     } else {
855         return ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNKNOWN, "Picture is a null pointer");
856     }
857     return nVal.result;
858 }
859 
GetMetadataComplete(napi_env env,napi_status status,void * data)860 static void GetMetadataComplete(napi_env env, napi_status status, void *data)
861 {
862     IMAGE_LOGD("[Picture]GetMetadata IN");
863     napi_value result = nullptr;
864     napi_get_undefined(env, &result);
865     auto context = static_cast<PictureAsyncContext*>(data);
866     if (context->imageMetadata != nullptr) {
867         result = MetadataNapi::CreateMetadata(env, context->imageMetadata);
868     }
869 
870     if (!IMG_IS_OK(status)) {
871         context->status = ERROR;
872         IMAGE_LOGE("Get Metadata failed!");
873     } else {
874         context->status = SUCCESS;
875     }
876     IMAGE_LOGD("[Picture]GetMetadata OUT");
877     CommonCallbackRoutine(env, context, result);
878 }
879 
CreateGetMetadataAsyncWork(napi_env env,napi_status & status,std::unique_ptr<PictureAsyncContext> & asyncContext,napi_value & result,uint32_t metadataType)880 void CreateGetMetadataAsyncWork(napi_env env, napi_status& status,
881                                 std::unique_ptr<PictureAsyncContext>& asyncContext,
882                                 napi_value& result, uint32_t metadataType)
883 {
884     asyncContext->metadataType = static_cast<MetadataType>(metadataType);
885     napi_create_promise(env, &(asyncContext->deferred), &result);
886     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetMetadata",
887         [](napi_env env, void* data) {
888             auto context = static_cast<PictureAsyncContext*>(data);
889             context->imageMetadata = context->rPicture->GetMetadata(context->metadataType);
890         }, GetMetadataComplete, asyncContext, asyncContext->work);
891 }
892 
GetMetadata(napi_env env,napi_callback_info info)893 napi_value PictureNapi::GetMetadata(napi_env env, napi_callback_info info)
894 {
895     napi_value result = nullptr;
896     napi_get_undefined(env, &result);
897     napi_status status;
898     napi_value thisVar = nullptr;
899     size_t argCount = NUM_1;
900     napi_value argValue[NUM_1] = {0};
901     uint32_t metadataType = 0;
902 
903     IMAGE_LOGD("GetMetadata IN");
904     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
905     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("Fail to get argment from info"));
906     std::unique_ptr<PictureAsyncContext> asyncContext = std::make_unique<PictureAsyncContext>();
907     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
908     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
909         nullptr, IMAGE_LOGE("Fail to unwrap context"));
910     asyncContext->rPicture = asyncContext->nConstructor->nativePicture_;
911     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPicture), nullptr, IMAGE_LOGE("Empty native picture"));
912     status = napi_get_value_uint32(env, argValue[NUM_0], &metadataType);
913     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
914         ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
915         "Fail to get metadata type"), IMAGE_LOGE("Fail to get metadata type"));
916     if (!Picture::IsValidPictureMetadataType(static_cast<MetadataType>(metadataType))) {
917         return ImageNapiUtils::ThrowExceptionError(
918             env, IMAGE_UNSUPPORTED_METADATA, "Unsupport MetadataType");
919     }
920     CreateGetMetadataAsyncWork(env, status, asyncContext, result, metadataType);
921     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
922         nullptr, IMAGE_LOGE("Fail to create async work"));
923     return result;
924 }
925 
SetMetadataComplete(napi_env env,napi_status status,void * data)926 static void SetMetadataComplete(napi_env env, napi_status status, void *data)
927 {
928     IMAGE_LOGD("[Picture]SetMetadata IN");
929     auto context = static_cast<PictureAsyncContext*>(data);
930     napi_value result = nullptr;
931     napi_get_undefined(env, &result);
932 
933     if (!IMG_IS_OK(status)) {
934         context->status = ERROR;
935         IMAGE_LOGE("Set Metadata failed!");
936     }
937     IMAGE_LOGD("[Picture]SetMetadata OUT");
938     CommonCallbackRoutine(env, context, result);
939 }
940 
CreateSetMetadataAsyncWork(napi_env env,napi_status & status,std::unique_ptr<PictureAsyncContext> & asyncContext,napi_value & result,uint32_t metadataType)941 void CreateSetMetadataAsyncWork(napi_env env, napi_status& status,
942                                 std::unique_ptr<PictureAsyncContext>& asyncContext,
943                                 napi_value& result, uint32_t metadataType)
944 {
945     asyncContext->metadataType = static_cast<MetadataType>(metadataType);
946     napi_create_promise(env, &(asyncContext->deferred), &result);
947     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "SetMetadata",
948         [](napi_env env, void* data) {
949             auto context = static_cast<PictureAsyncContext*>(data);
950             context->status = context->rPicture->SetMetadata(context->metadataType, context->imageMetadata);
951         }, SetMetadataComplete, asyncContext, asyncContext->work);
952 }
953 
SetMetadata(napi_env env,napi_callback_info info)954 napi_value PictureNapi::SetMetadata(napi_env env, napi_callback_info info)
955 {
956     napi_value result = nullptr;
957     napi_get_undefined(env, &result);
958     napi_status status;
959     napi_value thisVar = nullptr;
960     size_t argCount = NUM_2;
961     napi_value argValue[NUM_2] = {0};
962     uint32_t metadataType = 0;
963 
964     IMAGE_LOGD("SetMetadata IN");
965     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
966     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("Fail to get argments from info"));
967     std::unique_ptr<PictureAsyncContext> asyncContext = std::make_unique<PictureAsyncContext>();
968     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
969     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
970         nullptr, IMAGE_LOGE("Fail to unwrap context"));
971     asyncContext->rPicture = asyncContext->nConstructor->nativePicture_;
972     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPicture), nullptr, IMAGE_LOGE("Empty native picture"));
973 
974     status = napi_get_value_uint32(env, argValue[NUM_0], &metadataType);
975     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
976         ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
977         "Fail to get metadata type"), IMAGE_LOGE("Fail to get metadata type"));
978     if (Picture::IsValidPictureMetadataType(static_cast<MetadataType>(metadataType))) {
979         asyncContext->metadataType = MetadataType(metadataType);
980     } else {
981         return ImageNapiUtils::ThrowExceptionError(
982             env, IMAGE_UNSUPPORTED_METADATA, "Unsupport MetadataType");
983     }
984 
985     status = napi_unwrap(env, argValue[NUM_1], reinterpret_cast<void**>(&asyncContext->metadataNapi));
986     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
987         ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
988         "Fail to unwrap MetadataNapi"), IMAGE_LOGE("Fail to unwrap MetadataNapi"));
989     if (asyncContext->metadataNapi != nullptr) {
990         asyncContext->imageMetadata = asyncContext->metadataNapi->GetNativeMetadata();
991     } else {
992         return ImageNapiUtils::ThrowExceptionError(
993             env, IMAGE_BAD_PARAMETER, "Invalid args Metadata");
994     }
995     CreateSetMetadataAsyncWork(env, status, asyncContext, result, metadataType);
996     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
997         nullptr, IMAGE_LOGE("Fail to create async work"));
998     return result;
999 }
1000 
release()1001 void PictureNapi::release()
1002 {
1003     if (!isRelease) {
1004         if (nativePicture_ != nullptr) {
1005             nativePicture_ = nullptr;
1006         }
1007         isRelease = true;
1008     }
1009 }
1010 }  // namespace Media
1011 }  // namespace OHOS
1012