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