• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "image_packer_napi.h"
17 #include "hilog/log.h"
18 #include "media_errors.h"
19 #include "image_napi_utils.h"
20 #include "image_packer.h"
21 #include "image_source.h"
22 #include "image_source_napi.h"
23 #include "pixel_map_napi.h"
24 #include "image_trace.h"
25 #include "hitrace_meter.h"
26 
27 using OHOS::HiviewDFX::HiLog;
28 namespace {
29     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "ImagePackerNapi"};
30     constexpr uint32_t NUM_0 = 0;
31     constexpr uint32_t NUM_1 = 1;
32     constexpr uint32_t NUM_2 = 2;
33 }
34 
35 namespace OHOS {
36 namespace Media {
37 static const std::string CLASS_NAME_IMAGEPACKER = "ImagePacker";
38 std::shared_ptr<ImagePacker> ImagePackerNapi::sImgPck_ = nullptr;
39 std::shared_ptr<ImageSource> ImagePackerNapi::sImgSource_ = nullptr;
40 thread_local napi_ref ImagePackerNapi::sConstructor_ = nullptr;
41 
42 const int ARGS_THREE = 3;
43 const int PARAM0 = 0;
44 const int PARAM1 = 1;
45 const int PARAM2 = 2;
46 const int PARAM3 = 3;
47 const uint8_t BYTE_FULL = 0xFF;
48 const int32_t SIZE = 100;
49 const int32_t TYPE_IMAGE_SOURCE = 1;
50 const int32_t TYPE_PIXEL_MAP = 2;
51 const int64_t DEFAULT_BUFFER_SIZE = 25 * 1024 * 1024; // 25M is the maximum default packedSize
52 
53 struct ImagePackerAsyncContext {
54     napi_env env;
55     napi_async_work work;
56     napi_deferred deferred;
57     napi_ref callbackRef = nullptr;
58     napi_ref errorMsg = nullptr;
59     ImagePackerNapi *constructor_;
60     bool status = false;
61     std::shared_ptr<ImageSource> rImageSource;
62     PackOption packOption;
63     std::shared_ptr<ImagePacker> rImagePacker;
64     std::shared_ptr<PixelMap> rPixelMap;
65     std::unique_ptr<uint8_t[]> resultBuffer;
66     int32_t packType = TYPE_IMAGE_SOURCE;
67     int64_t resultBufferSize = 0;
68     int64_t packedSize = 0;
69 };
70 
71 struct PackingOption {
72     std::string format;
73     uint8_t quality = 100;
74 };
75 
ImagePackerNapi()76 ImagePackerNapi::ImagePackerNapi():env_(nullptr)
77 {}
78 
~ImagePackerNapi()79 ImagePackerNapi::~ImagePackerNapi()
80 {
81     release();
82 }
83 
CommonCallbackRoutine(napi_env env,ImagePackerAsyncContext * & connect,const napi_value & valueParam)84 static void CommonCallbackRoutine(napi_env env, ImagePackerAsyncContext* &connect, const napi_value &valueParam)
85 {
86     napi_value result[NUM_2] = {0};
87     napi_value retVal;
88     napi_value callback = nullptr;
89 
90     napi_get_undefined(env, &result[NUM_0]);
91     napi_get_undefined(env, &result[NUM_1]);
92 
93     if (connect->status == SUCCESS) {
94         result[NUM_1] = valueParam;
95     } else if (connect->errorMsg != nullptr) {
96         napi_get_reference_value(env, connect->errorMsg, &result[NUM_0]);
97         napi_delete_reference(env, connect->errorMsg);
98     } else {
99         napi_create_string_utf8(env, "Internal error", NAPI_AUTO_LENGTH, &(result[NUM_0]));
100     }
101 
102     if (connect->deferred) {
103         if (connect->status == SUCCESS) {
104             napi_resolve_deferred(env, connect->deferred, result[NUM_1]);
105         } else {
106             napi_reject_deferred(env, connect->deferred, result[NUM_0]);
107         }
108     } else {
109         napi_get_reference_value(env, connect->callbackRef, &callback);
110         napi_call_function(env, nullptr, callback, PARAM2, result, &retVal);
111         napi_delete_reference(env, connect->callbackRef);
112     }
113 
114     napi_delete_async_work(env, connect->work);
115 
116     delete connect;
117     connect = nullptr;
118 }
119 
BuildMsgOnError(napi_env env,ImagePackerAsyncContext * context,bool assertion,const std::string msg)120 static void BuildMsgOnError(napi_env env,
121     ImagePackerAsyncContext* context, bool assertion, const std::string msg)
122 {
123     napi_value tmpError;
124     napi_status status;
125     if (!assertion) {
126         HiLog::Error(LABEL, "%{public}s", msg.c_str());
127         status = napi_create_string_utf8(env, msg.c_str(), NAPI_AUTO_LENGTH, &tmpError);
128         if (status != napi_ok) {
129             HiLog::Error(LABEL, "Create error msg error");
130             return;
131         }
132         napi_create_reference(env, tmpError, NUM_1, &(context->errorMsg));
133     }
134 }
135 
STATIC_EXEC_FUNC(Packing)136 STATIC_EXEC_FUNC(Packing)
137 {
138     int64_t packedSize = 0;
139     auto context = static_cast<ImagePackerAsyncContext*>(data);
140     HiLog::Debug(LABEL, "image packer get supported format");
141     std::set<std::string> formats;
142     uint32_t ret = context->rImagePacker->GetSupportedFormats(formats);
143     if (ret != SUCCESS) {
144         HiLog::Error(LABEL, "image packer get supported format failed, ret=%{public}u.", ret);
145     }
146     HiLog::Info(LABEL, "ImagePacker BufferSize %{public}" PRId64, context->resultBufferSize);
147     context->resultBuffer = std::make_unique<uint8_t[]>(
148         (context->resultBufferSize <= 0)?DEFAULT_BUFFER_SIZE:context->resultBufferSize);
149     if (context->resultBuffer == nullptr) {
150         BuildMsgOnError(env, context, context->resultBuffer == nullptr, "ImagePacker buffer alloc error");
151         return;
152     }
153     context->rImagePacker->StartPacking(context->resultBuffer.get(),
154         context->resultBufferSize, context->packOption);
155     if (context->packType == TYPE_IMAGE_SOURCE) {
156         HiLog::Info(LABEL, "ImagePacker set image source");
157         if (context->rImageSource == nullptr) {
158             BuildMsgOnError(env, context, context->rImageSource == nullptr, "ImageSource is nullptr");
159             return;
160         }
161         context->rImagePacker->AddImage(*(context->rImageSource));
162     } else {
163         HiLog::Info(LABEL, "ImagePacker set pixelmap");
164         if (context->rPixelMap == nullptr) {
165             BuildMsgOnError(env, context, context->rImageSource == nullptr, "Pixelmap is nullptr");
166             return;
167         }
168         context->rImagePacker->AddImage(*(context->rPixelMap));
169     }
170     context->rImagePacker->FinalizePacking(packedSize);
171     HiLog::Debug(LABEL, "packedSize=%{public}" PRId64, packedSize);
172     if (packedSize > 0 && (packedSize < context->resultBufferSize)) {
173         context->packedSize = packedSize;
174         context->status = SUCCESS;
175     } else {
176         context->status = ERROR;
177         HiLog::Error(LABEL, "Packing failed, packedSize outside size.");
178     }
179 }
180 
STATIC_COMPLETE_FUNC(PackingError)181 STATIC_COMPLETE_FUNC(PackingError)
182 {
183     napi_value result = nullptr;
184     napi_get_undefined(env, &result);
185     auto context = static_cast<ImagePackerAsyncContext*>(data);
186     context->status = ERROR;
187     CommonCallbackRoutine(env, context, result);
188 }
189 
STATIC_COMPLETE_FUNC(Packing)190 STATIC_COMPLETE_FUNC(Packing)
191 {
192     napi_value result = nullptr;
193     napi_get_undefined(env, &result);
194     auto context = static_cast<ImagePackerAsyncContext*>(data);
195 
196     if (!ImageNapiUtils::CreateArrayBuffer(env, context->resultBuffer.get(),
197                                            context->packedSize, &result)) {
198         context->status = ERROR;
199         HiLog::Error(LABEL, "napi_create_arraybuffer failed!");
200         napi_get_undefined(env, &result);
201     } else {
202         context->status = SUCCESS;
203     }
204     context->resultBuffer = nullptr;
205     context->resultBufferSize = 0;
206     CommonCallbackRoutine(env, context, result);
207 }
208 
Init(napi_env env,napi_value exports)209 napi_value ImagePackerNapi::Init(napi_env env, napi_value exports)
210 {
211     napi_property_descriptor props[] = {
212         DECLARE_NAPI_FUNCTION("packing", Packing),
213         DECLARE_NAPI_FUNCTION("packingFromPixelMap", Packing),
214         DECLARE_NAPI_FUNCTION("release", Release),
215         DECLARE_NAPI_GETTER("supportedFormats", GetSupportedFormats),
216     };
217     napi_property_descriptor static_prop[] = {
218         DECLARE_NAPI_STATIC_FUNCTION("createImagePacker", CreateImagePacker),
219     };
220 
221     napi_value constructor = nullptr;
222 
223     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
224         napi_define_class(env, CLASS_NAME_IMAGEPACKER.c_str(), NAPI_AUTO_LENGTH, Constructor,
225         nullptr, IMG_ARRAY_SIZE(props), props, &constructor)), nullptr,
226         HiLog::Error(LABEL, "define class fail")
227     );
228 
229     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
230         napi_create_reference(env, constructor, 1, &sConstructor_)),
231         nullptr,
232         HiLog::Error(LABEL, "create reference fail")
233     );
234 
235     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
236         napi_set_named_property(env, exports, CLASS_NAME_IMAGEPACKER.c_str(), constructor)),
237         nullptr,
238         HiLog::Error(LABEL, "set named property fail")
239     );
240     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(
241         napi_define_properties(env, exports, IMG_ARRAY_SIZE(static_prop), static_prop)),
242         nullptr,
243         HiLog::Error(LABEL, "define properties fail")
244     );
245 
246     HiLog::Debug(LABEL, "Init success");
247     return exports;
248 }
249 
Constructor(napi_env env,napi_callback_info info)250 napi_value ImagePackerNapi::Constructor(napi_env env, napi_callback_info info)
251 {
252     napi_value undefineVar = nullptr;
253     napi_get_undefined(env, &undefineVar);
254 
255     napi_status status;
256     napi_value thisVar = nullptr;
257 
258     status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
259     if (status == napi_ok && thisVar != nullptr) {
260         std::unique_ptr<ImagePackerNapi> pImgPackerNapi = std::make_unique<ImagePackerNapi>();
261         if (pImgPackerNapi != nullptr) {
262             pImgPackerNapi->env_ = env;
263             pImgPackerNapi->nativeImgPck = sImgPck_;
264             status = napi_wrap(env, thisVar, reinterpret_cast<void *>(pImgPackerNapi.get()),
265                                ImagePackerNapi::Destructor, nullptr, nullptr);
266             if (status == napi_ok) {
267                 pImgPackerNapi.release();
268                 return thisVar;
269             } else {
270                 HiLog::Error(LABEL, "Failure wrapping js to native napi");
271             }
272         }
273     }
274 
275     return undefineVar;
276 }
277 
CreateImagePacker(napi_env env,napi_callback_info info)278 napi_value ImagePackerNapi::CreateImagePacker(napi_env env, napi_callback_info info)
279 {
280     StartTrace(HITRACE_TAG_ZIMAGE, "CreateImagePacker");
281     napi_value constructor = nullptr;
282     napi_value result = nullptr;
283     napi_status status;
284 
285     std::shared_ptr<ImagePacker> imagePacker = std::make_shared<ImagePacker>();
286     status = napi_get_reference_value(env, sConstructor_, &constructor);
287     if (IMG_IS_OK(status)) {
288         sImgPck_ = imagePacker;
289         status = napi_new_instance(env, constructor, 0, nullptr, &result);
290         if (status == napi_ok) {
291             return result;
292         } else {
293             HiLog::Error(LABEL, "New instance could not be obtained");
294         }
295     }
296     FinishTrace(HITRACE_TAG_ZIMAGE);
297     return result;
298 }
299 
Destructor(napi_env env,void * nativeObject,void * finalize)300 void ImagePackerNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
301 {
302 }
303 
parseBufferSize(napi_env env,napi_value root)304 static int64_t parseBufferSize(napi_env env, napi_value root)
305 {
306     napi_value tempValue = nullptr;
307     int64_t tmpNumber = DEFAULT_BUFFER_SIZE;
308     if (napi_get_named_property(env, root, "bufferSize", &tempValue) != napi_ok) {
309         HiLog::Info(LABEL, "No bufferSize, Using default");
310         return tmpNumber;
311     }
312     napi_get_value_int64(env, tempValue, &tmpNumber);
313     HiLog::Info(LABEL, "BufferSize is %{public}" PRId64, tmpNumber);
314     if (tmpNumber < 0) {
315         return DEFAULT_BUFFER_SIZE;
316     }
317     return tmpNumber;
318 }
319 
parsePackOptions(napi_env env,napi_value root,PackOption * opts)320 static bool parsePackOptions(napi_env env, napi_value root, PackOption* opts)
321 {
322     napi_value tmpValue = nullptr;
323     uint32_t tmpNumber = 0;
324 
325     if (!GET_NODE_BY_NAME(root, "format", tmpValue)) {
326         HiLog::Error(LABEL, "No format in pack option");
327         return false;
328     }
329 
330     bool isFormatArray = false;
331     napi_is_array(env, tmpValue, &isFormatArray);
332     auto formatType = ImageNapiUtils::getType(env, tmpValue);
333 
334     HiLog::Debug(LABEL, "parsePackOptions format type %{public}d, is array %{public}d",
335         formatType, isFormatArray);
336 
337     char buffer[SIZE] = {0};
338     size_t res = 0;
339     if (napi_string == formatType) {
340         if (napi_get_value_string_utf8(env, tmpValue, buffer, SIZE, &res) != napi_ok) {
341             HiLog::Error(LABEL, "Parse pack option format failed");
342             return false;
343         }
344         opts->format = std::string(buffer);
345     } else if (isFormatArray) {
346         uint32_t len = 0;
347         if (napi_get_array_length(env, tmpValue, &len) != napi_ok) {
348             HiLog::Error(LABEL, "Parse pack napi_get_array_length failed");
349             return false;
350         }
351         HiLog::Debug(LABEL, "Parse pack array_length=%{public}u", len);
352         for (size_t i = 0; i < len; i++) {
353             napi_value item;
354             napi_get_element(env, tmpValue, i, &item);
355             if (napi_get_value_string_utf8(env, item, buffer, SIZE, &res) != napi_ok) {
356                 HiLog::Error(LABEL, "Parse format in item failed %{public}zu", i);
357                 continue;
358             }
359             opts->format = std::string(buffer);
360             HiLog::Debug(LABEL, "format is %{public}s.", opts->format.c_str());
361         }
362     } else {
363         HiLog::Error(LABEL, "Invalid pack option format type");
364         return false;
365     }
366     HiLog::Debug(LABEL, "parsePackOptions format:[%{public}s]", opts->format.c_str());
367 
368     if (!GET_UINT32_BY_NAME(root, "quality", tmpNumber)) {
369         HiLog::Error(LABEL, "No quality in pack option");
370         return false;
371     }
372     if (tmpNumber > SIZE) {
373         HiLog::Error(LABEL, "Invalid quality");
374         opts->quality = BYTE_FULL;
375     } else {
376         opts->quality = static_cast<uint8_t>(tmpNumber & 0xff);
377     }
378     return true;
379 }
380 
ParserPackingArgumentType(napi_env env,napi_value argv)381 static int32_t ParserPackingArgumentType(napi_env env, napi_value argv)
382 {
383     napi_value constructor = nullptr;
384     napi_value global = nullptr;
385     bool isInstance = false;
386     napi_status ret = napi_invalid_arg;
387 
388     napi_get_global(env, &global);
389 
390     ret = napi_get_named_property(env, global, "ImageSource", &constructor);
391     if (ret != napi_ok) {
392         HiLog::Error(LABEL, "Get ImageSourceNapi property failed!");
393     }
394 
395     ret = napi_instanceof(env, argv, constructor, &isInstance);
396     if (ret == napi_ok && isInstance) {
397         HiLog::Debug(LABEL, "This is ImageSourceNapi type!");
398         return TYPE_IMAGE_SOURCE;
399     }
400 
401     ret = napi_get_named_property(env, global, "PixelMap", &constructor);
402     if (ret != napi_ok) {
403         HiLog::Error(LABEL, "Get PixelMapNapi property failed!");
404     }
405 
406     ret = napi_instanceof(env, argv, constructor, &isInstance);
407     if (ret == napi_ok && isInstance) {
408         HiLog::Debug(LABEL, "This is PixelMapNapi type!");
409         return TYPE_PIXEL_MAP;
410     }
411 
412     HiLog::Error(LABEL, "Inalued type!");
413     return TYPE_IMAGE_SOURCE;
414 }
415 
GetImageSourceFromNapi(napi_env env,napi_value value)416 static std::shared_ptr<ImageSource> GetImageSourceFromNapi(napi_env env, napi_value value)
417 {
418     if (env == nullptr || value == nullptr) {
419         HiLog::Error(LABEL, "GetImageSourceFromNapi input is null");
420     }
421     std::unique_ptr<ImageSourceNapi> imageSourceNapi = std::make_unique<ImageSourceNapi>();
422     napi_status status = napi_unwrap(env, value, reinterpret_cast<void**>(&imageSourceNapi));
423     if (!IMG_IS_OK(status)) {
424         HiLog::Error(LABEL, "GetImageSourceFromNapi napi unwrap failed");
425         return nullptr;
426     }
427     if (imageSourceNapi == nullptr) {
428         HiLog::Error(LABEL, "GetImageSourceFromNapi imageSourceNapi is nullptr");
429         return nullptr;
430     }
431     return imageSourceNapi.release()->nativeImgSrc;
432 }
433 
ParserPackingArguments(napi_env env,napi_value * argv,size_t argc,ImagePackerAsyncContext * context)434 static void ParserPackingArguments(napi_env env,
435     napi_value* argv, size_t argc, ImagePackerAsyncContext* context)
436 {
437     int32_t refCount = 1;
438     if (argc < PARAM1 || argc > PARAM3) {
439         BuildMsgOnError(env, context, (argc < PARAM1 || argc > PARAM3), "Arguments Count error");
440     }
441     context->packType = ParserPackingArgumentType(env, argv[PARAM0]);
442     if (context->packType == TYPE_IMAGE_SOURCE) {
443         context->rImageSource = GetImageSourceFromNapi(env, argv[PARAM0]);
444         BuildMsgOnError(env, context, context->rImageSource != nullptr, "ImageSource mismatch");
445     } else {
446         context->rPixelMap = PixelMapNapi::GetPixelMap(env, argv[PARAM0]);
447         BuildMsgOnError(env, context, context->rPixelMap != nullptr, "PixelMap mismatch");
448     }
449     if (argc > PARAM1 && ImageNapiUtils::getType(env, argv[PARAM1]) == napi_object) {
450         BuildMsgOnError(env, context,
451             parsePackOptions(env, argv[PARAM1], &(context->packOption)), "PackOptions mismatch");
452         context->resultBufferSize = parseBufferSize(env, argv[PARAM1]);
453     }
454     if (argc > PARAM2 && ImageNapiUtils::getType(env, argv[PARAM2]) == napi_function) {
455         napi_create_reference(env, argv[PARAM2], refCount, &(context->callbackRef));
456     }
457 }
458 
Packing(napi_env env,napi_callback_info info)459 napi_value ImagePackerNapi::Packing(napi_env env, napi_callback_info info)
460 {
461     StartTrace(HITRACE_TAG_ZIMAGE, "Packing");
462     napi_status status;
463     napi_value result = nullptr;
464     size_t argc = ARGS_THREE;
465     napi_value argv[ARGS_THREE] = {0};
466     napi_value thisVar = nullptr;
467 
468     napi_get_undefined(env, &result);
469 
470     IMG_JS_ARGS(env, info, status, argc, argv, thisVar);
471     NAPI_ASSERT(env, IMG_IS_OK(status), "fail to napi_get_cb_info");
472 
473     std::unique_ptr<ImagePackerAsyncContext> asyncContext = std::make_unique<ImagePackerAsyncContext>();
474     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
475     NAPI_ASSERT(env, IMG_IS_READY(status, asyncContext->constructor_), "fail to unwrap constructor_");
476 
477     asyncContext->rImagePacker = std::move(asyncContext->constructor_->nativeImgPck);
478     ParserPackingArguments(env, argv, argc, asyncContext.get());
479     if (asyncContext->callbackRef == nullptr) {
480         napi_create_promise(env, &(asyncContext->deferred), &result);
481     }
482 
483     ImageNapiUtils::HicheckerReport();
484 
485     if (asyncContext->errorMsg != nullptr) {
486         IMG_CREATE_CREATE_ASYNC_WORK(env, status, "PackingError",
487             [](napi_env env, void *data) {}, PackingErrorComplete, asyncContext, asyncContext->work);
488     } else {
489         IMG_CREATE_CREATE_ASYNC_WORK(env, status, "Packing",
490             PackingExec, PackingComplete, asyncContext, asyncContext->work);
491     }
492 
493     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
494         nullptr, HiLog::Error(LABEL, "fail to create async work"));
495     FinishTrace(HITRACE_TAG_ZIMAGE);
496     return result;
497 }
498 
GetSupportedFormats(napi_env env,napi_callback_info info)499 napi_value ImagePackerNapi::GetSupportedFormats(napi_env env, napi_callback_info info)
500 {
501     napi_value result = nullptr;
502     napi_get_undefined(env, &result);
503 
504     napi_status status;
505     napi_value thisVar = nullptr;
506     size_t argCount = 0;
507 
508     IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
509 
510     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
511 
512     std::unique_ptr<ImagePackerAsyncContext> context = std::make_unique<ImagePackerAsyncContext>();
513     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&context->constructor_));
514 
515     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_),
516         nullptr, HiLog::Error(LABEL, "fail to unwrap context"));
517     std::set<std::string> formats;
518     uint32_t ret = context->constructor_->nativeImgPck->GetSupportedFormats(formats);
519 
520     IMG_NAPI_CHECK_RET_D((ret == SUCCESS),
521         nullptr, HiLog::Error(LABEL, "fail to get supported formats"));
522 
523     napi_create_array(env, &result);
524     size_t i = 0;
525     for (const std::string& formatStr: formats) {
526         napi_value format = nullptr;
527         napi_create_string_latin1(env, formatStr.c_str(), formatStr.length(), &format);
528         napi_set_element(env, result, i, format);
529         i++;
530     }
531     return result;
532 }
533 
ReleaseComplete(napi_env env,napi_status status,void * data)534 static void ReleaseComplete(napi_env env, napi_status status, void *data)
535 {
536     napi_value result = nullptr;
537     napi_get_undefined(env, &result);
538 
539     auto context = static_cast<ImagePackerAsyncContext*>(data);
540     if (context != nullptr && context->constructor_ != nullptr) {
541         delete context->constructor_;
542         context->constructor_ = nullptr;
543     }
544     CommonCallbackRoutine(env, context, result);
545 }
546 
Release(napi_env env,napi_callback_info info)547 napi_value ImagePackerNapi::Release(napi_env env, napi_callback_info info)
548 {
549     StartTrace(HITRACE_TAG_ZIMAGE, "Release");
550     napi_value result = nullptr;
551     napi_get_undefined(env, &result);
552 
553     int32_t refCount = 1;
554     napi_status status;
555     napi_value thisVar = nullptr;
556     napi_value argValue[NUM_1] = {0};
557     size_t argCount = 1;
558 
559     IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
560     HiLog::Debug(LABEL, "Release argCount is [%{public}zu]", argCount);
561     IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, HiLog::Error(LABEL, "fail to napi_get_cb_info"));
562 
563     std::unique_ptr<ImagePackerAsyncContext> context = std::make_unique<ImagePackerAsyncContext>();
564     status = napi_remove_wrap(env, thisVar, reinterpret_cast<void**>(&context->constructor_));
565 
566     IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_), result,
567         HiLog::Error(LABEL, "fail to unwrap context"));
568     HiLog::Debug(LABEL, "Release argCount is [%{public}zu]", argCount);
569     if (argCount == 1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_function) {
570         napi_create_reference(env, argValue[NUM_0], refCount, &context->callbackRef);
571     }
572 
573     if (context->callbackRef == nullptr) {
574         napi_create_promise(env, &(context->deferred), &result);
575     }
576 
577     IMG_CREATE_CREATE_ASYNC_WORK(env, status, "Release",
578         [](napi_env env, void *data) {}, ReleaseComplete, context, context->work);
579     FinishTrace(HITRACE_TAG_ZIMAGE);
580     return result;
581 }
release()582 void ImagePackerNapi::release()
583 {
584     if (!isRelease) {
585         nativeImgPck = nullptr;
586         isRelease = true;
587     }
588 }
589 }  // namespace Media
590 }  // namespace OHOS
591