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 if (pictureNapi->nativePicture_ != nullptr) {
434 auto auxiliaryPic = pictureNapi->nativePicture_->GetAuxiliaryPicture(type);
435 if (auxiliaryPic != nullptr) {
436 result = AuxiliaryPictureNapi::CreateAuxiliaryPicture(env, std::move(auxiliaryPic));
437 } else {
438 IMAGE_LOGE("native auxiliary picture is nullptr!");
439 }
440 } else {
441 IMAGE_LOGE("native picture is nullptr!");
442 }
443 return result;
444 }
445
GetPicture(napi_env env,napi_value picture)446 std::shared_ptr<Picture> PictureNapi::GetPicture(napi_env env, napi_value picture)
447 {
448 PictureNapi *pictureNapi = nullptr;
449 napi_status status = napi_unwrap(env, picture, reinterpret_cast<void**>(&pictureNapi));
450 if (!IMG_IS_OK(status)) {
451 IMAGE_LOGE("GetPicture napi unwrap failed");
452 return nullptr;
453 }
454 if (pictureNapi == nullptr) {
455 IMAGE_LOGE("GetPixelMap pixmapNapi is nullptr");
456 return nullptr;
457 }
458 return pictureNapi->nativePicture_;
459 }
460
SetAuxiliaryPicture(napi_env env,napi_callback_info info)461 napi_value PictureNapi::SetAuxiliaryPicture(napi_env env, napi_callback_info info)
462 {
463 napi_value result = nullptr;
464 napi_get_undefined(env, &result);
465 napi_status status;
466 napi_value thisVar = nullptr;
467 napi_value argValue[NUM_2] = {0};
468 size_t argCount = NUM_2;
469 uint32_t auxiType = 0;
470
471 IMAGE_LOGD("SetAuxiliaryPictureSync IN");
472 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
473 PictureNapi* pictureNapi = nullptr;
474 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pictureNapi));
475 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pictureNapi), result, IMAGE_LOGE("fail to unwrap PictureNapi"));
476
477 status = napi_get_value_uint32(env, argValue[NUM_0], &auxiType);
478 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
479 "Fail to get auxiliary picture type!"), IMAGE_LOGE("Fail to get auxiliary picture Type"));
480 AuxiliaryPictureType type = ParseAuxiliaryPictureType(auxiType);
481 if (type == AuxiliaryPictureType::NONE) {
482 return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
483 "The type does not match the auxiliary picture type!");
484 }
485
486 AuxiliaryPictureNapi* auxiliaryPictureNapi = nullptr;
487 status = napi_unwrap(env, argValue[NUM_1], reinterpret_cast<void**>(&auxiliaryPictureNapi));
488 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, pictureNapi),
489 ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Fail to unwrap AuxiliaryPictureNapi!"),
490 IMAGE_LOGE("Fail to unwrap AuxiliaryPictureNapi"));
491
492 if (pictureNapi->nativePicture_ != nullptr) {
493 auto auxiliaryPicturePtr = auxiliaryPictureNapi->GetNativeAuxiliaryPic();
494 if (auxiliaryPicturePtr != nullptr) {
495 if (type != auxiliaryPicturePtr->GetAuxiliaryPictureInfo().auxiliaryPictureType) {
496 return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
497 "The type does not match the auxiliary picture type!");
498 } else {
499 pictureNapi->nativePicture_->SetAuxiliaryPicture(auxiliaryPicturePtr);
500 }
501 } else {
502 return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
503 "Native auxiliary picture is nullptr!");
504 }
505 } else {
506 IMAGE_LOGE("native picture is nullptr!");
507 }
508
509 return result;
510 }
511
STATIC_EXEC_FUNC(CreatePicture)512 STATIC_EXEC_FUNC(CreatePicture)
513 {
514 IMAGE_INFO("CreatePictureEX IN");
515 auto context = static_cast<PictureAsyncContext*>(data);
516 auto picture = Picture::Create(context->rPixelMap);
517 context->rPicture = std::move(picture);
518 IMAGE_INFO("CreatePictureEX OUT");
519 if (IMG_NOT_NULL(context->rPicture)) {
520 context->status = SUCCESS;
521 } else {
522 context->status = ERROR;
523 }
524 }
525
CreatePicture(napi_env env,napi_callback_info info)526 napi_value PictureNapi::CreatePicture(napi_env env, napi_callback_info info)
527 {
528 IMAGE_INFO("CreatePicture IN");
529 if (sConstructor_ == nullptr) {
530 napi_value exports = nullptr;
531 napi_create_object(env, &exports);
532 PictureNapi::Init(env, exports);
533 }
534 napi_value result = nullptr;
535 napi_get_undefined(env, &result);
536 napi_value constructor = nullptr;
537 napi_status status;
538 napi_value thisVar = nullptr;
539 napi_value argValue[NUM_1] = {0};
540 size_t argCount = NUM_1;
541 IMAGE_LOGD("CreatePicture IN");
542 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
543 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
544 "Invalid args"), IMAGE_LOGE("fail to napi_get_cb_info"));
545 IMG_NAPI_CHECK_RET_D(argCount == NUM_1, ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
546 "Invalid args count"), IMAGE_LOGE("Invalid args count %{public}zu", argCount));
547 std::unique_ptr<PictureAsyncContext> asyncContext = std::make_unique<PictureAsyncContext>();
548 if (ParserImageType(env, argValue[NUM_0]) == ImageType::TYPE_PIXEL_MAP) {
549 asyncContext->rPixelMap = PixelMapNapi::GetPixelMap(env, argValue[NUM_0]);
550 if (asyncContext->rPixelMap == nullptr) {
551 return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Get arg pixelmap failed");
552 }
553 } else {
554 return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Input image type mismatch");
555 }
556 CreatePictureExec(env, static_cast<void*>((asyncContext).get()));
557 status = napi_get_reference_value(env, sConstructor_, &constructor);
558 if (IMG_IS_OK(status)) {
559 sPicture_ = std::move(asyncContext->rPicture);
560 status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
561 }
562 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to create picture sync"));
563 IMAGE_INFO("CreatePicture OUT");
564 return result;
565 }
566
ThrowExceptionError(napi_env env,const std::string & tag,const std::uint32_t & code,const std::string & info)567 napi_value PictureNapi::ThrowExceptionError(napi_env env,
568 const std::string &tag, const std::uint32_t &code, const std::string &info)
569 {
570 auto errNode = ETS_API_ERROR_CODE.find(tag);
571 if (errNode != ETS_API_ERROR_CODE.end() &&
572 errNode->second.find(code) != errNode->second.end()) {
573 return ImageNapiUtils::ThrowExceptionError(env, code, info);
574 }
575 return ImageNapiUtils::ThrowExceptionError(env, ERROR, "Operation failed");
576 }
577
CreatePictureFromParcel(napi_env env,napi_callback_info info)578 napi_value PictureNapi::CreatePictureFromParcel(napi_env env, napi_callback_info info)
579 {
580 if (sConstructor_ == nullptr) {
581 napi_value exports = nullptr;
582 napi_create_object(env, &exports);
583 PictureNapi::Init(env, exports);
584 }
585 napi_value result = nullptr;
586 napi_get_undefined(env, &result);
587 napi_status status;
588 napi_value thisVar = nullptr;
589 napi_value argValue[NUM_1] = {0};
590 size_t argCount = NUM_1;
591 IMAGE_LOGD("Call CreatePictureFromParcel");
592 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
593 if (!IMG_IS_OK(status) || argCount != NUM_1) {
594 return PictureNapi::ThrowExceptionError(env,
595 CREATE_PICTURE_FROM_PARCEL, IMAGE_BAD_PARAMETER, "Fail to napi_get_cb_info");
596 }
597 napi_unwrap(env, argValue[NUM_0], (void **)&messageSequence);
598 if (messageSequence == nullptr) {
599 return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, "Fail to unwrap messageSequence");
600 }
601 auto messageParcel = messageSequence->GetMessageParcel();
602 if (messageParcel == nullptr) {
603 return ImageNapiUtils::ThrowExceptionError(env, ERR_IPC, "Get parcel failed");
604 }
605 PICTURE_ERR error;
606 auto picture = Picture::Unmarshalling(*messageParcel, error);
607 if (!IMG_NOT_NULL(picture)) {
608 return ImageNapiUtils::ThrowExceptionError(env, ERR_IPC, "Unmarshalling picture failed");
609 }
610 std::shared_ptr<OHOS::Media::Picture> picturePtr(picture);
611 sPicture_ = std::move(picturePtr);
612 napi_value constructor = nullptr;
613 status = napi_get_reference_value(env, sConstructor_, &constructor);
614 if (IMG_IS_OK(status)) {
615 if (sPicture_ == nullptr) {
616 status = napi_invalid_arg;
617 IMAGE_LOGE("NewPictureNapiInstance picture is nullptr");
618 } else {
619 status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
620 }
621 }
622 if (!IMG_IS_OK(status)) {
623 IMAGE_LOGE("New instance could not be obtained");
624 return PictureNapi::ThrowExceptionError(env,
625 CREATE_PICTURE_FROM_PARCEL, ERR_IMAGE_NAPI_ERROR, "New instance could not be obtained");
626 }
627 return result;
628 }
GetMainPixelmap(napi_env env,napi_callback_info info)629 napi_value PictureNapi::GetMainPixelmap(napi_env env, napi_callback_info info)
630 {
631 NapiValues nVal;
632 napi_get_undefined(env, &nVal.result);
633 nVal.argc = NUM_0;
634 IMG_JS_ARGS(env, info, nVal.status, nVal.argc, nullptr, nVal.thisVar);
635 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(nVal.status), nVal.result, IMAGE_LOGE("Fail to arg info"));
636
637 PictureNapi* pictureNapi = nullptr;
638 nVal.status = napi_unwrap(env, nVal.thisVar, reinterpret_cast<void**>(&pictureNapi));
639
640 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(nVal.status, pictureNapi), nVal.result, IMAGE_LOGE("Fail to unwrap context"));
641
642 if (pictureNapi->nativePicture_ != nullptr) {
643 auto pixelmap = pictureNapi->nativePicture_->GetMainPixel();
644 nVal.result = PixelMapNapi::CreatePixelMap(env, pixelmap);
645 } else {
646 IMAGE_LOGE("Native picture is nullptr!");
647 }
648 return nVal.result;
649 }
650
Release(napi_env env,napi_callback_info info)651 napi_value PictureNapi::Release(napi_env env, napi_callback_info info)
652 {
653 NapiValues nVal;
654 nVal.result = nullptr;
655 napi_get_undefined(env, &nVal.result);
656 nVal.argc = NUM_0;
657 IMG_JS_ARGS(env, info, nVal.status, nVal.argc, nullptr, nVal.thisVar);
658 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(nVal.status), nVal.result, IMAGE_LOGE("Fail to arg info"));
659
660 PictureNapi *picturenapi = nullptr;
661 nVal.status = napi_remove_wrap(env, nVal.thisVar, reinterpret_cast<void**>(&picturenapi));
662
663 return nVal.result;
664 }
665
Marshalling(napi_env env,napi_callback_info info)666 napi_value PictureNapi::Marshalling(napi_env env, napi_callback_info info)
667 {
668 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
669 NapiValues nVal;
670 nVal.argc = NUM_1;
671 napi_value argValue[NUM_1] = {0};
672 nVal.argv = argValue;
673 if (!prepareNapiEnv(env, info, &nVal)) {
674 return ImageNapiUtils::ThrowExceptionError(
675 env, IMAGE_BAD_PARAMETER, "Fail to unwrap context");
676 }
677 nVal.context->rPicture = nVal.context->nConstructor->nativePicture_;
678 if (nVal.argc != NUM_0 && nVal.argc != NUM_1) {
679 return ImageNapiUtils::ThrowExceptionError(
680 env, IMAGE_BAD_PARAMETER, "Invalid args count");
681 }
682 NAPI_MessageSequence *napiSequence = nullptr;
683 napi_get_cb_info(env, info, &nVal.argc, nVal.argv, nullptr, nullptr);
684 napi_unwrap(env, nVal.argv[0], reinterpret_cast<void**>(&napiSequence));
685 if (napiSequence == nullptr) {
686 return ImageNapiUtils::ThrowExceptionError(
687 env, IMAGE_BAD_PARAMETER, "Marshalling picture napi_unwrap failed.");
688 }
689 auto messageParcel = napiSequence->GetMessageParcel();
690 if (messageParcel == nullptr) {
691 return ImageNapiUtils::ThrowExceptionError(
692 env, ERR_IPC, "Marshalling picture to parcel failed.");
693 }
694 bool st = nVal.context->rPicture->Marshalling(*messageParcel);
695 if (!st) {
696 return ImageNapiUtils::ThrowExceptionError(
697 env, ERR_IPC, "Marshalling picture to parcel failed.");
698 }
699 return nVal.result;
700 #else
701 return napi_value(nullptr);
702 #endif
703 }
704
CreateHDRComposedPixelmapComplete(napi_env env,napi_status status,void * data)705 static void CreateHDRComposedPixelmapComplete(napi_env env, napi_status status, void *data)
706 {
707 napi_value result = nullptr;
708 napi_get_undefined(env, &result);
709 auto context = static_cast<PictureAsyncContext*>(data);
710
711 if (context->rPixelMap != nullptr) {
712 result = PixelMapNapi::CreatePixelMap(env, context->rPixelMap);
713 context->status = SUCCESS;
714 } else {
715 context->status = ERROR;
716 }
717 CommonCallbackRoutine(env, context, result);
718 }
719
GetHdrComposedPixelMap(napi_env env,napi_callback_info info)720 napi_value PictureNapi::GetHdrComposedPixelMap(napi_env env, napi_callback_info info)
721 {
722 napi_value result = nullptr;
723 napi_get_undefined(env, &result);
724
725 napi_status status;
726 napi_value thisVar = nullptr;
727 size_t argCount = NUM_0;
728
729 IMAGE_LOGD("GetHdrComposedPixelMap IN");
730 IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
731
732 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("Fail to napi_get_cb_info"));
733
734 std::unique_ptr<PictureAsyncContext> asyncContext = std::make_unique<PictureAsyncContext>();
735 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
736 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor), result,
737 IMAGE_LOGE("Fail to napi_unwrap context"));
738 asyncContext->rPicture = asyncContext->nConstructor->nativePicture_;
739 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPicture),
740 nullptr, IMAGE_LOGE("Empty native pixelmap"));
741 if (asyncContext->rPicture->GetAuxiliaryPicture(AuxiliaryPictureType::GAINMAP) == nullptr) {
742 return ImageNapiUtils::ThrowExceptionError(env, IMAGE_UNSUPPORTED_OPERATION, "There is no GAINMAP");
743 }
744 if (asyncContext->rPicture->GetMainPixel()->GetAllocatorType() != AllocatorType::DMA_ALLOC) {
745 return ImageNapiUtils::ThrowExceptionError(env, IMAGE_UNSUPPORTED_OPERATION, "Unsupported operations");
746 }
747 napi_create_promise(env, &(asyncContext->deferred), &result);
748
749 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetHdrComposedPixelMap",
750 [](napi_env env, void *data) {
751 auto context = static_cast<PictureAsyncContext*>(data);
752 auto tmpixel = context->rPicture->GetHdrComposedPixelMap();
753 context->rPixelMap = std::move(tmpixel);
754 context->status = SUCCESS;
755 }, CreateHDRComposedPixelmapComplete, asyncContext, asyncContext->work);
756 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
757 nullptr, IMAGE_LOGE("Fail to create async work"));
758
759 return result;
760 }
761
GetGainmapPixelmap(napi_env env,napi_callback_info info)762 napi_value PictureNapi::GetGainmapPixelmap(napi_env env, napi_callback_info info)
763 {
764 NapiValues nVal;
765 napi_get_undefined(env, &nVal.result);
766 IMAGE_LOGD("GetGainmapPixelmap");
767 nVal.argc = NUM_0;
768 IMG_JS_ARGS(env, info, nVal.status, nVal.argc, nullptr, nVal.thisVar);
769 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(nVal.status), nVal.result, IMAGE_LOGE("Parameter acquisition failed"));
770
771 PictureNapi* pictureNapi = nullptr;
772 nVal.status = napi_unwrap(env, nVal.thisVar, reinterpret_cast<void**>(&pictureNapi));
773 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(nVal.status, pictureNapi),
774 nVal.result, IMAGE_LOGE("Failed to retrieve native pointer"));
775
776 if (pictureNapi->nativePicture_ != nullptr) {
777 auto gainpixelmap = pictureNapi->nativePicture_->GetGainmapPixelMap();
778 nVal.result = PixelMapNapi::CreatePixelMap(env, gainpixelmap);
779 } else {
780 return ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNKNOWN, "Picture is a null pointer");
781 }
782 return nVal.result;
783 }
784
GetMetadataComplete(napi_env env,napi_status status,void * data)785 static void GetMetadataComplete(napi_env env, napi_status status, void *data)
786 {
787 IMAGE_LOGD("[Picture]GetMetadata IN");
788 napi_value result = nullptr;
789 napi_get_undefined(env, &result);
790 auto context = static_cast<PictureAsyncContext*>(data);
791 if (context->imageMetadata != nullptr) {
792 result = MetadataNapi::CreateMetadata(env, context->imageMetadata);
793 }
794
795 if (!IMG_IS_OK(status)) {
796 context->status = ERROR;
797 IMAGE_LOGE("Get Metadata failed!");
798 } else {
799 context->status = SUCCESS;
800 }
801 IMAGE_LOGD("[Picture]GetMetadata OUT");
802 CommonCallbackRoutine(env, context, result);
803 }
804
GetMetadata(napi_env env,napi_callback_info info)805 napi_value PictureNapi::GetMetadata(napi_env env, napi_callback_info info)
806 {
807 napi_value result = nullptr;
808 napi_get_undefined(env, &result);
809 napi_status status;
810 napi_value thisVar = nullptr;
811 size_t argCount = NUM_1;
812 napi_value argValue[NUM_1] = {0};
813 uint32_t metadataType = 0;
814
815 IMAGE_LOGD("GetMetadata IN");
816 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
817 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("Fail to get argment from info"));
818 std::unique_ptr<PictureAsyncContext> asyncContext = std::make_unique<PictureAsyncContext>();
819 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
820 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
821 nullptr, IMAGE_LOGE("Fail to unwrap context"));
822 asyncContext->rPicture = asyncContext->nConstructor->nativePicture_;
823 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPicture), nullptr, IMAGE_LOGE("Empty native picture"));
824 status = napi_get_value_uint32(env, argValue[NUM_0], &metadataType);
825 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
826 ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
827 "Fail to get metadata type"), IMAGE_LOGE("Fail to get metadata type"));
828 if (metadataType != static_cast<uint32_t>(MetadataType::EXIF)) {
829 return ImageNapiUtils::ThrowExceptionError(
830 env, IMAGE_UNSUPPORTED_METADATA, "Unsupport MetadataType");
831 }
832
833 napi_create_promise(env, &(asyncContext->deferred), &result);
834 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetMetadata",
835 [](napi_env env, void* data) {
836 auto context = static_cast<PictureAsyncContext*>(data);
837 context->imageMetadata = std::reinterpret_pointer_cast<ImageMetadata>(context->rPicture->GetExifMetadata());
838 }, GetMetadataComplete, asyncContext, asyncContext->work);
839 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
840 nullptr, IMAGE_LOGE("Fail to create async work"));
841 return result;
842 }
843
SetMetadataComplete(napi_env env,napi_status status,void * data)844 static void SetMetadataComplete(napi_env env, napi_status status, void *data)
845 {
846 IMAGE_LOGD("[Picture]SetMetadata IN");
847 auto context = static_cast<PictureAsyncContext*>(data);
848 napi_value result = nullptr;
849 napi_get_undefined(env, &result);
850
851 if (!IMG_IS_OK(status)) {
852 context->status = ERROR;
853 IMAGE_LOGE("Set Metadata failed!");
854 }
855 IMAGE_LOGD("[Picture]SetMetadata OUT");
856 CommonCallbackRoutine(env, context, result);
857 }
858
SetMetadata(napi_env env,napi_callback_info info)859 napi_value PictureNapi::SetMetadata(napi_env env, napi_callback_info info)
860 {
861 napi_value result = nullptr;
862 napi_get_undefined(env, &result);
863 napi_status status;
864 napi_value thisVar = nullptr;
865 size_t argCount = NUM_2;
866 napi_value argValue[NUM_2] = {0};
867 uint32_t metadataType = 0;
868
869 IMAGE_LOGD("SetMetadata IN");
870 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
871 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("Fail to get argments from info"));
872 std::unique_ptr<PictureAsyncContext> asyncContext = std::make_unique<PictureAsyncContext>();
873 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor));
874 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor),
875 nullptr, IMAGE_LOGE("Fail to unwrap context"));
876 asyncContext->rPicture = asyncContext->nConstructor->nativePicture_;
877 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rPicture), nullptr, IMAGE_LOGE("Empty native picture"));
878
879 status = napi_get_value_uint32(env, argValue[NUM_0], &metadataType);
880 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
881 ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
882 "Fail to get metadata type"), IMAGE_LOGE("Fail to get metadata type"));
883 if (metadataType == static_cast<uint32_t>(MetadataType::EXIF)) {
884 asyncContext->metadataType = MetadataType(metadataType);
885 } else {
886 return ImageNapiUtils::ThrowExceptionError(
887 env, IMAGE_UNSUPPORTED_METADATA, "Unsupport MetadataType");
888 }
889
890 status = napi_unwrap(env, argValue[NUM_1], reinterpret_cast<void**>(&asyncContext->metadataNapi));
891 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
892 ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
893 "Fail to unwrap MetadataNapi"), IMAGE_LOGE("Fail to unwrap MetadataNapi"));
894 if (asyncContext->metadataNapi != nullptr) {
895 asyncContext->imageMetadata = asyncContext->metadataNapi->GetNativeMetadata();
896 } else {
897 return ImageNapiUtils::ThrowExceptionError(
898 env, IMAGE_BAD_PARAMETER, "Invalid args Metadata");
899 }
900
901 napi_create_promise(env, &(asyncContext->deferred), &result);
902 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "SetMetadata",
903 [](napi_env env, void* data) {
904 auto context = static_cast<PictureAsyncContext*>(data);
905 context->status = context->rPicture->SetExifMetadata(
906 std::reinterpret_pointer_cast<ExifMetadata>(context->imageMetadata));
907 }, SetMetadataComplete, asyncContext, asyncContext->work);
908 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
909 nullptr, IMAGE_LOGE("Fail to create async work"));
910 return result;
911 }
912
release()913 void PictureNapi::release()
914 {
915 if (!isRelease) {
916 if (nativePicture_ != nullptr) {
917 nativePicture_ = nullptr;
918 }
919 isRelease = true;
920 }
921 }
922 } // namespace Media
923 } // namespace OHOS
924