• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "picture_napi.h"
17 #include "media_errors.h"
18 #include "image_log.h"
19 #include "image_napi_utils.h"
20 #include "image_napi.h"
21 #include "pixel_map_napi.h"
22 #include "auxiliary_picture_napi.h"
23 #include "auxiliary_picture.h"
24 #include "napi_message_sequence.h"
25 #include "metadata.h"
26 #include "metadata_napi.h"
27 #include "image_common.h"
28 
29 #undef LOG_DOMAIN
30 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
31 
32 #undef LOG_TAG
33 #define LOG_TAG "PictureNapi"
34 
35 namespace {
36     constexpr uint32_t NUM_0 = 0;
37     constexpr uint32_t NUM_1 = 1;
38     constexpr uint32_t NUM_2 = 2;
39 }
40 
41 namespace OHOS {
42 namespace Media {
43 static const std::string CREATE_PICTURE_FROM_PARCEL = "createPictureFromParcel";
44 static const std::map<std::string, std::set<uint32_t>> ETS_API_ERROR_CODE = {
45     {CREATE_PICTURE_FROM_PARCEL, {62980096, 62980105, 62980115, 62980097,
46         62980177, 62980178, 62980179, 62980180, 62980246}}
47 };
48 static const std::string CLASS_NAME = "Picture";
49 thread_local napi_ref PictureNapi::sConstructor_ = nullptr;
50 thread_local std::shared_ptr<Picture> PictureNapi::sPicture_ = nullptr;
51 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
52 NAPI_MessageSequence* messageSequence = nullptr;
53 #endif
54 
55 struct PictureAsyncContext {
56     napi_env env;
57     napi_async_work work;
58     napi_deferred deferred;
59     napi_ref callbackRef;
60     napi_ref error = nullptr;
61     uint32_t status;
62     std::shared_ptr<Picture> rPicture;
63     PictureNapi *nConstructor;
64     std::shared_ptr<PixelMap> rPixelMap;
65     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