1 /*
2 * Copyright (C) 2022 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_napi.h"
17
18 #include "napi/native_node_api.h"
19 #include "image_log.h"
20 #include "media_errors.h"
21 #include "image_format.h"
22 #include "image_napi_utils.h"
23
24 #undef LOG_DOMAIN
25 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
26
27 #undef LOG_TAG
28 #define LOG_TAG "ImageNapi"
29
30 namespace {
31 constexpr int NUM0 = 0;
32 constexpr int NUM1 = 1;
33 constexpr int NUM2 = 2;
34 const std::string MY_NAME = "ImageNapi";
35 }
36
37 namespace OHOS {
38 namespace Media {
39 struct ImageAsyncContext {
40 napi_env env = nullptr;
41 napi_async_work work = nullptr;
42 napi_deferred deferred = nullptr;
43 napi_ref callbackRef = nullptr;
44 napi_ref thisRef = nullptr;
45 ImageNapi *napi = nullptr;
46 uint32_t status;
47 int32_t componentType;
48 NativeImage* image = nullptr;
49 NativeComponent* component = nullptr;
50 bool isTestContext = false;
51 };
52 ImageHolderManager<NativeImage> ImageNapi::sNativeImageHolder_;
53 thread_local napi_ref ImageNapi::sConstructor_ = nullptr;
54
ImageNapi()55 ImageNapi::ImageNapi()
56 {}
57
~ImageNapi()58 ImageNapi::~ImageNapi()
59 {
60 NativeRelease();
61 }
62
NativeRelease()63 void ImageNapi::NativeRelease()
64 {
65 if (native_ != nullptr) {
66 native_->release();
67 native_ = nullptr;
68 }
69 }
70
Init(napi_env env,napi_value exports)71 napi_value ImageNapi::Init(napi_env env, napi_value exports)
72 {
73 IMAGE_FUNCTION_IN();
74 napi_property_descriptor props[] = {
75 DECLARE_NAPI_GETTER("clipRect", JSGetClipRect),
76 DECLARE_NAPI_GETTER("size", JsGetSize),
77 DECLARE_NAPI_GETTER("format", JsGetFormat),
78 DECLARE_NAPI_FUNCTION("getComponent", JsGetComponent),
79 DECLARE_NAPI_FUNCTION("release", JsRelease),
80 };
81 size_t size = IMG_ARRAY_SIZE(props);
82 napi_value thisVar = nullptr;
83 auto name = MY_NAME.c_str();
84 if (napi_define_class(env, name, SIZE_MAX, Constructor, nullptr, size, props, &thisVar) != napi_ok) {
85 IMAGE_ERR("Define class failed");
86 return exports;
87 }
88
89 if (sConstructor_ != nullptr) {
90 napi_delete_reference(env, sConstructor_);
91 sConstructor_ = nullptr;
92 }
93
94 if (napi_create_reference(env, thisVar, NUM1, &sConstructor_) != napi_ok) {
95 IMAGE_ERR("Create reference failed");
96 return exports;
97 }
98
99 if (napi_set_named_property(env, exports, name, thisVar) != napi_ok) {
100 IMAGE_ERR("Define class failed");
101 return exports;
102 }
103
104 IMAGE_DEBUG("Init success");
105 return exports;
106 }
107
108
GetNativeImage(napi_env env,napi_value image)109 std::shared_ptr<NativeImage> ImageNapi::GetNativeImage(napi_env env, napi_value image)
110 {
111 ImageNapi* napi = nullptr;
112
113 napi_status status = napi_unwrap(env, image, reinterpret_cast<void**>(&napi));
114 if (!IMG_IS_OK(status) || napi == nullptr) {
115 IMAGE_ERR("GetImage napi unwrap failed");
116 return nullptr;
117 }
118 return napi->native_;
119 }
120
Constructor(napi_env env,napi_callback_info info)121 napi_value ImageNapi::Constructor(napi_env env, napi_callback_info info)
122 {
123 napi_status status;
124 napi_value thisVar = nullptr;
125 napi_value undefineVar;
126 size_t argc = NUM1;
127 napi_value argv[NUM1];
128
129 IMAGE_FUNCTION_IN();
130 napi_get_undefined(env, &undefineVar);
131 status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
132 if (status != napi_ok || thisVar == nullptr || argc != NUM1) {
133 IMAGE_ERR("Constructor Failed to napi_get_cb_info");
134 return undefineVar;
135 }
136 std::string id;
137 if (!ImageNapiUtils::GetUtf8String(env, argv[NUM0], id) || (id.size() == NUM0)) {
138 IMAGE_ERR("Failed to parse native image id");
139 return undefineVar;
140 }
141 std::unique_ptr<ImageNapi> napi = std::make_unique<ImageNapi>();
142 napi->native_ = sNativeImageHolder_.get(id);
143 napi->isTestImage_ = false;
144 if (napi->native_ == nullptr) {
145 if (MY_NAME.compare(id.c_str()) == 0) {
146 napi->isTestImage_ = true;
147 } else {
148 IMAGE_ERR("Failed to get native image");
149 return undefineVar;
150 }
151 }
152 status = napi_wrap(env, thisVar,
153 reinterpret_cast<void *>(napi.get()), ImageNapi::Destructor, nullptr, nullptr);
154 if (status != napi_ok) {
155 IMAGE_ERR("Failure wrapping js to native napi");
156 return undefineVar;
157 }
158
159 napi.release();
160 IMAGE_FUNCTION_OUT();
161 return thisVar;
162 }
163
Destructor(napi_env env,void * nativeObject,void * finalize)164 void ImageNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
165 {
166 if (nativeObject != nullptr) {
167 delete reinterpret_cast<ImageNapi *>(nativeObject);
168 }
169 }
170
Create(napi_env env)171 napi_value ImageNapi::Create(napi_env env)
172 {
173 napi_value constructor = nullptr;
174 napi_value result = nullptr;
175 napi_value argv[NUM1];
176
177 IMAGE_FUNCTION_IN();
178 if (env == nullptr) {
179 IMAGE_ERR("Input args is invalid");
180 return nullptr;
181 }
182 if (napi_get_reference_value(env, sConstructor_, &constructor) == napi_ok && constructor != nullptr) {
183 if (napi_create_string_utf8(env, MY_NAME.c_str(), NAPI_AUTO_LENGTH, &(argv[NUM0])) != napi_ok) {
184 IMAGE_ERR("Create native image id Failed");
185 }
186 if (napi_new_instance(env, constructor, NUM1, argv, &result) != napi_ok) {
187 IMAGE_ERR("New instance could not be obtained");
188 }
189 }
190 IMAGE_FUNCTION_OUT();
191 return result;
192 }
Create(napi_env env,std::shared_ptr<NativeImage> nativeImage)193 napi_value ImageNapi::Create(napi_env env, std::shared_ptr<NativeImage> nativeImage)
194 {
195 napi_value constructor = nullptr;
196 napi_value result = nullptr;
197 napi_value argv[NUM1];
198
199 IMAGE_FUNCTION_IN();
200 if (env == nullptr || nativeImage == nullptr) {
201 IMAGE_ERR("Input args is invalid %{public}p vs %{public}p", env, nativeImage.get());
202 return nullptr;
203 }
204 if (napi_get_reference_value(env, sConstructor_, &constructor) == napi_ok && constructor != nullptr) {
205 auto id = sNativeImageHolder_.save(nativeImage);
206 if (napi_create_string_utf8(env, id.c_str(), NAPI_AUTO_LENGTH, &(argv[NUM0])) != napi_ok) {
207 IMAGE_ERR("Create native image id Failed");
208 }
209 if (napi_new_instance(env, constructor, NUM1, argv, &result) != napi_ok) {
210 IMAGE_ERR("New instance could not be obtained");
211 }
212 }
213 IMAGE_FUNCTION_OUT();
214 return result;
215 }
JsCheckObjectType(napi_env env,napi_value value,napi_valuetype type)216 static inline bool JsCheckObjectType(napi_env env, napi_value value, napi_valuetype type)
217 {
218 return (ImageNapiUtils::getType(env, value) == type);
219 }
220
JsGetCallbackFunc(napi_env env,napi_value value,napi_ref * result)221 static inline bool JsGetCallbackFunc(napi_env env, napi_value value, napi_ref *result)
222 {
223 if (JsCheckObjectType(env, value, napi_function)) {
224 napi_create_reference(env, value, NUM1, result);
225 return true;
226 }
227 return false;
228 }
229
JsGetInt32Args(napi_env env,napi_value value,int * result)230 static inline bool JsGetInt32Args(napi_env env, napi_value value, int *result)
231 {
232 if (JsCheckObjectType(env, value, napi_number)) {
233 napi_get_value_int32(env, value, result);
234 return true;
235 }
236 return false;
237 }
238 using AsyncExecCallback = void (*)(napi_env env, ImageAsyncContext* ctx);
239 using AsyncCompleteCallback = void (*)(napi_env env, napi_status status, ImageAsyncContext* ctx);
JsCreateWork(napi_env env,const char * name,AsyncExecCallback exec,AsyncCompleteCallback complete,ImageAsyncContext * ctx)240 static bool JsCreateWork(napi_env env, const char* name, AsyncExecCallback exec,
241 AsyncCompleteCallback complete, ImageAsyncContext* ctx)
242 {
243 napi_value resource = nullptr;
244 napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &resource);
245 napi_status status = napi_create_async_work(
246 env, nullptr, resource, reinterpret_cast<napi_async_execute_callback>(exec),
247 reinterpret_cast<napi_async_complete_callback>(complete), static_cast<void *>(ctx), &(ctx->work));
248 if (status != napi_ok) {
249 IMAGE_ERR("fail to create async work %{public}d", status);
250 return false;
251 }
252
253 if (napi_queue_async_work(env, ctx->work) != napi_ok) {
254 IMAGE_ERR("fail to queue async work");
255 return false;
256 }
257 return true;
258 }
259
GetNative()260 NativeImage* ImageNapi::GetNative()
261 {
262 if (native_ != nullptr) {
263 return native_.get();
264 }
265 return nullptr;
266 }
267
UnwrapContext(napi_env env,napi_callback_info info,size_t * argc=nullptr,napi_value * argv=nullptr)268 static std::unique_ptr<ImageAsyncContext> UnwrapContext(napi_env env, napi_callback_info info,
269 size_t* argc = nullptr, napi_value* argv = nullptr)
270 {
271 napi_value thisVar = nullptr;
272 size_t tmp = NUM0;
273
274 IMAGE_FUNCTION_IN();
275
276 if (napi_get_cb_info(env, info, (argc == nullptr)?&tmp:argc, argv, &thisVar, nullptr) != napi_ok) {
277 IMAGE_ERR("Fail to napi_get_cb_info");
278 return nullptr;
279 }
280
281 std::unique_ptr<ImageAsyncContext> ctx = std::make_unique<ImageAsyncContext>();
282 if (napi_unwrap(env, thisVar, reinterpret_cast<void**>(&ctx->napi)) != napi_ok || ctx->napi == nullptr) {
283 IMAGE_ERR("fail to unwrap constructor_");
284 return nullptr;
285 }
286 ctx->image = ctx->napi->GetNative();
287 napi_create_reference(env, thisVar, NUM1, &(ctx->thisRef));
288 return ctx;
289 }
290
ProcessPromise(napi_env env,napi_deferred deferred,napi_value * result,bool resolved)291 static inline void ProcessPromise(napi_env env, napi_deferred deferred, napi_value* result, bool resolved)
292 {
293 if (resolved) {
294 napi_resolve_deferred(env, deferred, result[NUM1]);
295 } else {
296 napi_reject_deferred(env, deferred, result[NUM0]);
297 }
298 }
ProcessCallback(napi_env env,napi_ref ref,napi_value * result)299 static inline void ProcessCallback(napi_env env, napi_ref ref, napi_value* result)
300 {
301 napi_value retVal;
302 napi_value callback;
303 napi_get_reference_value(env, ref, &callback);
304 napi_call_function(env, nullptr, callback, NUM2, result, &retVal);
305 napi_delete_reference(env, ref);
306 }
CommonCallbackRoutine(napi_env env,ImageAsyncContext * & context,const napi_value & valueParam)307 static void CommonCallbackRoutine(napi_env env, ImageAsyncContext* &context, const napi_value &valueParam)
308 {
309 IMAGE_FUNCTION_IN();
310 napi_value result[2] = {0};
311
312 if (context == nullptr) {
313 IMAGE_ERR("context is nullptr");
314 return;
315 }
316
317 if (context->status == SUCCESS) {
318 napi_create_uint32(env, context->status, &result[0]);
319 result[1] = valueParam;
320 } else {
321 ImageNapiUtils::CreateErrorObj(env, result[0], context->status,
322 "There is generic napi failure!");
323 napi_get_undefined(env, &result[1]);
324 }
325
326 if (context->deferred) {
327 ProcessPromise(env, context->deferred, result, context->status == SUCCESS);
328 } else {
329 ProcessCallback(env, context->callbackRef, result);
330 }
331
332 napi_delete_async_work(env, context->work);
333
334 delete context;
335 context = nullptr;
336 IMAGE_FUNCTION_OUT();
337 }
338
BuildIntProperty(napi_env env,const std::string & name,int32_t val,napi_value result)339 static void BuildIntProperty(napi_env env, const std::string &name,
340 int32_t val, napi_value result)
341 {
342 napi_value nVal;
343 napi_create_int32(env, val, &nVal);
344 napi_set_named_property(env, result, name.c_str(), nVal);
345 }
346
BuildJsSize(napi_env env,int32_t width,int32_t height)347 static napi_value BuildJsSize(napi_env env, int32_t width, int32_t height)
348 {
349 napi_value result = nullptr;
350
351 napi_create_object(env, &result);
352
353 BuildIntProperty(env, "width", width, result);
354 BuildIntProperty(env, "height", height, result);
355 return result;
356 }
357
BuildJsRegion(napi_env env,int32_t width,int32_t height,int32_t x,int32_t y)358 static napi_value BuildJsRegion(napi_env env, int32_t width,
359 int32_t height, int32_t x, int32_t y)
360 {
361 napi_value result = nullptr;
362
363 napi_create_object(env, &result);
364
365 napi_set_named_property(env, result, "size", BuildJsSize(env, width, height));
366
367 BuildIntProperty(env, "x", x, result);
368 BuildIntProperty(env, "y", y, result);
369 return result;
370 }
371
JSGetClipRect(napi_env env,napi_callback_info info)372 napi_value ImageNapi::JSGetClipRect(napi_env env, napi_callback_info info)
373 {
374 napi_value result = nullptr;
375
376 IMAGE_FUNCTION_IN();
377 napi_get_undefined(env, &result);
378 std::unique_ptr<ImageAsyncContext> context = UnwrapContext(env, info);
379 if (context != nullptr && context->napi != nullptr && context->napi->isTestImage_) {
380 const int32_t WIDTH = 8192;
381 const int32_t HEIGHT = 8;
382 return BuildJsRegion(env, WIDTH, HEIGHT, NUM0, NUM0);
383 }
384 if (context == nullptr || context->image == nullptr) {
385 IMAGE_ERR("Image surface buffer is nullptr");
386 return result;
387 }
388
389 int32_t width = NUM0;
390 int32_t height = NUM0;
391 if (context->image->GetSize(width, height) != SUCCESS) {
392 IMAGE_ERR("Image native get size failed");
393 return result;
394 }
395 return BuildJsRegion(env, width, height, NUM0, NUM0);
396 }
397
JsGetSize(napi_env env,napi_callback_info info)398 napi_value ImageNapi::JsGetSize(napi_env env, napi_callback_info info)
399 {
400 napi_value result = nullptr;
401
402 IMAGE_FUNCTION_IN();
403 napi_get_undefined(env, &result);
404 std::unique_ptr<ImageAsyncContext> context = UnwrapContext(env, info);
405 if (context != nullptr && context->napi != nullptr && context->napi->isTestImage_) {
406 const int32_t WIDTH = 8192;
407 const int32_t HEIGHT = 8;
408 return BuildJsSize(env, WIDTH, HEIGHT);
409 }
410 if (context == nullptr || context->image == nullptr) {
411 IMAGE_ERR("Image surface buffer is nullptr");
412 return result;
413 }
414
415 int32_t width = NUM0;
416 int32_t height = NUM0;
417 if (context->image->GetSize(width, height) != SUCCESS) {
418 IMAGE_ERR("Image native get size failed");
419 return result;
420 }
421 return BuildJsSize(env, width, height);
422 }
423
JsGetFormat(napi_env env,napi_callback_info info)424 napi_value ImageNapi::JsGetFormat(napi_env env, napi_callback_info info)
425 {
426 napi_value result = nullptr;
427
428 IMAGE_FUNCTION_IN();
429 napi_get_undefined(env, &result);
430 std::unique_ptr<ImageAsyncContext> context = UnwrapContext(env, info);
431 if (context != nullptr && context->napi != nullptr && context->napi->isTestImage_) {
432 const int32_t FORMAT = 12;
433 napi_create_int32(env, FORMAT, &result);
434 return result;
435 }
436 if (context == nullptr || context->image == nullptr) {
437 IMAGE_ERR("Image surface buffer is nullptr");
438 return result;
439 }
440
441 int32_t format = NUM0;
442 if (context->image->GetFormat(format) != SUCCESS) {
443 IMAGE_ERR("Image native get format failed");
444 return result;
445 }
446
447 napi_create_int32(env, format, &result);
448 return result;
449 }
450
JSReleaseCallBack(napi_env env,napi_status status,ImageAsyncContext * context)451 static void JSReleaseCallBack(napi_env env, napi_status status,
452 ImageAsyncContext* context)
453 {
454 IMAGE_FUNCTION_IN();
455 napi_value result = nullptr;
456 napi_get_undefined(env, &result);
457
458 if (context == nullptr) {
459 IMAGE_ERR("context is nullptr");
460 return;
461 }
462
463 if (context->thisRef != nullptr) {
464 napi_value thisVar;
465 napi_get_reference_value(env, context->thisRef, &thisVar);
466 napi_delete_reference(env, context->thisRef);
467 if (thisVar != nullptr) {
468 ImageNapi *tmp = nullptr;
469 auto status_ = napi_remove_wrap(env, thisVar, reinterpret_cast<void**>(&tmp));
470 if (status_ != napi_ok) {
471 IMAGE_ERR("NAPI remove wrap failed status %{public}d", status_);
472 }
473 }
474 }
475
476 context->status = SUCCESS;
477 IMAGE_FUNCTION_OUT();
478 CommonCallbackRoutine(env, context, result);
479 }
480
JsRelease(napi_env env,napi_callback_info info)481 napi_value ImageNapi::JsRelease(napi_env env, napi_callback_info info)
482 {
483 IMAGE_FUNCTION_IN();
484 napi_value result = nullptr;
485 size_t argc = NUM1;
486 napi_value argv[NUM1] = {0};
487
488 napi_get_undefined(env, &result);
489 auto context = UnwrapContext(env, info, &argc, argv);
490 if (context == nullptr) {
491 IMAGE_ERR("fail to unwrap constructor_");
492 return result;
493 }
494 if (argc == NUM1) {
495 if (!JsGetCallbackFunc(env, argv[NUM0], &(context->callbackRef))) {
496 IMAGE_ERR("Unsupport arg 0 type");
497 return result;
498 }
499 } else {
500 napi_create_promise(env, &(context->deferred), &result);
501 }
502
503 if (JsCreateWork(env, "JsRelease", [](napi_env env, ImageAsyncContext* data) {},
504 JSReleaseCallBack, context.get())) {
505 context.release();
506 }
507 IMAGE_FUNCTION_OUT();
508 return result;
509 }
510
CreateArrayBuffer(napi_env env,uint8_t * src,size_t srcLen,napi_value * res)511 static bool CreateArrayBuffer(napi_env env, uint8_t* src, size_t srcLen, napi_value *res)
512 {
513 if (src == nullptr || srcLen == 0) {
514 return false;
515 }
516 auto status = napi_create_external_arraybuffer(env, src, srcLen,
517 [](napi_env env, void* data, void* hint) { }, nullptr, res);
518 if (status != napi_ok) {
519 return false;
520 }
521 return true;
522 }
523
IsEqual(const int32_t & check,ImageFormat format)524 static inline bool IsEqual(const int32_t& check, ImageFormat format)
525 {
526 return (check == int32_t(format));
527 }
IsEqual(const int32_t & check,ComponentType type)528 static inline bool IsEqual(const int32_t& check, ComponentType type)
529 {
530 return (check == int32_t(type));
531 }
IsYUVComponent(const int32_t & type)532 static inline bool IsYUVComponent(const int32_t& type)
533 {
534 return (IsEqual(type, ComponentType::YUV_Y) ||
535 IsEqual(type, ComponentType::YUV_U) ||
536 IsEqual(type, ComponentType::YUV_V));
537 }
IsYUV422SPImage(int32_t format)538 static inline bool IsYUV422SPImage(int32_t format)
539 {
540 return (IsEqual(format, ImageFormat::YCBCR_422_SP) ||
541 (format == int32_t(GRAPHIC_PIXEL_FMT_YCBCR_422_SP)));
542 }
CheckComponentType(const int32_t & type,int32_t format)543 static inline bool CheckComponentType(const int32_t& type, int32_t format)
544 {
545 return ((IsYUV422SPImage(format) && IsYUVComponent(type)) ||
546 (!IsYUV422SPImage(format) && IsEqual(type, ComponentType::JPEG)));
547 }
548
BuildJsComponentObject(napi_env env,int32_t type,uint8_t * buffer,NativeComponent * component,napi_value * result)549 static bool BuildJsComponentObject(napi_env env, int32_t type, uint8_t* buffer,
550 NativeComponent* component, napi_value* result)
551 {
552 napi_value array;
553 if (!CreateArrayBuffer(env, buffer, component->size, &array)) {
554 return false;
555 }
556 napi_create_object(env, result);
557 napi_set_named_property(env, *result, "byteBuffer", array);
558 BuildIntProperty(env, "componentType", type, *result);
559 BuildIntProperty(env, "rowStride", component->rowStride, *result);
560 BuildIntProperty(env, "pixelStride", component->pixelStride, *result);
561 return true;
562 }
TestGetComponentCallBack(napi_env env,napi_status status,ImageAsyncContext * context)563 static void TestGetComponentCallBack(napi_env env, napi_status status, ImageAsyncContext* context)
564 {
565 if (context == nullptr) {
566 IMAGE_ERR("Invalid input context");
567 return;
568 }
569 napi_value result;
570 napi_value array;
571 void *nativePtr = nullptr;
572 if (napi_create_arraybuffer(env, NUM1, &nativePtr, &array) != napi_ok || nativePtr == nullptr) {
573 return;
574 }
575 napi_create_object(env, &result);
576 napi_set_named_property(env, result, "byteBuffer", array);
577 BuildIntProperty(env, "componentType", context->componentType, result);
578 BuildIntProperty(env, "rowStride", NUM0, result);
579 BuildIntProperty(env, "pixelStride", NUM0, result);
580 context->status = SUCCESS;
581 CommonCallbackRoutine(env, context, result);
582 }
583
JsGetComponentCallBack(napi_env env,napi_status status,ImageAsyncContext * context)584 static void JsGetComponentCallBack(napi_env env, napi_status status, ImageAsyncContext* context)
585 {
586 IMAGE_FUNCTION_IN();
587 napi_value result;
588 napi_get_undefined(env, &result);
589
590 if (context != nullptr && context->napi != nullptr && context->isTestContext) {
591 TestGetComponentCallBack(env, status, context);
592 return;
593 }
594
595 if (context == nullptr) {
596 IMAGE_ERR("Invalid input context");
597 return;
598 }
599 context->status = ERROR;
600 NativeComponent* component = context->component;
601 if (component == nullptr) {
602 IMAGE_ERR("Invalid component");
603 CommonCallbackRoutine(env, context, result);
604 return;
605 }
606
607 uint8_t *buffer = nullptr;
608 if (component->virAddr != nullptr) {
609 buffer = component->virAddr;
610 } else {
611 buffer = component->raw.data();
612 }
613
614 if (buffer == nullptr || component->size == NUM0) {
615 IMAGE_ERR("Invalid buffer");
616 CommonCallbackRoutine(env, context, result);
617 return;
618 }
619
620 if (BuildJsComponentObject(env, context->componentType, buffer, component, &result)) {
621 context->status = SUCCESS;
622 } else {
623 IMAGE_ERR("napi_create_arraybuffer failed!");
624 }
625
626 IMAGE_FUNCTION_OUT();
627 CommonCallbackRoutine(env, context, result);
628 }
JsGetComponentExec(napi_env env,ImageAsyncContext * context)629 static void JsGetComponentExec(napi_env env, ImageAsyncContext* context)
630 {
631 if (context == nullptr || context->napi == nullptr) {
632 IMAGE_ERR("Invalid input context");
633 return;
634 }
635
636 auto native = context->napi->GetNative();
637 if (native == nullptr) {
638 IMAGE_ERR("Empty native");
639 return;
640 }
641 context->component = native->GetComponent(context->componentType);
642 }
643
JsGetComponentArgs(napi_env env,size_t argc,napi_value * argv,ImageAsyncContext * context)644 static bool JsGetComponentArgs(napi_env env, size_t argc, napi_value* argv, ImageAsyncContext* context)
645 {
646 if (argv == nullptr || context == nullptr || argc < NUM1 || context->napi == nullptr) {
647 IMAGE_ERR("argv is nullptr");
648 return false;
649 }
650
651 if (!JsGetInt32Args(env, argv[NUM0], &(context->componentType))) {
652 IMAGE_ERR("Unsupport arg 0 type");
653 return false;
654 }
655
656 auto native = context->napi->GetNative();
657 if (native == nullptr && !context->isTestContext) {
658 IMAGE_ERR("native is nullptr");
659 return false;
660 }
661
662 int32_t format = NUM0;
663 if (context->isTestContext) {
664 const int32_t TEST_FORMAT = 12;
665 format = TEST_FORMAT;
666 } else {
667 native->GetFormat(format);
668 }
669
670 if (!CheckComponentType(context->componentType, format)) {
671 IMAGE_ERR("Unsupport component type 0 value: %{public}d", context->componentType);
672 return false;
673 }
674
675 if (argc == NUM2 && !JsGetCallbackFunc(env, argv[NUM1], &(context->callbackRef))) {
676 IMAGE_ERR("Unsupport arg 1 type");
677 return false;
678 }
679 return true;
680 }
681
JsGetComponent(napi_env env,napi_callback_info info)682 napi_value ImageNapi::JsGetComponent(napi_env env, napi_callback_info info)
683 {
684 IMAGE_FUNCTION_IN();
685 napi_value result = nullptr;
686 size_t argc = NUM2;
687 napi_value argv[NUM2] = {0};
688
689 napi_get_undefined(env, &result);
690 auto context = UnwrapContext(env, info, &argc, argv);
691 if (context == nullptr) {
692 return ImageNapiUtils::ThrowExceptionError(env, static_cast<int32_t>(napi_invalid_arg),
693 "fail to unwrap constructor_ ");
694 }
695 context->isTestContext = context->napi->isTestImage_;
696 if (!JsGetComponentArgs(env, argc, argv, context.get())) {
697 return ImageNapiUtils::ThrowExceptionError(env, static_cast<int32_t>(napi_invalid_arg),
698 "Unsupport arg type!");
699 }
700
701 if (context->callbackRef == nullptr) {
702 napi_create_promise(env, &(context->deferred), &result);
703 }
704
705 if (JsCreateWork(env, "JsGetComponent", JsGetComponentExec, JsGetComponentCallBack, context.get())) {
706 context.release();
707 }
708
709 IMAGE_FUNCTION_OUT();
710 return result;
711 }
712 } // namespace Media
713 } // namespace OHOS
714