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