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_source_napi.h"
17 #include <fcntl.h>
18 #include "image_common.h"
19 #include "image_log.h"
20 #include "image_napi_utils.h"
21 #include "media_errors.h"
22 #include "string_ex.h"
23 #include "image_trace.h"
24 #include "hitrace_meter.h"
25 #include "exif_metadata_formatter.h"
26 #include "image_dfx.h"
27 #include "color_space_object_convertor.h"
28
29 #undef LOG_DOMAIN
30 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
31
32 #undef LOG_TAG
33 #define LOG_TAG "ImageSourceNapi"
34
35 namespace {
36 constexpr int INVALID_FD = -1;
37 constexpr uint32_t NUM_0 = 0;
38 constexpr uint32_t NUM_1 = 1;
39 constexpr uint32_t NUM_2 = 2;
40 constexpr uint32_t NUM_3 = 3;
41 constexpr uint32_t NUM_4 = 4;
42 constexpr uint32_t NUM_5 = 5;
43 }
44
45 namespace OHOS {
46 namespace Media {
47 thread_local napi_ref ImageSourceNapi::sConstructor_ = nullptr;
48 thread_local std::shared_ptr<ImageSource> ImageSourceNapi::sImgSrc_ = nullptr;
49 thread_local std::shared_ptr<IncrementalPixelMap> ImageSourceNapi::sIncPixelMap_ = nullptr;
50 static const std::string CLASS_NAME = "ImageSource";
51 static const std::string FILE_URL_PREFIX = "file://";
52 thread_local std::string ImageSourceNapi::filePath_ = "";
53 thread_local int ImageSourceNapi::fileDescriptor_ = -1;
54 thread_local void* ImageSourceNapi::fileBuffer_ = nullptr;
55 thread_local size_t ImageSourceNapi::fileBufferSize_ = 0;
56
57 napi_ref ImageSourceNapi::pixelMapFormatRef_ = nullptr;
58 napi_ref ImageSourceNapi::propertyKeyRef_ = nullptr;
59 napi_ref ImageSourceNapi::imageFormatRef_ = nullptr;
60 napi_ref ImageSourceNapi::alphaTypeRef_ = nullptr;
61 napi_ref ImageSourceNapi::scaleModeRef_ = nullptr;
62 napi_ref ImageSourceNapi::componentTypeRef_ = nullptr;
63 napi_ref ImageSourceNapi::decodingDynamicRangeRef_ = nullptr;
64 napi_ref ImageSourceNapi::decodingResolutionQualityRef_ = nullptr;
65
66 static std::mutex imageSourceCrossThreadMutex_;
67
68 struct RawFileDescriptorInfo {
69 int32_t fd = INVALID_FD;
70 int32_t offset;
71 int32_t length;
72 };
73
74 struct ImageSourceAsyncContext {
75 napi_env env;
76 napi_async_work work;
77 napi_deferred deferred;
78 napi_ref callbackRef = nullptr;
79 ImageSourceNapi *constructor_;
80 uint32_t status;
81 std::string pathName = "";
82 int fdIndex = INVALID_FD;
83 void* sourceBuffer = nullptr;
84 size_t sourceBufferSize = NUM_0;
85 std::string keyStr;
86 std::string valueStr;
87 std::vector<std::string> keyStrArray;
88 std::vector<std::pair<std::string, std::string>> kVStrArray;
89 std::string defaultValueStr;
90 int32_t valueInt;
91 int32_t deufltValueInt;
92 void *updataBuffer;
93 size_t updataBufferSize;
94 uint32_t updataBufferOffset = 0;
95 uint32_t updataLength = 0;
96 bool isCompleted = false;
97 bool isSuccess = false;
98 bool isBatch = false;
99 size_t pathNameLength;
100 SourceOptions opts;
101 uint32_t index = 0;
102 ImageInfo imageInfo;
103 DecodeOptions decodeOpts;
104 std::shared_ptr<ImageSource> rImageSource;
105 std::shared_ptr<PixelMap> rPixelMap;
106 std::string errMsg;
107 std::multimap<std::int32_t, std::string> errMsgArray;
108 std::unique_ptr<std::vector<std::unique_ptr<PixelMap>>> pixelMaps;
109 std::unique_ptr<std::vector<int32_t>> delayTimes;
110 std::unique_ptr<std::vector<int32_t>> disposalType;
111 uint32_t frameCount = 0;
112 struct RawFileDescriptorInfo rawFileInfo;
113 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
114 DecodingOptionsForPicture decodingOptsForPicture;
115 std::shared_ptr<Picture> rPicture;
116 #endif
117 };
118
119 struct ImageSourceSyncContext {
120 ImageSourceNapi *constructor_;
121 uint32_t status;
122 uint32_t index = 0;
123 DecodeOptions decodeOpts;
124 std::shared_ptr<PixelMap> rPixelMap;
125 std::string errMsg;
126 };
127
128 struct ImageEnum {
129 std::string name;
130 int32_t numVal;
131 std::string strVal;
132 };
133
134 static std::vector<struct ImageEnum> sPixelMapFormatMap = {
135 {"UNKNOWN", 0, ""},
136 {"ARGB_8888", 1, ""},
137 {"RGB_565", 2, ""},
138 {"RGBA_8888", 3, ""},
139 {"BGRA_8888", 4, ""},
140 {"RGB_888", 5, ""},
141 {"ALPHA_8", 6, ""},
142 {"RGBA_F16", 7, ""},
143 {"NV21", 8, ""},
144 {"NV12", 9, ""},
145 {"RGBA_1010102", 10, ""},
146 {"YCBCR_P010", 11, ""},
147 {"YCRCB_P010", 12, ""},
148 };
149 static std::vector<struct ImageEnum> sPropertyKeyMap = {
150 {"BITS_PER_SAMPLE", 0, "BitsPerSample"},
151 {"ORIENTATION", 0, "Orientation"},
152 {"IMAGE_LENGTH", 0, "ImageLength"},
153 {"IMAGE_WIDTH", 0, "ImageWidth"},
154 {"GPS_LATITUDE", 0, "GPSLatitude"},
155 {"GPS_LONGITUDE", 0, "GPSLongitude"},
156 {"GPS_LATITUDE_REF", 0, "GPSLatitudeRef"},
157 {"GPS_LONGITUDE_REF", 0, "GPSLongitudeRef"},
158 {"DATE_TIME_ORIGINAL", 0, "DateTimeOriginal"},
159 {"EXPOSURE_TIME", 0, "ExposureTime"},
160 {"SCENE_TYPE", 0, "SceneType"},
161 {"ISO_SPEED_RATINGS", 0, "ISOSpeedRatings"},
162 {"F_NUMBER", 0, "FNumber"},
163 {"COMPRESSED_BITS_PER_PIXEL", 0, "CompressedBitsPerPixel"},
164 {"DATE_TIME", 0, "DateTime"},
165 {"GPS_TIME_STAMP", 0, "GPSTimeStamp"},
166 {"GPS_DATE_STAMP", 0, "GPSDateStamp"},
167 {"IMAGE_DESCRIPTION", 0, "ImageDescription"},
168 {"MAKE", 0, "Make"},
169 {"MODEL", 0, "Model"},
170 {"PHOTO_MODE", 0, "PhotoMode"},
171 {"SENSITIVITY_TYPE", 0, "SensitivityType"},
172 {"STANDARD_OUTPUT_SENSITIVITY", 0, "StandardOutputSensitivity"},
173 {"RECOMMENDED_EXPOSURE_INDEX", 0, "RecommendedExposureIndex"},
174 {"ISO_SPEED", 0, "ISOSpeedRatings"},
175 {"APERTURE_VALUE", 0, "ApertureValue"},
176 {"EXPOSURE_BIAS_VALUE", 0, "ExposureBiasValue"},
177 {"METERING_MODE", 0, "MeteringMode"},
178 {"LIGHT_SOURCE", 0, "LightSource"},
179 {"FLASH", 0, "Flash"},
180 {"FOCAL_LENGTH", 0, "FocalLength"},
181 {"USER_COMMENT", 0, "UserComment"},
182 {"PIXEL_X_DIMENSION", 0, "PixelXDimension"},
183 {"PIXEL_Y_DIMENSION", 0, "PixelYDimension"},
184 {"WHITE_BALANCE", 0, "WhiteBalance"},
185 {"FOCAL_LENGTH_IN_35_MM_FILM", 0, "FocalLengthIn35mmFilm"},
186 {"CAPTURE_MODE", 0, "HwMnoteCaptureMode"},
187 {"PHYSICAL_APERTURE", 0, "HwMnotePhysicalAperture"},
188 {"ROLL_ANGLE", 0, "HwMnoteRollAngle"},
189 {"PITCH_ANGLE", 0, "HwMnotePitchAngle"},
190 {"SCENE_FOOD_CONF", 0, "HwMnoteSceneFoodConf"},
191 {"SCENE_STAGE_CONF", 0, "HwMnoteSceneStageConf"},
192 {"SCENE_BLUE_SKY_CONF", 0, "HwMnoteSceneBlueSkyConf"},
193 {"SCENE_GREEN_PLANT_CONF", 0, "HwMnoteSceneGreenPlantConf"},
194 {"SCENE_BEACH_CONF", 0, "HwMnoteSceneBeachConf"},
195 {"SCENE_SNOW_CONF", 0, "HwMnoteSceneSnowConf"},
196 {"SCENE_SUNSET_CONF", 0, "HwMnoteSceneSunsetConf"},
197 {"SCENE_FLOWERS_CONF", 0, "HwMnoteSceneFlowersConf"},
198 {"SCENE_NIGHT_CONF", 0, "HwMnoteSceneNightConf"},
199 {"SCENE_TEXT_CONF", 0, "HwMnoteSceneTextConf"},
200 {"FACE_COUNT", 0, "HwMnoteFaceCount"},
201 {"FOCUS_MODE", 0, "HwMnoteFocusMode"},
202 {"COMPRESSION", 0, "Compression"},
203 {"PHOTOMETRIC_INTERPRETATION", 0, "PhotometricInterpretation"},
204 {"STRIP_OFFSETS", 0, "StripOffsets"},
205 {"SAMPLES_PER_PIXEL", 0, "SamplesPerPixel"},
206 {"ROWS_PER_STRIP", 0, "RowsPerStrip"},
207 {"STRIP_BYTE_COUNTS", 0, "StripByteCounts"},
208 {"X_RESOLUTION", 0, "XResolution"},
209 {"Y_RESOLUTION", 0, "YResolution"},
210 {"PLANAR_CONFIGURATION", 0, "PlanarConfiguration"},
211 {"RESOLUTION_UNIT", 0, "ResolutionUnit"},
212 {"TRANSFER_FUNCTION", 0, "TransferFunction"},
213 {"SOFTWARE", 0, "Software"},
214 {"ARTIST", 0, "Artist"},
215 {"WHITE_POINT", 0, "WhitePoint"},
216 {"PRIMARY_CHROMATICITIES", 0, "PrimaryChromaticities"},
217 {"YCBCR_COEFFICIENTS", 0, "YCbCrCoefficients"},
218 {"YCBCR_SUB_SAMPLING", 0, "YCbCrSubSampling"},
219 {"YCBCR_POSITIONING", 0, "YCbCrPositioning"},
220 {"REFERENCE_BLACK_WHITE", 0, "ReferenceBlackWhite"},
221 {"COPYRIGHT", 0, "Copyright"},
222 {"JPEG_INTERCHANGE_FORMAT", 0, "JPEGInterchangeFormat"},
223 {"JPEG_INTERCHANGE_FORMAT_LENGTH", 0, "JPEGInterchangeFormatLength"},
224 {"EXPOSURE_PROGRAM", 0, "ExposureProgram"},
225 {"SPECTRAL_SENSITIVITY", 0, "SpectralSensitivity"},
226 {"OECF", 0, "OECF"},
227 {"EXIF_VERSION", 0, "ExifVersion"},
228 {"DATE_TIME_DIGITIZED", 0, "DateTimeDigitized"},
229 {"COMPONENTS_CONFIGURATION", 0, "ComponentsConfiguration"},
230 {"SHUTTER_SPEED", 0, "ShutterSpeedValue"},
231 {"BRIGHTNESS_VALUE", 0, "BrightnessValue"},
232 {"MAX_APERTURE_VALUE", 0, "MaxApertureValue"},
233 {"SUBJECT_DISTANCE", 0, "SubjectDistance"},
234 {"SUBJECT_AREA", 0, "SubjectArea"},
235 {"MAKER_NOTE", 0, "MakerNote"},
236 {"SUBSEC_TIME", 0, "SubsecTime"},
237 {"SUBSEC_TIME_ORIGINAL", 0, "SubsecTimeOriginal"},
238 {"SUBSEC_TIME_DIGITIZED", 0, "SubsecTimeDigitized"},
239 {"FLASHPIX_VERSION", 0, "FlashpixVersion"},
240 {"COLOR_SPACE", 0, "ColorSpace"},
241 {"RELATED_SOUND_FILE", 0, "RelatedSoundFile"},
242 {"FLASH_ENERGY", 0, "FlashEnergy"},
243 {"SPATIAL_FREQUENCY_RESPONSE", 0, "SpatialFrequencyResponse"},
244 {"FOCAL_PLANE_X_RESOLUTION", 0, "FocalPlaneXResolution"},
245 {"FOCAL_PLANE_Y_RESOLUTION", 0, "FocalPlaneYResolution"},
246 {"FOCAL_PLANE_RESOLUTION_UNIT", 0, "FocalPlaneResolutionUnit"},
247 {"SUBJECT_LOCATION", 0, "SubjectLocation"},
248 {"EXPOSURE_INDEX", 0, "ExposureIndex"},
249 {"SENSING_METHOD", 0, "SensingMethod"},
250 {"FILE_SOURCE", 0, "FileSource"},
251 {"CFA_PATTERN", 0, "CFAPattern"},
252 {"CUSTOM_RENDERED", 0, "CustomRendered"},
253 {"EXPOSURE_MODE", 0, "ExposureMode"},
254 {"DIGITAL_ZOOM_RATIO", 0, "DigitalZoomRatio"},
255 {"SCENE_CAPTURE_TYPE", 0, "SceneCaptureType"},
256 {"GAIN_CONTROL", 0, "GainControl"},
257 {"CONTRAST", 0, "Contrast"},
258 {"SATURATION", 0, "Saturation"},
259 {"SHARPNESS", 0, "Sharpness"},
260 {"DEVICE_SETTING_DESCRIPTION", 0, "DeviceSettingDescription"},
261 {"SUBJECT_DISTANCE_RANGE", 0, "SubjectDistanceRange"},
262 {"IMAGE_UNIQUE_ID", 0, "ImageUniqueID"},
263 {"GPS_VERSION_ID", 0, "GPSVersionID"},
264 {"GPS_ALTITUDE_REF", 0, "GPSAltitudeRef"},
265 {"GPS_ALTITUDE", 0, "GPSAltitude"},
266 {"GPS_SATELLITES", 0, "GPSSatellites"},
267 {"GPS_STATUS", 0, "GPSStatus"},
268 {"GPS_MEASURE_MODE", 0, "GPSMeasureMode"},
269 {"GPS_DOP", 0, "GPSDOP"},
270 {"GPS_SPEED_REF", 0, "GPSSpeedRef"},
271 {"GPS_SPEED", 0, "GPSSpeed"},
272 {"GPS_TRACK_REF", 0, "GPSTrackRef"},
273 {"GPS_TRACK", 0, "GPSTrack"},
274 {"GPS_IMG_DIRECTION_REF", 0, "GPSImgDirectionRef"},
275 {"GPS_IMG_DIRECTION", 0, "GPSImgDirection"},
276 {"GPS_MAP_DATUM", 0, "GPSMapDatum"},
277 {"GPS_DEST_LATITUDE_REF", 0, "GPSDestLatitudeRef"},
278 {"GPS_DEST_LATITUDE", 0, "GPSDestLatitude"},
279 {"GPS_DEST_LONGITUDE_REF", 0, "GPSDestLongitudeRef"},
280 {"GPS_DEST_LONGITUDE", 0, "GPSDestLongitude"},
281 {"GPS_DEST_BEARING_REF", 0, "GPSDestBearingRef"},
282 {"GPS_DEST_BEARING", 0, "GPSDestBearing"},
283 {"GPS_DEST_DISTANCE_REF", 0, "GPSDestDistanceRef"},
284 {"GPS_DEST_DISTANCE", 0, "GPSDestDistance"},
285 {"GPS_PROCESSING_METHOD", 0, "GPSProcessingMethod"},
286 {"GPS_AREA_INFORMATION", 0, "GPSAreaInformation"},
287 {"GPS_DIFFERENTIAL", 0, "GPSDifferential"},
288 {"BODY_SERIAL_NUMBER", 0, "BodySerialNumber"},
289 {"CAMERA_OWNER_NAME", 0, "CameraOwnerName"},
290 {"COMPOSITE_IMAGE", 0, "CompositeImage"},
291 {"COMPRESSED_BITS_PER_PIXEL", 0, "CompressedBitsPerPixel"},
292 {"DNG_VERSION", 0, "DNGVersion"},
293 {"DEFAULT_CROP_SIZE", 0, "DefaultCropSize"},
294 {"GAMMA", 0, "Gamma"},
295 {"ISO_SPEED_LATITUDE_YYY", 0, "ISOSpeedLatitudeyyy"},
296 {"ISO_SPEED_LATITUDE_ZZZ", 0, "ISOSpeedLatitudezzz"},
297 {"LENS_MAKE", 0, "LensMake"},
298 {"LENS_MODEL", 0, "LensModel"},
299 {"LENS_SERIAL_NUMBER", 0, "LensSerialNumber"},
300 {"LENS_SPECIFICATION", 0, "LensSpecification"},
301 {"NEW_SUBFILE_TYPE", 0, "NewSubfileType"},
302 {"OFFSET_TIME", 0, "OffsetTime"},
303 {"OFFSET_TIME_DIGITIZED", 0, "OffsetTimeDigitized"},
304 {"OFFSET_TIME_ORIGINAL", 0, "OffsetTimeOriginal"},
305 {"SOURCE_EXPOSURE_TIMES_OF_COMPOSITE_IMAGE", 0, "SourceExposureTimesOfCompositeImage"},
306 {"SOURCE_IMAGE_NUMBER_OF_COMPOSITE_IMAGE", 0, "SourceImageNumberOfCompositeImage"},
307 {"SUBFILE_TYPE", 0, "SubfileType"},
308 {"GPS_H_POSITIONING_ERROR", 0, "GPSHPositioningError"},
309 {"PHOTOGRAPHIC_SENSITIVITY", 0, "PhotographicSensitivity"},
310 {"BURST_NUMBER", 0, "HwMnoteBurstNumber"},
311 {"FACE_CONF", 0, "HwMnoteFaceConf"},
312 {"FACE_LEYE_CENTER", 0, "HwMnoteFaceLeyeCenter"},
313 {"FACE_MOUTH_CENTER", 0, "HwMnoteFaceMouthCenter"},
314 {"FACE_POINTER", 0, "HwMnoteFacePointer"},
315 {"FACE_RECT", 0, "HwMnoteFaceRect"},
316 {"FACE_REYE_CENTER", 0, "HwMnoteFaceReyeCenter"},
317 {"FACE_SMILE_SCORE", 0, "HwMnoteFaceSmileScore"},
318 {"FACE_VERSION", 0, "HwMnoteFaceVersion"},
319 {"FRONT_CAMERA", 0, "HwMnoteFrontCamera"},
320 {"SCENE_POINTER", 0, "HwMnoteScenePointer"},
321 {"SCENE_VERSION", 0, "HwMnoteSceneVersion"},
322 {"IS_XMAGE_SUPPORTED", 0, "HwMnoteIsXmageSupported"},
323 {"XMAGE_MODE", 0, "HwMnoteXmageMode"},
324 {"XMAGE_LEFT", 0, "HwMnoteXmageLeft"},
325 {"XMAGE_TOP", 0, "HwMnoteXmageTop"},
326 {"XMAGE_RIGHT", 0, "HwMnoteXmageRight"},
327 {"XMAGE_BOTTOM", 0, "HwMnoteXmageBottom"},
328 {"CLOUD_ENHANCEMENT_MODE", 0, "HwMnoteCloudEnhancementMode"},
329 {"WIND_SNAPSHOT_MODE", 0, "HwMnoteWindSnapshotMode"},
330 {"GIF_LOOP_COUNT", 0, "GIFLoopCount"},
331 };
332 static std::vector<struct ImageEnum> sImageFormatMap = {
333 {"YCBCR_422_SP", 1000, ""},
334 {"JPEG", 2000, ""},
335 };
336 static std::vector<struct ImageEnum> sAlphaTypeMap = {
337 {"UNKNOWN", 0, ""},
338 {"OPAQUE", 1, ""},
339 {"PREMUL", 2, ""},
340 {"UNPREMUL", 3, ""},
341 };
342 static std::vector<struct ImageEnum> sScaleModeMap = {
343 {"FIT_TARGET_SIZE", 0, ""},
344 {"CENTER_CROP", 1, ""},
345 };
346 static std::vector<struct ImageEnum> sComponentTypeMap = {
347 {"YUV_Y", 1, ""},
348 {"YUV_U", 2, ""},
349 {"YUV_V", 3, ""},
350 {"JPEG", 4, ""},
351 };
352 static std::vector<struct ImageEnum> sDecodingDynamicRangeMap = {
353 {"AUTO", 0, ""},
354 {"SDR", 1, ""},
355 {"HDR", 2, ""},
356 };
357 static std::vector<struct ImageEnum> sDecodingResolutionQualityMap = {
358 {"LOW", 1, ""},
359 {"MEDIUM", 2, ""},
360 {"HIGH", 3, ""},
361 };
362
GetStringArgument(napi_env env,napi_value value)363 static std::string GetStringArgument(napi_env env, napi_value value)
364 {
365 std::string strValue = "";
366 size_t bufLength = 0;
367 napi_status status = napi_get_value_string_utf8(env, value, nullptr, NUM_0, &bufLength);
368 if (status == napi_ok && bufLength > NUM_0 && bufLength < PATH_MAX) {
369 char *buffer = reinterpret_cast<char *>(malloc((bufLength + NUM_1) * sizeof(char)));
370 if (buffer == nullptr) {
371 IMAGE_LOGE("No memory");
372 return strValue;
373 }
374
375 status = napi_get_value_string_utf8(env, value, buffer, bufLength + NUM_1, &bufLength);
376 if (status == napi_ok) {
377 IMAGE_LOGD("Get Success");
378 strValue.assign(buffer, 0, bufLength + NUM_1);
379 }
380 if (buffer != nullptr) {
381 free(buffer);
382 buffer = nullptr;
383 }
384 }
385 return strValue;
386 }
387
ImageSourceCallbackRoutine(napi_env env,ImageSourceAsyncContext * & context,const napi_value & valueParam)388 static void ImageSourceCallbackRoutine(napi_env env, ImageSourceAsyncContext* &context, const napi_value &valueParam)
389 {
390 napi_value result[NUM_2] = {0};
391 napi_value retVal;
392 napi_value callback = nullptr;
393
394 napi_get_undefined(env, &result[NUM_0]);
395 napi_get_undefined(env, &result[NUM_1]);
396
397 if (context == nullptr) {
398 IMAGE_LOGE("context is nullptr");
399 return;
400 }
401
402 if (context->status == SUCCESS) {
403 result[NUM_1] = valueParam;
404 } else if (context->errMsgArray.size() > 0) {
405 auto iter = context->errMsgArray.find(IMAGE_DECODE_FAILED);
406 if (iter != context->errMsgArray.end()) {
407 ImageNapiUtils::CreateErrorObj(env, result[NUM_0], iter->first, iter->second);
408 }
409 } else if (context->errMsg.size() > 0) {
410 napi_create_string_utf8(env, context->errMsg.c_str(), NAPI_AUTO_LENGTH, &result[NUM_0]);
411 } else {
412 IMAGE_LOGD("error status, no message");
413 napi_create_string_utf8(env, "error status, no message", NAPI_AUTO_LENGTH, &result[NUM_0]);
414 }
415
416 if (context->deferred) {
417 if (context->status == SUCCESS) {
418 napi_resolve_deferred(env, context->deferred, result[NUM_1]);
419 } else {
420 napi_reject_deferred(env, context->deferred, result[NUM_0]);
421 }
422 } else {
423 IMAGE_LOGD("call callback function");
424 napi_get_reference_value(env, context->callbackRef, &callback);
425 napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
426 napi_delete_reference(env, context->callbackRef);
427 }
428
429 napi_delete_async_work(env, context->work);
430
431 if (context != nullptr) {
432 delete context;
433 context = nullptr;
434 }
435 }
436
ImageSourceCallbackWithErrorObj(napi_env env,ImageSourceAsyncContext * & context,const napi_value & val)437 static void ImageSourceCallbackWithErrorObj(napi_env env,
438 ImageSourceAsyncContext* &context, const napi_value &val)
439 {
440 napi_value result[NUM_2] = {0};
441
442 if (context == nullptr) {
443 IMAGE_LOGE("context is nullptr");
444 return;
445 }
446
447 if (context->status == SUCCESS) {
448 napi_get_undefined(env, &result[NUM_0]);
449 result[NUM_1] = val;
450 } else {
451 std::string errMsg = (context->errMsg.size() > 0) ? context->errMsg : "error status, no message";
452 IMAGE_LOGD("Operation failed code:%{public}d, msg:%{public}s",
453 context->status, errMsg.c_str());
454 ImageNapiUtils::CreateErrorObj(env, result[NUM_0], context->status, errMsg);
455 napi_get_undefined(env, &result[NUM_1]);
456 }
457
458 if (context->deferred) {
459 if (context->status == SUCCESS) {
460 napi_resolve_deferred(env, context->deferred, result[NUM_1]);
461 } else {
462 napi_reject_deferred(env, context->deferred, result[NUM_0]);
463 }
464 } else {
465 napi_value retVal;
466 napi_value callback = nullptr;
467 IMAGE_LOGD("call callback function");
468 napi_get_reference_value(env, context->callbackRef, &callback);
469 napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
470 napi_delete_reference(env, context->callbackRef);
471 }
472
473 napi_delete_async_work(env, context->work);
474
475 delete context;
476 context = nullptr;
477 }
478
CreateEnumTypeObject(napi_env env,napi_valuetype type,napi_ref * ref,std::vector<struct ImageEnum> imageEnumMap)479 static napi_value CreateEnumTypeObject(napi_env env,
480 napi_valuetype type, napi_ref* ref, std::vector<struct ImageEnum> imageEnumMap)
481 {
482 napi_value result = nullptr;
483 napi_status status;
484 int32_t refCount = 1;
485 std::string propName;
486 status = napi_create_object(env, &result);
487 if (status == napi_ok) {
488 for (auto imgEnum : imageEnumMap) {
489 napi_value enumNapiValue = nullptr;
490 if (type == napi_string) {
491 status = napi_create_string_utf8(env, imgEnum.strVal.c_str(),
492 NAPI_AUTO_LENGTH, &enumNapiValue);
493 } else if (type == napi_number) {
494 status = napi_create_int32(env, imgEnum.numVal, &enumNapiValue);
495 } else {
496 IMAGE_LOGE("Unsupported type %{public}d!", type);
497 }
498 if (status == napi_ok && enumNapiValue != nullptr) {
499 status = napi_set_named_property(env, result, imgEnum.name.c_str(), enumNapiValue);
500 }
501 if (status != napi_ok) {
502 IMAGE_LOGE("Failed to add named prop!");
503 break;
504 }
505 }
506
507 if (status == napi_ok) {
508 status = napi_create_reference(env, result, refCount, ref);
509 if (status == napi_ok) {
510 return result;
511 }
512 }
513 }
514 IMAGE_LOGE("CreateEnumTypeObject is Failed!");
515 napi_get_undefined(env, &result);
516 return result;
517 }
518
GetStringArrayArgument(napi_env env,napi_value object)519 std::vector<std::string> GetStringArrayArgument(napi_env env, napi_value object)
520 {
521 std::vector<std::string> keyStrArray;
522 uint32_t arrayLen = 0;
523 napi_status status = napi_get_array_length(env, object, &arrayLen);
524 if (status != napi_ok) {
525 IMAGE_LOGE("Get array length failed: %{public}d", status);
526 return keyStrArray;
527 }
528
529 for (uint32_t i = 0; i < arrayLen; i++) {
530 napi_value element;
531 if (napi_get_element(env, object, i, &element) == napi_ok) {
532 keyStrArray.emplace_back(GetStringArgument(env, element));
533 }
534 }
535
536 IMAGE_LOGD("Get string argument success.");
537 return keyStrArray;
538 }
539
GetRecordArgument(napi_env env,napi_value object)540 std::vector<std::pair<std::string, std::string>> GetRecordArgument(napi_env env, napi_value object)
541 {
542 std::vector<std::pair<std::string, std::string>> kVStrArray;
543 napi_value recordNameList = nullptr;
544 uint32_t recordCount = 0;
545 napi_status status = napi_get_property_names(env, object, &recordNameList);
546 if (status != napi_ok) {
547 IMAGE_LOGE("Get recordNameList property names failed %{public}d", status);
548 return kVStrArray;
549 }
550 status = napi_get_array_length(env, recordNameList, &recordCount);
551 if (status != napi_ok) {
552 IMAGE_LOGE("Get recordNameList array length failed %{public}d", status);
553 return kVStrArray;
554 }
555
556 napi_value recordName = nullptr;
557 napi_value recordValue = nullptr;
558 for (uint32_t i = 0; i < recordCount; ++i) {
559 status = napi_get_element(env, recordNameList, i, &recordName);
560 if (status != napi_ok) {
561 IMAGE_LOGE("Get recordName element failed %{public}d", status);
562 continue;
563 }
564 std::string keyStr = GetStringArgument(env, recordName);
565 status = napi_get_named_property(env, object, keyStr.c_str(), &recordValue);
566 if (status != napi_ok) {
567 IMAGE_LOGE("Get recordValue name property failed %{public}d", status);
568 continue;
569 }
570 std::string valueStr = GetStringArgument(env, recordValue);
571 kVStrArray.push_back(std::make_pair(keyStr, valueStr));
572 }
573
574 IMAGE_LOGD("Get record argument success.");
575 return kVStrArray;
576 }
577
SetValueString(napi_env env,std::string keyStr,std::string valueStr,napi_value & object)578 napi_status SetValueString(napi_env env, std::string keyStr, std::string valueStr, napi_value &object)
579 {
580 napi_value value = nullptr;
581 napi_status status;
582 if (valueStr != "") {
583 status = napi_create_string_utf8(env, valueStr.c_str(), valueStr.length(), &value);
584 if (status != napi_ok) {
585 IMAGE_LOGE("Set Value failed %{public}d", status);
586 return napi_invalid_arg;
587 }
588 } else {
589 status = napi_get_null(env, &value);
590 if (status != napi_ok) {
591 IMAGE_LOGE("Set null failed %{public}d", status);
592 return napi_invalid_arg;
593 }
594 }
595 status = napi_set_named_property(env, object, keyStr.c_str(), value);
596 if (status != napi_ok) {
597 IMAGE_LOGE("Set Key failed %{public}d", status);
598 return napi_invalid_arg;
599 }
600 IMAGE_LOGD("Set string value success.");
601 return napi_ok;
602 }
603
SetRecordParametersInfo(napi_env env,std::vector<std::pair<std::string,std::string>> recordParameters)604 napi_value SetRecordParametersInfo(napi_env env, std::vector<std::pair<std::string, std::string>> recordParameters)
605 {
606 napi_value result = nullptr;
607 napi_get_undefined(env, &result);
608 napi_status status = napi_create_object(env, &result);
609 if (status != napi_ok) {
610 IMAGE_LOGE("Create record failed %{public}d", status);
611 return result;
612 }
613
614 for (size_t index = 0; index < recordParameters.size(); ++index) {
615 status = SetValueString(env, recordParameters[index].first, recordParameters[index].second, result);
616 if (status != napi_ok) {
617 IMAGE_LOGE("Set current record parameter failed %{public}d", status);
618 continue;
619 }
620 }
621
622 IMAGE_LOGD("Set record parameters info success");
623 return result;
624 }
625
CreateModifyErrorArray(napi_env env,std::multimap<std::int32_t,std::string> errMsgArray)626 napi_value CreateModifyErrorArray(napi_env env, std::multimap<std::int32_t, std::string> errMsgArray)
627 {
628 napi_value result = nullptr;
629 napi_status status = napi_create_array_with_length(env, errMsgArray.size(), &result);
630 if (status != napi_ok) {
631 IMAGE_LOGE("Malloc array buffer failed %{public}d", status);
632 return result;
633 }
634
635 uint32_t index = 0;
636 for (auto it = errMsgArray.begin(); it != errMsgArray.end(); ++it) {
637 napi_value errMsgVal;
638 napi_get_undefined(env, &errMsgVal);
639 if (it->first == ERR_MEDIA_WRITE_PARCEL_FAIL) {
640 ImageNapiUtils::CreateErrorObj(env, errMsgVal, it->first,
641 "Create Fd without write permission! exif key: " + it->second);
642 } else if (it->first == ERR_MEDIA_OUT_OF_RANGE) {
643 ImageNapiUtils::CreateErrorObj(env, errMsgVal, it->first,
644 "The given buffer size is too small to add new exif data! exif key: " + it->second);
645 } else if (it->first == ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
646 ImageNapiUtils::CreateErrorObj(env, errMsgVal, it->first,
647 "The image does not support EXIF decoding. exif key: " + it->second);
648 } else if (it->first == ERR_MEDIA_VALUE_INVALID) {
649 ImageNapiUtils::CreateErrorObj(env, errMsgVal, it->first, it->second);
650 } else {
651 ImageNapiUtils::CreateErrorObj(env, errMsgVal, ERROR,
652 "There is generic napi failure! exif key: " + it->second);
653 }
654 status = napi_set_element(env, result, index, errMsgVal);
655 if (status != napi_ok) {
656 IMAGE_LOGE("Add error message to array failed %{public}d", status);
657 continue;
658 }
659 ++index;
660 }
661
662 IMAGE_LOGD("Create modify error array success.");
663 return result;
664 }
665
CreateObtainErrorArray(napi_env env,std::multimap<std::int32_t,std::string> errMsgArray)666 napi_value CreateObtainErrorArray(napi_env env, std::multimap<std::int32_t, std::string> errMsgArray)
667 {
668 napi_value result = nullptr;
669 napi_status status = napi_create_array_with_length(env, errMsgArray.size(), &result);
670 if (status != napi_ok) {
671 IMAGE_LOGE("Malloc array buffer failed %{public}d", status);
672 return result;
673 }
674
675 uint32_t index = 0;
676 for (auto it = errMsgArray.begin(); it != errMsgArray.end(); ++it) {
677 napi_value errMsgVal;
678 napi_get_undefined(env, &errMsgVal);
679 if (it->first == ERR_IMAGE_DECODE_ABNORMAL) {
680 ImageNapiUtils::CreateErrorObj(env, errMsgVal, it->first,
681 "The image source data is incorrect! exif key: " + it->second);
682 } else if (it->first == ERR_IMAGE_UNKNOWN_FORMAT) {
683 ImageNapiUtils::CreateErrorObj(env, errMsgVal, it->first,
684 "Unknown image format! exif key: " + it->second);
685 } else if (it->first == ERR_IMAGE_DECODE_FAILED) {
686 ImageNapiUtils::CreateErrorObj(env, errMsgVal, it->first,
687 "Failed to decode the image! exif key: " + it->second);
688 } else {
689 ImageNapiUtils::CreateErrorObj(env, errMsgVal, ERROR,
690 "There is generic napi failure! exif key: " + it->second);
691 }
692 status = napi_set_element(env, result, index, errMsgVal);
693 if (status != napi_ok) {
694 IMAGE_LOGE("Add error message to array failed %{public}d", status);
695 continue;
696 }
697 ++index;
698 }
699
700 IMAGE_LOGD("Create obtain error array success.");
701 return result;
702 }
703
ImageSourceNapi()704 ImageSourceNapi::ImageSourceNapi():env_(nullptr)
705 { }
706
~ImageSourceNapi()707 ImageSourceNapi::~ImageSourceNapi()
708 {
709 release();
710 }
711
712 struct ImageConstructorInfo {
713 std::string className;
714 napi_ref* classRef;
715 napi_callback constructor;
716 const napi_property_descriptor* property;
717 size_t propertyCount;
718 const napi_property_descriptor* staticProperty;
719 size_t staticPropertyCount;
720 };
721
DoInit(napi_env env,napi_value exports,struct ImageConstructorInfo info)722 static napi_value DoInit(napi_env env, napi_value exports, struct ImageConstructorInfo info)
723 {
724 napi_value constructor = nullptr;
725 napi_status status = napi_define_class(env, info.className.c_str(), NAPI_AUTO_LENGTH,
726 info.constructor, nullptr, info.propertyCount, info.property, &constructor);
727 if (status != napi_ok) {
728 IMAGE_LOGE("define class fail");
729 return nullptr;
730 }
731
732 status = napi_create_reference(env, constructor, NUM_1, info.classRef);
733 if (status != napi_ok) {
734 IMAGE_LOGE("create reference fail");
735 return nullptr;
736 }
737
738 napi_value global = nullptr;
739 status = napi_get_global(env, &global);
740 if (status != napi_ok) {
741 IMAGE_LOGE("Init:get global fail");
742 return nullptr;
743 }
744
745 status = napi_set_named_property(env, global, info.className.c_str(), constructor);
746 if (status != napi_ok) {
747 IMAGE_LOGE("Init:set global named property fail");
748 return nullptr;
749 }
750
751 status = napi_set_named_property(env, exports, info.className.c_str(), constructor);
752 if (status != napi_ok) {
753 IMAGE_LOGE("set named property fail");
754 return nullptr;
755 }
756
757 status = napi_define_properties(env, exports, info.staticPropertyCount, info.staticProperty);
758 if (status != napi_ok) {
759 IMAGE_LOGE("define properties fail");
760 return nullptr;
761 }
762 return exports;
763 }
764
RegisterNapi()765 std::vector<napi_property_descriptor> ImageSourceNapi::RegisterNapi()
766 {
767 std::vector<napi_property_descriptor> properties = {
768 DECLARE_NAPI_FUNCTION("getImageInfo", GetImageInfo),
769 DECLARE_NAPI_FUNCTION("getImageInfoSync", GetImageInfoSync),
770 DECLARE_NAPI_FUNCTION("modifyImageProperty", ModifyImageProperty),
771 DECLARE_NAPI_FUNCTION("modifyImageProperties", ModifyImageProperty),
772 DECLARE_NAPI_FUNCTION("getImageProperty", GetImageProperty),
773 DECLARE_NAPI_FUNCTION("getImageProperties", GetImageProperty),
774 DECLARE_NAPI_FUNCTION("getDelayTimeList", GetDelayTime),
775 DECLARE_NAPI_FUNCTION("getDisposalTypeList", GetDisposalType),
776 DECLARE_NAPI_FUNCTION("getFrameCount", GetFrameCount),
777 DECLARE_NAPI_FUNCTION("createPixelMapList", CreatePixelMapList),
778 DECLARE_NAPI_FUNCTION("createPixelMap", CreatePixelMap),
779 DECLARE_NAPI_FUNCTION("createPixelMapSync", CreatePixelMapSync),
780 DECLARE_NAPI_FUNCTION("updateData", UpdateData),
781 DECLARE_NAPI_FUNCTION("release", Release),
782 DECLARE_NAPI_GETTER("supportedFormats", GetSupportedFormats),
783 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
784 DECLARE_NAPI_FUNCTION("createPicture", CreatePicture),
785 #endif
786 };
787
788 return properties;
789 }
790
Init(napi_env env,napi_value exports)791 napi_value ImageSourceNapi::Init(napi_env env, napi_value exports)
792 {
793 std::vector<napi_property_descriptor> props = ImageSourceNapi::RegisterNapi();
794 napi_property_descriptor static_prop[] = {
795 DECLARE_NAPI_STATIC_FUNCTION("createImageSource", CreateImageSource),
796 DECLARE_NAPI_STATIC_FUNCTION("CreateIncrementalSource", CreateIncrementalSource),
797 DECLARE_NAPI_PROPERTY("PixelMapFormat",
798 CreateEnumTypeObject(env, napi_number, &pixelMapFormatRef_, sPixelMapFormatMap)),
799 DECLARE_NAPI_PROPERTY("PropertyKey", CreateEnumTypeObject(env, napi_string, &propertyKeyRef_, sPropertyKeyMap)),
800 DECLARE_NAPI_PROPERTY("ImageFormat", CreateEnumTypeObject(env, napi_number, &imageFormatRef_, sImageFormatMap)),
801 DECLARE_NAPI_PROPERTY("AlphaType", CreateEnumTypeObject(env, napi_number, &alphaTypeRef_, sAlphaTypeMap)),
802 DECLARE_NAPI_PROPERTY("ScaleMode", CreateEnumTypeObject(env, napi_number, &scaleModeRef_, sScaleModeMap)),
803 DECLARE_NAPI_PROPERTY("ComponentType",
804 CreateEnumTypeObject(env, napi_number, &componentTypeRef_, sComponentTypeMap)),
805 DECLARE_NAPI_PROPERTY("DecodingDynamicRange",
806 CreateEnumTypeObject(env, napi_number, &decodingDynamicRangeRef_, sDecodingDynamicRangeMap)),
807 DECLARE_NAPI_PROPERTY("ResolutionQuality",
808 CreateEnumTypeObject(env, napi_number, &decodingResolutionQualityRef_, sDecodingResolutionQualityMap)),
809 };
810
811 struct ImageConstructorInfo info = {
812 .className = CLASS_NAME,
813 .classRef = &sConstructor_,
814 .constructor = Constructor,
815 .property = props.data(),
816 .propertyCount = props.size(),
817 .staticProperty = static_prop,
818 .staticPropertyCount = sizeof(static_prop) / sizeof(static_prop[NUM_0]),
819 };
820 if (DoInit(env, exports, info)) {
821 return nullptr;
822 }
823 return exports;
824 }
825
Constructor(napi_env env,napi_callback_info info)826 napi_value ImageSourceNapi::Constructor(napi_env env, napi_callback_info info)
827 {
828 napi_value undefineValue = nullptr;
829 napi_get_undefined(env, &undefineValue);
830
831 napi_status status;
832 napi_value thisVar = nullptr;
833 status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
834 if (status == napi_ok && thisVar != nullptr) {
835 std::unique_ptr<ImageSourceNapi> pImgSrcNapi = std::make_unique<ImageSourceNapi>();
836 if (pImgSrcNapi != nullptr) {
837 pImgSrcNapi->env_ = env;
838 pImgSrcNapi->nativeImgSrc = sImgSrc_;
839 if (pImgSrcNapi->nativeImgSrc == nullptr) {
840 IMAGE_LOGE("Failed to set nativeImageSource with null. Maybe a reentrancy error");
841 }
842 pImgSrcNapi->navIncPixelMap_ = sIncPixelMap_;
843 sIncPixelMap_ = nullptr;
844 sImgSrc_ = nullptr;
845 status = napi_wrap(env, thisVar, reinterpret_cast<void *>(pImgSrcNapi.get()),
846 ImageSourceNapi::Destructor, nullptr, nullptr);
847 if (status == napi_ok) {
848 pImgSrcNapi.release();
849 return thisVar;
850 } else {
851 IMAGE_LOGE("Failure wrapping js to native napi");
852 }
853 }
854 }
855
856 return undefineValue;
857 }
858
Destructor(napi_env env,void * nativeObject,void * finalize)859 void ImageSourceNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
860 {
861 reinterpret_cast<ImageSourceNapi *>(nativeObject)->nativeImgSrc = nullptr;
862 IMAGE_LOGD("ImageSourceNapi::Destructor");
863 }
864
GetSupportedFormats(napi_env env,napi_callback_info info)865 napi_value ImageSourceNapi::GetSupportedFormats(napi_env env, napi_callback_info info)
866 {
867 napi_value result = nullptr;
868 napi_get_undefined(env, &result);
869
870 napi_status status;
871 napi_value thisVar = nullptr;
872 size_t argCount = 0;
873 IMAGE_LOGD("GetSupportedFormats IN");
874
875 IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar);
876
877 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
878
879 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
880 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
881
882 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_),
883 nullptr, IMAGE_LOGE("fail to unwrap context"));
884 std::set<std::string> formats;
885 uint32_t ret = asyncContext->constructor_->nativeImgSrc->GetSupportedFormats(formats);
886
887 IMG_NAPI_CHECK_RET_D((ret == SUCCESS),
888 nullptr, IMAGE_LOGE("fail to get supported formats"));
889
890 napi_create_array(env, &result);
891 size_t i = 0;
892 for (const std::string& formatStr: formats) {
893 napi_value format = nullptr;
894 napi_create_string_latin1(env, formatStr.c_str(), formatStr.length(), &format);
895 napi_set_element(env, result, i, format);
896 i++;
897 }
898 return result;
899 }
900
STATIC_NAPI_VALUE_FUNC(GetImageInfo)901 STATIC_NAPI_VALUE_FUNC(GetImageInfo)
902 {
903 napi_value result = nullptr;
904 auto imageInfo = static_cast<ImageInfo*>(data);
905 auto rImageSource = static_cast<ImageSource*>(ptr);
906 napi_create_object(env, &result);
907
908 napi_value size = nullptr;
909 napi_create_object(env, &size);
910
911 napi_value sizeWith = nullptr;
912 napi_create_int32(env, imageInfo->size.width, &sizeWith);
913 napi_set_named_property(env, size, "width", sizeWith);
914
915 napi_value sizeHeight = nullptr;
916 napi_create_int32(env, imageInfo->size.height, &sizeHeight);
917 napi_set_named_property(env, size, "height", sizeHeight);
918
919 napi_set_named_property(env, result, "size", size);
920
921 napi_value pixelFormatValue = nullptr;
922 napi_create_int32(env, static_cast<int32_t>(imageInfo->pixelFormat), &pixelFormatValue);
923 napi_set_named_property(env, result, "pixelFormat", pixelFormatValue);
924
925 napi_value colorSpaceValue = nullptr;
926 napi_create_int32(env, static_cast<int32_t>(imageInfo->colorSpace), &colorSpaceValue);
927 napi_set_named_property(env, result, "colorSpace", colorSpaceValue);
928
929 napi_value alphaTypeValue = nullptr;
930 napi_create_int32(env, static_cast<int32_t>(imageInfo->alphaType), &alphaTypeValue);
931 napi_set_named_property(env, result, "alphaType", alphaTypeValue);
932 napi_value encodedFormatValue = nullptr;
933 napi_create_string_utf8(env, imageInfo->encodedFormat.c_str(), NAPI_AUTO_LENGTH,
934 &encodedFormatValue);
935 napi_set_named_property(env, result, "mimeType", encodedFormatValue);
936
937 if (rImageSource != nullptr) {
938 napi_value isHdrValue = nullptr;
939 napi_get_boolean(env, rImageSource->IsHdrImage(), &isHdrValue);
940 napi_set_named_property(env, result, "isHdr", isHdrValue);
941 }
942 return result;
943 }
944
STATIC_COMPLETE_FUNC(GetImageInfo)945 STATIC_COMPLETE_FUNC(GetImageInfo)
946 {
947 napi_value result = nullptr;
948 auto context = static_cast<ImageSourceAsyncContext*>(data);
949 if (context->status == SUCCESS) {
950 result = GetImageInfoNapiValue(env, &(context->imageInfo), context->rImageSource.get());
951 if (!IMG_IS_OK(status)) {
952 context->status = ERROR;
953 IMAGE_LOGE("napi_create_int32 failed!");
954 napi_get_undefined(env, &result);
955 } else {
956 context->status = SUCCESS;
957 }
958 } else {
959 napi_get_undefined(env, &result);
960 }
961
962 ImageSourceCallbackRoutine(env, context, result);
963 }
964
ParseSize(napi_env env,napi_value root,Size * size)965 static bool ParseSize(napi_env env, napi_value root, Size* size)
966 {
967 if (size == nullptr) {
968 IMAGE_LOGE("size is nullptr");
969 return false;
970 }
971 if (!GET_INT32_BY_NAME(root, "height", size->height)) {
972 return false;
973 }
974
975 if (!GET_INT32_BY_NAME(root, "width", size->width)) {
976 return false;
977 }
978
979 return true;
980 }
981
ParseRegion(napi_env env,napi_value root,Rect * region)982 static bool ParseRegion(napi_env env, napi_value root, Rect* region)
983 {
984 napi_value tmpValue = nullptr;
985
986 if (region == nullptr) {
987 IMAGE_LOGE("region is nullptr");
988 return false;
989 }
990
991 if (!GET_INT32_BY_NAME(root, "x", region->left)) {
992 return false;
993 }
994
995 if (!GET_INT32_BY_NAME(root, "y", region->top)) {
996 return false;
997 }
998
999 if (!GET_NODE_BY_NAME(root, "size", tmpValue)) {
1000 return false;
1001 }
1002
1003 if (!GET_INT32_BY_NAME(tmpValue, "height", region->height)) {
1004 return false;
1005 }
1006
1007 if (!GET_INT32_BY_NAME(tmpValue, "width", region->width)) {
1008 return false;
1009 }
1010
1011 return true;
1012 }
1013
IsSupportPixelFormat(int32_t val)1014 static bool IsSupportPixelFormat(int32_t val)
1015 {
1016 if (val >= static_cast<int32_t>(PixelFormat::UNKNOWN) &&
1017 val < static_cast<int32_t>(PixelFormat::EXTERNAL_MAX)) {
1018 return true;
1019 }
1020
1021 return false;
1022 }
1023
ParsePixlForamt(int32_t val)1024 static PixelFormat ParsePixlForamt(int32_t val)
1025 {
1026 if (val < static_cast<int32_t>(PixelFormat::EXTERNAL_MAX)) {
1027 return PixelFormat(val);
1028 }
1029
1030 return PixelFormat::UNKNOWN;
1031 }
1032
ParseResolutionQuality(napi_env env,napi_value root)1033 static ResolutionQuality ParseResolutionQuality(napi_env env, napi_value root)
1034 {
1035 uint32_t resolutionQuality = NUM_0;
1036 if (!GET_UINT32_BY_NAME(root, "resolutionQuality", resolutionQuality)) {
1037 IMAGE_LOGD("no resolutionQuality");
1038 return ResolutionQuality::UNKNOWN;
1039 }
1040 if (resolutionQuality <= static_cast<uint32_t>(ResolutionQuality::HIGH) && (resolutionQuality >=
1041 static_cast<uint32_t>(ResolutionQuality::UNKNOWN))) {
1042 return ResolutionQuality(resolutionQuality);
1043 }
1044 return ResolutionQuality::UNKNOWN;
1045 }
1046
ParseDynamicRange(napi_env env,napi_value root)1047 static DecodeDynamicRange ParseDynamicRange(napi_env env, napi_value root)
1048 {
1049 uint32_t tmpNumber = 0;
1050 if (!GET_UINT32_BY_NAME(root, "desiredDynamicRange", tmpNumber)) {
1051 IMAGE_LOGD("no desiredDynamicRange");
1052 return DecodeDynamicRange::SDR;
1053 }
1054 if (tmpNumber <= static_cast<uint32_t>(DecodeDynamicRange::HDR)) {
1055 return DecodeDynamicRange(tmpNumber);
1056 }
1057 return DecodeDynamicRange::SDR;
1058 }
1059
1060
ParseDecodeOptions2(napi_env env,napi_value root,DecodeOptions * opts,std::string & error)1061 static bool ParseDecodeOptions2(napi_env env, napi_value root, DecodeOptions* opts, std::string &error)
1062 {
1063 uint32_t tmpNumber = 0;
1064 if (!GET_UINT32_BY_NAME(root, "desiredPixelFormat", tmpNumber)) {
1065 IMAGE_LOGD("no desiredPixelFormat");
1066 } else {
1067 if (IsSupportPixelFormat(tmpNumber)) {
1068 opts->desiredPixelFormat = ParsePixlForamt(tmpNumber);
1069 } else {
1070 IMAGE_LOGD("Invalid desiredPixelFormat %{public}d", tmpNumber);
1071 error = "DecodeOptions mismatch";
1072 return false;
1073 }
1074 }
1075
1076 if (!GET_INT32_BY_NAME(root, "fitDensity", opts->fitDensity)) {
1077 IMAGE_LOGD("no fitDensity");
1078 }
1079
1080 if (GET_UINT32_BY_NAME(root, "fillColor", opts->SVGOpts.fillColor.color)) {
1081 opts->SVGOpts.fillColor.isValidColor = true;
1082 IMAGE_LOGD("fillColor %{public}x", opts->SVGOpts.fillColor.color);
1083 } else {
1084 IMAGE_LOGD("no fillColor");
1085 }
1086
1087 if (GET_UINT32_BY_NAME(root, "SVGResize", opts->SVGOpts.SVGResize.resizePercentage)) {
1088 opts->SVGOpts.SVGResize.isValidPercentage = true;
1089 IMAGE_LOGD("SVGResize percentage %{public}x", opts->SVGOpts.SVGResize.resizePercentage);
1090 } else {
1091 IMAGE_LOGD("no SVGResize percentage");
1092 }
1093 napi_value nDesiredColorSpace = nullptr;
1094 if (napi_get_named_property(env, root, "desiredColorSpace", &nDesiredColorSpace) == napi_ok) {
1095 opts->desiredColorSpaceInfo = OHOS::ColorManager::GetColorSpaceByJSObject(env, nDesiredColorSpace);
1096 IMAGE_LOGD("desiredColorSpace parse finished");
1097 }
1098 if (opts->desiredColorSpaceInfo == nullptr) {
1099 IMAGE_LOGD("no desiredColorSpace");
1100 }
1101 opts->desiredDynamicRange = ParseDynamicRange(env, root);
1102 opts->resolutionQuality = ParseResolutionQuality(env, root);
1103 return true;
1104 }
1105
ParseDecodeOptions(napi_env env,napi_value root,DecodeOptions * opts,uint32_t * pIndex,std::string & error)1106 static bool ParseDecodeOptions(napi_env env, napi_value root, DecodeOptions* opts,
1107 uint32_t* pIndex, std::string &error)
1108 {
1109 napi_value tmpValue = nullptr;
1110
1111 if (!ImageNapiUtils::GetUint32ByName(env, root, "index", pIndex)) {
1112 IMAGE_LOGD("no index");
1113 }
1114
1115 if (opts == nullptr) {
1116 IMAGE_LOGE("opts is nullptr");
1117 return false;
1118 }
1119
1120 if (!GET_UINT32_BY_NAME(root, "sampleSize", opts->sampleSize)) {
1121 IMAGE_LOGD("no sampleSize");
1122 }
1123
1124 if (!GET_UINT32_BY_NAME(root, "rotate", opts->rotateNewDegrees)) {
1125 IMAGE_LOGD("no rotate");
1126 } else {
1127 if (opts->rotateNewDegrees >= 0 &&
1128 opts->rotateNewDegrees <= 360) { // 360 is the maximum rotation angle.
1129 opts->rotateDegrees = static_cast<float>(opts->rotateNewDegrees);
1130 } else {
1131 IMAGE_LOGD("Invalid rotate %{public}d", opts->rotateNewDegrees);
1132 error = "DecodeOptions mismatch";
1133 return false;
1134 }
1135 }
1136
1137 if (!GET_BOOL_BY_NAME(root, "editable", opts->editable)) {
1138 IMAGE_LOGD("no editable");
1139 }
1140
1141 if (!GET_NODE_BY_NAME(root, "desiredSize", tmpValue)) {
1142 IMAGE_LOGD("no desiredSize");
1143 } else {
1144 if (!ParseSize(env, tmpValue, &(opts->desiredSize))) {
1145 IMAGE_LOGD("ParseSize error");
1146 }
1147 }
1148
1149 if (!GET_NODE_BY_NAME(root, "desiredRegion", tmpValue)) {
1150 IMAGE_LOGD("no desiredRegion");
1151 } else {
1152 if (!ParseRegion(env, tmpValue, &(opts->CropRect))) {
1153 IMAGE_LOGD("ParseRegion error");
1154 }
1155 }
1156 return ParseDecodeOptions2(env, root, opts, error);
1157 }
1158
FileUrlToRawPath(const std::string & path)1159 static std::string FileUrlToRawPath(const std::string &path)
1160 {
1161 if (path.size() > FILE_URL_PREFIX.size() &&
1162 (path.compare(0, FILE_URL_PREFIX.size(), FILE_URL_PREFIX) == 0)) {
1163 return path.substr(FILE_URL_PREFIX.size());
1164 }
1165 return path;
1166 }
1167
parseSourceOptions(napi_env env,napi_value root,SourceOptions * opts)1168 static void parseSourceOptions(napi_env env, napi_value root, SourceOptions* opts)
1169 {
1170 if (!ImageNapiUtils::GetInt32ByName(env, root, "sourceDensity", &(opts->baseDensity))) {
1171 IMAGE_LOGD("no sourceDensity");
1172 }
1173
1174 int32_t pixelFormat = 0;
1175 if (!ImageNapiUtils::GetInt32ByName(env, root, "sourcePixelFormat", &pixelFormat)) {
1176 IMAGE_LOGD("no sourcePixelFormat");
1177 } else {
1178 opts->pixelFormat = static_cast<PixelFormat>(pixelFormat);
1179 IMAGE_LOGI("sourcePixelFormat:%{public}d", static_cast<int32_t>(opts->pixelFormat));
1180 }
1181
1182 napi_value tmpValue = nullptr;
1183 if (!GET_NODE_BY_NAME(root, "sourceSize", tmpValue)) {
1184 IMAGE_LOGD("no sourceSize");
1185 } else {
1186 if (!ParseSize(env, tmpValue, &(opts->size))) {
1187 IMAGE_LOGD("ParseSize error");
1188 }
1189 IMAGE_LOGI("sourceSize:(%{public}d, %{public}d)", opts->size.width, opts->size.height);
1190 }
1191 }
PrepareNapiEnv(napi_env env)1192 static void PrepareNapiEnv(napi_env env)
1193 {
1194 napi_value globalValue;
1195 napi_get_global(env, &globalValue);
1196 napi_value func;
1197 napi_get_named_property(env, globalValue, "requireNapi", &func);
1198
1199 napi_value imageInfo;
1200 napi_create_string_utf8(env, "multimedia.image", NAPI_AUTO_LENGTH, &imageInfo);
1201 napi_value funcArgv[1] = { imageInfo };
1202 napi_value returnValue;
1203 napi_call_function(env, globalValue, func, 1, funcArgv, &returnValue);
1204 }
1205
hasNamedProperty(napi_env env,napi_value object,std::string name)1206 static bool hasNamedProperty(napi_env env, napi_value object, std::string name)
1207 {
1208 bool res = false;
1209 return (napi_has_named_property(env, object, name.c_str(), &res) == napi_ok) && res;
1210 }
1211
parseRawFileItem(napi_env env,napi_value argValue,std::string item,int32_t * value)1212 static bool parseRawFileItem(napi_env env, napi_value argValue, std::string item, int32_t* value)
1213 {
1214 napi_value nItem;
1215 if (napi_get_named_property(env, argValue, item.c_str(), &nItem) != napi_ok) {
1216 IMAGE_LOGE("Failed to parse RawFileDescriptor item %{public}s", item.c_str());
1217 return false;
1218 }
1219 if (napi_get_value_int32(env, nItem, value) != napi_ok) {
1220 IMAGE_LOGE("Failed to get RawFileDescriptor item %{public}s value", item.c_str());
1221 return false;
1222 }
1223 return true;
1224 }
1225
isRawFileDescriptor(napi_env env,napi_value argValue,ImageSourceAsyncContext * context)1226 static bool isRawFileDescriptor(napi_env env, napi_value argValue, ImageSourceAsyncContext* context)
1227 {
1228 if (env == nullptr || argValue == nullptr || context == nullptr) {
1229 IMAGE_LOGE("isRawFileDescriptor invalid input");
1230 return false;
1231 }
1232 if (!hasNamedProperty(env, argValue, "fd") ||
1233 !hasNamedProperty(env, argValue, "offset") ||
1234 !hasNamedProperty(env, argValue, "length")) {
1235 IMAGE_LOGD("RawFileDescriptor mismatch");
1236 return false;
1237 }
1238 if (parseRawFileItem(env, argValue, "fd", &(context->rawFileInfo.fd)) &&
1239 parseRawFileItem(env, argValue, "offset", &(context->rawFileInfo.offset)) &&
1240 parseRawFileItem(env, argValue, "length", &(context->rawFileInfo.length))) {
1241 return true;
1242 }
1243
1244 IMAGE_LOGE("Failed to parse RawFileDescriptor item");
1245 return false;
1246 }
1247
CreateNativeImageSource(napi_env env,napi_value argValue,SourceOptions & opts,ImageSourceAsyncContext * context)1248 static std::unique_ptr<ImageSource> CreateNativeImageSource(napi_env env, napi_value argValue,
1249 SourceOptions &opts, ImageSourceAsyncContext* context)
1250 {
1251 std::unique_ptr<ImageSource> imageSource = nullptr;
1252 uint32_t errorCode = ERR_MEDIA_INVALID_VALUE;
1253 napi_status status;
1254
1255 auto inputType = ImageNapiUtils::getType(env, argValue);
1256 if (napi_string == inputType) { // File Path
1257 if (!ImageNapiUtils::GetUtf8String(env, argValue, context->pathName)) {
1258 IMAGE_LOGE("fail to get pathName");
1259 return imageSource;
1260 }
1261 context->pathName = FileUrlToRawPath(context->pathName);
1262 context->pathNameLength = context->pathName.size();
1263 imageSource = ImageSource::CreateImageSource(context->pathName, opts, errorCode);
1264 } else if (napi_number == inputType) { // Fd
1265 napi_get_value_int32(env, argValue, &context->fdIndex);
1266 IMAGE_LOGD("CreateImageSource fdIndex is [%{public}d]", context->fdIndex);
1267 imageSource = ImageSource::CreateImageSource(context->fdIndex, opts, errorCode);
1268 } else if (isRawFileDescriptor(env, argValue, context)) {
1269 IMAGE_LOGE(
1270 "CreateImageSource RawFileDescriptor fd: %{public}d, offset: %{public}d, length: %{public}d",
1271 context->rawFileInfo.fd, context->rawFileInfo.offset, context->rawFileInfo.length);
1272 int32_t fileSize = context->rawFileInfo.offset + context->rawFileInfo.length;
1273 imageSource = ImageSource::CreateImageSource(context->rawFileInfo.fd,
1274 context->rawFileInfo.offset, fileSize, opts, errorCode);
1275 } else { // Input Buffer
1276 uint32_t refCount = NUM_1;
1277 napi_ref arrayRef = nullptr;
1278 napi_create_reference(env, argValue, refCount, &arrayRef);
1279 status = napi_get_arraybuffer_info(env, argValue, &(context->sourceBuffer), &(context->sourceBufferSize));
1280 if (status != napi_ok) {
1281 napi_delete_reference(env, arrayRef);
1282 IMAGE_LOGE("fail to get arraybufferinfo");
1283 return nullptr;
1284 }
1285 imageSource = ImageSource::CreateImageSource(static_cast<uint8_t *>(context->sourceBuffer),
1286 context->sourceBufferSize, opts, errorCode);
1287 napi_delete_reference(env, arrayRef);
1288 }
1289 return imageSource;
1290 }
1291
CreateImageSource(napi_env env,napi_callback_info info)1292 napi_value ImageSourceNapi::CreateImageSource(napi_env env, napi_callback_info info)
1293 {
1294 napi_value result = nullptr;
1295 napi_get_undefined(env, &result);
1296
1297 napi_status status;
1298 napi_value thisVar = nullptr;
1299 napi_value argValue[NUM_2] = {0};
1300 size_t argCount = 2;
1301 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1302 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1303 NAPI_ASSERT(env, argCount > 0, "No arg!");
1304
1305 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
1306 SourceOptions opts;
1307 if (argCount > NUM_1) {
1308 parseSourceOptions(env, argValue[NUM_1], &opts);
1309 }
1310 std::unique_ptr<ImageSource> imageSource = CreateNativeImageSource(env, argValue[NUM_0],
1311 opts, asyncContext.get());
1312 if (imageSource == nullptr) {
1313 IMAGE_LOGE("CreateImageSourceExec error");
1314 napi_get_undefined(env, &result);
1315 return result;
1316 }
1317
1318 {
1319 std::lock_guard<std::mutex> lock(imageSourceCrossThreadMutex_);
1320 filePath_ = asyncContext->pathName;
1321 fileDescriptor_ = asyncContext->fdIndex;
1322 fileBuffer_ = asyncContext->sourceBuffer;
1323 fileBufferSize_ = asyncContext->sourceBufferSize;
1324 }
1325
1326 napi_value constructor = nullptr;
1327 status = napi_get_reference_value(env, sConstructor_, &constructor);
1328 if (IMG_IS_OK(status)) {
1329 sImgSrc_ = std::move(imageSource);
1330 status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
1331 }
1332 if (!IMG_IS_OK(status)) {
1333 IMAGE_LOGE("New instance could not be obtained");
1334 napi_get_undefined(env, &result);
1335 }
1336 return result;
1337 }
1338
CreateImageSourceComplete(napi_env env,napi_status status,void * data)1339 napi_value ImageSourceNapi::CreateImageSourceComplete(napi_env env, napi_status status, void *data)
1340 {
1341 napi_value constructor = nullptr;
1342 napi_value result = nullptr;
1343
1344 IMAGE_LOGD("CreateImageSourceComplete IN");
1345 auto context = static_cast<ImageSourceAsyncContext*>(data);
1346 if (context == nullptr) {
1347 return result;
1348 }
1349 status = napi_get_reference_value(env, sConstructor_, &constructor);
1350 if (IMG_IS_OK(status)) {
1351 sImgSrc_ = context->rImageSource;
1352 status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
1353 }
1354
1355 if (!IMG_IS_OK(status)) {
1356 context->status = ERROR;
1357 IMAGE_LOGE("New instance could not be obtained");
1358 napi_get_undefined(env, &result);
1359 }
1360 return result;
1361 }
1362
CreateIncrementalSource(napi_env env,napi_callback_info info)1363 napi_value ImageSourceNapi::CreateIncrementalSource(napi_env env, napi_callback_info info)
1364 {
1365 napi_value globalValue;
1366 napi_get_global(env, &globalValue);
1367 napi_value func;
1368 napi_get_named_property(env, globalValue, "requireNapi", &func);
1369
1370 napi_value imageInfo;
1371 napi_create_string_utf8(env, "multimedia.image", NAPI_AUTO_LENGTH, &imageInfo);
1372 napi_value funcArgv[1] = { imageInfo };
1373 napi_value returnValue;
1374 napi_call_function(env, globalValue, func, 1, funcArgv, &returnValue);
1375
1376 napi_value result = nullptr;
1377 napi_get_undefined(env, &result);
1378
1379 napi_status status;
1380 IMAGE_LOGD("CreateIncrementalSource IN");
1381
1382 napi_value thisVar = nullptr;
1383 napi_value argValue[NUM_2] = {0};
1384 size_t argCount = NUM_2;
1385 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1386 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1387
1388 uint32_t errorCode = 0;
1389 IncrementalSourceOptions incOpts;
1390 if (argCount == NUM_2) {
1391 parseSourceOptions(env, argValue[NUM_1], &(incOpts.sourceOptions));
1392 }
1393
1394 incOpts.incrementalMode = IncrementalMode::INCREMENTAL_DATA;
1395 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateIncrementalImageSource(incOpts, errorCode);
1396 DecodeOptions decodeOpts;
1397 std::unique_ptr<IncrementalPixelMap> incPixelMap = imageSource->CreateIncrementalPixelMap(0, decodeOpts, errorCode);
1398 IMAGE_LOGD("CreateIncrementalImageSource end");
1399 if (errorCode != SUCCESS) {
1400 IMAGE_LOGE("CreateIncrementalImageSource error");
1401 napi_get_undefined(env, &result);
1402 return result;
1403 }
1404 napi_value constructor = nullptr;
1405 status = napi_get_reference_value(env, sConstructor_, &constructor);
1406 if (IMG_IS_OK(status)) {
1407 sImgSrc_ = std::move(imageSource);
1408 sIncPixelMap_ = std::move(incPixelMap);
1409 status = napi_new_instance(env, constructor, NUM_0, nullptr, &result);
1410 }
1411 if (!IMG_IS_OK(status)) {
1412 IMAGE_LOGE("New instance could not be obtained");
1413 napi_get_undefined(env, &result);
1414 }
1415 return result;
1416 }
1417
GetImageInfo(napi_env env,napi_callback_info info)1418 napi_value ImageSourceNapi::GetImageInfo(napi_env env, napi_callback_info info)
1419 {
1420 ImageTrace imageTrace("ImageSourceNapi::GetImageInfo");
1421 napi_value result = nullptr;
1422 napi_get_undefined(env, &result);
1423
1424 int32_t refCount = 1;
1425 napi_status status;
1426 napi_value thisVar = nullptr;
1427 napi_value argValue[NUM_2] = {0};
1428 size_t argCount = 2;
1429 IMAGE_LOGD("GetImageInfo IN");
1430 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1431 IMAGE_LOGD("GetImageInfo argCount is [%{public}zu]", argCount);
1432
1433 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1434
1435 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
1436 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
1437
1438 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_),
1439 nullptr, IMAGE_LOGE("fail to unwrap context"));
1440
1441 asyncContext->rImageSource = asyncContext->constructor_->nativeImgSrc;
1442
1443 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rImageSource),
1444 nullptr, IMAGE_LOGE("empty native pixelmap"));
1445 IMAGE_LOGD("GetImageInfo argCount is [%{public}zu]", argCount);
1446 if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_function) {
1447 IMAGE_LOGD("GetImageInfo arg0 getType is [%{public}u]", ImageNapiUtils::getType(env, argValue[NUM_0]));
1448 napi_create_reference(env, argValue[NUM_0], refCount, &asyncContext->callbackRef);
1449 } else if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_number) {
1450 napi_get_value_uint32(env, argValue[NUM_0], &asyncContext->index);
1451 } else if (argCount == NUM_2 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_number
1452 && ImageNapiUtils::getType(env, argValue[NUM_1]) == napi_function) {
1453 IMAGE_LOGD("GetImageInfo arg0 getType is [%{public}u]", ImageNapiUtils::getType(env, argValue[NUM_0]));
1454 IMAGE_LOGD("GetImageInfo arg1 getType is [%{public}u]", ImageNapiUtils::getType(env, argValue[NUM_1]));
1455 napi_get_value_uint32(env, argValue[NUM_0], &asyncContext->index);
1456 napi_create_reference(env, argValue[NUM_1], refCount, &asyncContext->callbackRef);
1457 }
1458
1459 if (asyncContext->callbackRef == nullptr) {
1460 napi_create_promise(env, &(asyncContext->deferred), &result);
1461 } else {
1462 napi_get_undefined(env, &result);
1463 }
1464
1465 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageInfo",
1466 [](napi_env env, void *data) {
1467 auto context = static_cast<ImageSourceAsyncContext*>(data);
1468 int index = (context->index >= NUM_0) ? context->index : NUM_0;
1469 context->status = context->rImageSource->GetImageInfo(index, context->imageInfo);
1470 }, GetImageInfoComplete, asyncContext, asyncContext->work);
1471
1472 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1473 nullptr, IMAGE_LOGE("fail to create async work"));
1474 return result;
1475 }
1476
GetImageInfoSync(napi_env env,napi_callback_info info)1477 napi_value ImageSourceNapi::GetImageInfoSync(napi_env env, napi_callback_info info)
1478 {
1479 napi_value result = nullptr;
1480 napi_get_undefined(env, &result);
1481 napi_status status;
1482 napi_value thisVar = nullptr;
1483 napi_value argValue[NUM_1] = {0};
1484 size_t argCount = NUM_1;
1485 uint32_t index = 0;
1486 uint32_t ret = SUCCESS;
1487
1488 IMAGE_LOGD("GetImageInfoSync IN");
1489 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1490 IMAGE_LOGD("GetImageInfoSync argCount is [%{public}zu]", argCount);
1491 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1492
1493 std::unique_ptr<ImageSourceNapi> imageSourceNapi = nullptr;
1494 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&imageSourceNapi));
1495
1496 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, imageSourceNapi),
1497 nullptr, IMAGE_LOGE("fail to unwrap context"));
1498 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, imageSourceNapi->nativeImgSrc),
1499 nullptr, IMAGE_LOGE("empty native pixelmap"));
1500
1501 if (argCount == NUM_1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_number) {
1502 napi_get_value_uint32(env, argValue[NUM_0], &index);
1503 }
1504
1505 if (imageSourceNapi->nativeImgSrc != nullptr) {
1506 ImageInfo imageinfo;
1507 ret = imageSourceNapi->nativeImgSrc->GetImageInfo(index, imageinfo);
1508 if (ret == SUCCESS) {
1509 result = GetImageInfoNapiValue(env, &imageinfo, imageSourceNapi->nativeImgSrc.get());
1510 }
1511 } else {
1512 IMAGE_LOGE("native imageSourceNapi is nullptr!");
1513 }
1514 imageSourceNapi.release();
1515 return result;
1516 }
1517
CreatePixelMapInner(ImageSourceNapi * thisPtr,std::shared_ptr<ImageSource> imageSource,uint32_t index,DecodeOptions decodeOpts,uint32_t & status)1518 static std::shared_ptr<PixelMap> CreatePixelMapInner(ImageSourceNapi *thisPtr,
1519 std::shared_ptr<ImageSource> imageSource, uint32_t index, DecodeOptions decodeOpts, uint32_t &status)
1520 {
1521 if (thisPtr == nullptr || imageSource == nullptr) {
1522 IMAGE_LOGE("Invailed args");
1523 status = ERROR;
1524 }
1525
1526 std::shared_ptr<PixelMap> pixelMap;
1527 auto incPixelMap = (thisPtr == nullptr) ? nullptr : thisPtr->GetIncrementalPixelMap();
1528 if (incPixelMap != nullptr) {
1529 IMAGE_LOGD("Get Incremental PixelMap!!!");
1530 pixelMap = incPixelMap;
1531 } else {
1532 decodeOpts.invokeType = JS_INTERFACE;
1533 pixelMap = (imageSource == nullptr) ? nullptr : imageSource->CreatePixelMapEx((index >= NUM_0) ? index : NUM_0,
1534 decodeOpts, status);
1535 }
1536
1537 if (status != SUCCESS || !IMG_NOT_NULL(pixelMap)) {
1538 IMAGE_LOGE("Create PixelMap error");
1539 }
1540
1541 return pixelMap;
1542 }
1543
CreatePixelMapExecute(napi_env env,void * data)1544 static void CreatePixelMapExecute(napi_env env, void *data)
1545 {
1546 IMAGE_LOGD("CreatePixelMapExecute IN");
1547 if (data == nullptr) {
1548 IMAGE_LOGE("data is nullptr");
1549 return;
1550 }
1551 auto context = static_cast<ImageSourceAsyncContext*>(data);
1552 if (context == nullptr) {
1553 IMAGE_LOGE("empty context");
1554 return;
1555 }
1556
1557 if (context->errMsg.size() > 0) {
1558 IMAGE_LOGE("mismatch args");
1559 context->status = ERROR;
1560 return;
1561 }
1562
1563 context->rPixelMap = CreatePixelMapInner(context->constructor_, context->rImageSource,
1564 context->index, context->decodeOpts, context->status);
1565
1566 if (context->status != SUCCESS) {
1567 context->errMsg = "Create PixelMap error";
1568 IMAGE_LOGE("Create PixelMap error");
1569 }
1570 IMAGE_LOGD("CreatePixelMapExecute OUT");
1571 }
1572
CreatePixelMapComplete(napi_env env,napi_status status,void * data)1573 static void CreatePixelMapComplete(napi_env env, napi_status status, void *data)
1574 {
1575 IMAGE_LOGD("CreatePixelMapComplete IN");
1576 napi_value result = nullptr;
1577 auto context = static_cast<ImageSourceAsyncContext*>(data);
1578
1579 if (context->status == SUCCESS) {
1580 result = PixelMapNapi::CreatePixelMap(env, context->rPixelMap);
1581 } else {
1582 napi_get_undefined(env, &result);
1583 }
1584 IMAGE_LOGD("CreatePixelMapComplete OUT");
1585 ImageSourceCallbackRoutine(env, context, result);
1586 }
1587
CreatePixelMapCompleteSync(napi_env env,napi_status status,ImageSourceSyncContext * context)1588 static napi_value CreatePixelMapCompleteSync(napi_env env, napi_status status, ImageSourceSyncContext *context)
1589 {
1590 IMAGE_LOGD("CreatePixelMapCompleteSync IN");
1591 napi_value result = nullptr;
1592
1593 if (context->status == SUCCESS) {
1594 result = PixelMapNapi::CreatePixelMap(env, context->rPixelMap);
1595 } else {
1596 napi_get_undefined(env, &result);
1597 }
1598 IMAGE_LOGD("CreatePixelMapCompleteSync OUT");
1599 return result;
1600 }
1601
CreatePixelMap(napi_env env,napi_callback_info info)1602 napi_value ImageSourceNapi::CreatePixelMap(napi_env env, napi_callback_info info)
1603 {
1604 napi_value result = nullptr;
1605 napi_get_undefined(env, &result);
1606
1607 int32_t refCount = 1;
1608 napi_status status;
1609 napi_value thisVar = nullptr;
1610 napi_value argValue[NUM_2] = {0};
1611 size_t argCount = NUM_2;
1612 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1613 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, thisVar), nullptr, IMAGE_LOGE("fail to get thisVar"));
1614 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1615
1616 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
1617
1618 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
1619 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_),
1620 nullptr, IMAGE_LOGE("fail to unwrap context"));
1621 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_->nativeImgSrc),
1622 nullptr, IMAGE_LOGE("fail to unwrap nativeImgSrc"));
1623 asyncContext->rImageSource = asyncContext->constructor_->nativeImgSrc;
1624 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rImageSource),
1625 nullptr, IMAGE_LOGE("empty native rImageSource"));
1626
1627 if (argCount == NUM_0) {
1628 IMAGE_LOGD("CreatePixelMap with no arg");
1629 } else if (argCount == NUM_1 || argCount == NUM_2) {
1630 if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_object) {
1631 if (!ParseDecodeOptions(env, argValue[NUM_0], &(asyncContext->decodeOpts),
1632 &(asyncContext->index), asyncContext->errMsg)) {
1633 IMAGE_LOGE("DecodeOptions mismatch");
1634 }
1635 }
1636 if (ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1637 napi_create_reference(env, argValue[argCount - 1], refCount, &asyncContext->callbackRef);
1638 }
1639 } else {
1640 IMAGE_LOGE("argCount mismatch");
1641 return result;
1642 }
1643 if (asyncContext->callbackRef == nullptr) {
1644 napi_create_promise(env, &(asyncContext->deferred), &result);
1645 } else {
1646 napi_get_undefined(env, &result);
1647 }
1648
1649 ImageNapiUtils::HicheckerReport();
1650 IMG_CREATE_CREATE_ASYNC_WORK_WITH_QOS(env, status, "CreatePixelMap", CreatePixelMapExecute,
1651 CreatePixelMapComplete, asyncContext, asyncContext->work, napi_qos_user_initiated);
1652
1653 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1654 nullptr, IMAGE_LOGE("fail to create async work"));
1655 return result;
1656 }
1657
CreatePixelMapSync(napi_env env,napi_callback_info info)1658 napi_value ImageSourceNapi::CreatePixelMapSync(napi_env env, napi_callback_info info)
1659 {
1660 napi_value result = nullptr;
1661 napi_get_undefined(env, &result);
1662
1663 napi_status status;
1664 napi_value thisVar = nullptr;
1665 napi_value argValue[NUM_1] = {0};
1666 size_t argCount = NUM_1;
1667 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1668 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, thisVar), nullptr, IMAGE_LOGE("fail to get thisVar"));
1669 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1670
1671 std::unique_ptr<ImageSourceSyncContext> syncContext = std::make_unique<ImageSourceSyncContext>();
1672 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&syncContext->constructor_));
1673 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, syncContext->constructor_),
1674 nullptr, IMAGE_LOGE("fail to unwrap context"));
1675 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, syncContext->constructor_->nativeImgSrc),
1676 nullptr, IMAGE_LOGE("fail to unwrap nativeImgSrc"));
1677
1678 if (argCount == NUM_0) {
1679 IMAGE_LOGD("CreatePixelMap with no arg");
1680 } else if (argCount == NUM_1) {
1681 if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_object) {
1682 if (!ParseDecodeOptions(env, argValue[NUM_0], &(syncContext->decodeOpts),
1683 &(syncContext->index), syncContext->errMsg)) {
1684 IMAGE_LOGE("DecodeOptions mismatch");
1685 syncContext->errMsg = "DecodeOptions mismatch";
1686 return result;
1687 }
1688 }
1689 }
1690
1691 syncContext->rPixelMap = CreatePixelMapInner(syncContext->constructor_, syncContext->constructor_->nativeImgSrc,
1692 syncContext->index, syncContext->decodeOpts, syncContext->status);
1693
1694 if (syncContext->status != SUCCESS) {
1695 syncContext->errMsg = "Create PixelMap error";
1696 IMAGE_LOGE("Create PixelMap error");
1697 }
1698 result = CreatePixelMapCompleteSync(env, status, static_cast<ImageSourceSyncContext*>((syncContext).get()));
1699
1700 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
1701 nullptr, IMAGE_LOGE("fail to create PixelMap"));
1702 return result;
1703 }
1704
ParsePropertyOptions(napi_env env,napi_value root,ImageSourceAsyncContext * context)1705 static bool ParsePropertyOptions(napi_env env, napi_value root, ImageSourceAsyncContext* context)
1706 {
1707 napi_value tmpValue = nullptr;
1708 if (!GET_UINT32_BY_NAME(root, "index", context->index)) {
1709 IMAGE_LOGD("no index");
1710 return false;
1711 }
1712 if (!GET_NODE_BY_NAME(root, "defaultValue", tmpValue)) {
1713 IMAGE_LOGD("no defaultValue");
1714 } else {
1715 if (tmpValue != nullptr) {
1716 context->defaultValueStr = GetStringArgument(env, tmpValue);
1717 }
1718 }
1719 return true;
1720 }
1721
ModifyImagePropertyComplete(napi_env env,napi_status status,ImageSourceAsyncContext * context)1722 static void ModifyImagePropertyComplete(napi_env env, napi_status status, ImageSourceAsyncContext *context)
1723 {
1724 if (context == nullptr) {
1725 IMAGE_LOGE("context is nullptr");
1726 return;
1727 }
1728
1729 napi_value result[NUM_2] = {0};
1730 napi_get_undefined(env, &result[NUM_0]);
1731 napi_get_undefined(env, &result[NUM_1]);
1732 napi_value retVal;
1733 napi_value callback = nullptr;
1734 if (context->isBatch) {
1735 result[NUM_0] = CreateModifyErrorArray(env, context->errMsgArray);
1736 } else {
1737 if (context->status == ERR_MEDIA_WRITE_PARCEL_FAIL) {
1738 if (context->fdIndex != -1) {
1739 ImageNapiUtils::CreateErrorObj(env, result[NUM_0], context->status,
1740 "Create Fd without write permission!");
1741 } else {
1742 ImageNapiUtils::CreateErrorObj(env, result[0], context->status,
1743 "The EXIF data failed to be written to the file.");
1744 }
1745 } else if (context->status == ERR_MEDIA_OUT_OF_RANGE) {
1746 ImageNapiUtils::CreateErrorObj(env, result[NUM_0], context->status,
1747 "The given buffer size is too small to add new exif data!");
1748 } else if (context->status == ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
1749 ImageNapiUtils::CreateErrorObj(env, result[NUM_0], context->status,
1750 "The exif data format is not standard, so modify it failed!");
1751 } else if (context->status == ERR_MEDIA_VALUE_INVALID) {
1752 ImageNapiUtils::CreateErrorObj(env, result[NUM_0], context->status, context->errMsg);
1753 }
1754 }
1755
1756 if (context->deferred) {
1757 if (context->status == SUCCESS) {
1758 napi_resolve_deferred(env, context->deferred, result[NUM_1]);
1759 } else {
1760 napi_reject_deferred(env, context->deferred, result[NUM_0]);
1761 }
1762 } else {
1763 IMAGE_LOGD("call callback function");
1764 napi_get_reference_value(env, context->callbackRef, &callback);
1765 napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
1766 napi_delete_reference(env, context->callbackRef);
1767 }
1768
1769 napi_delete_async_work(env, context->work);
1770
1771 delete context;
1772 context = nullptr;
1773 }
1774
GenerateErrMsg(ImageSourceAsyncContext * context,std::string & errMsg)1775 static void GenerateErrMsg(ImageSourceAsyncContext *context, std::string &errMsg)
1776 {
1777 if (context == nullptr) {
1778 return;
1779 }
1780 switch (context->status) {
1781 case ERR_IMAGE_DECODE_EXIF_UNSUPPORT:
1782 errMsg = "The image does not support EXIF decoding.";
1783 break;
1784 case ERROR:
1785 errMsg = "The operation failed.";
1786 break;
1787 case ERR_IMAGE_DATA_UNSUPPORT:
1788 errMsg = "The image data is not supported.";
1789 break;
1790 case ERR_IMAGE_SOURCE_DATA:
1791 errMsg = "The image source data is incorrect.";
1792 break;
1793 case ERR_IMAGE_SOURCE_DATA_INCOMPLETE:
1794 errMsg = "The image source data is incomplete.";
1795 break;
1796 case ERR_IMAGE_MISMATCHED_FORMAT:
1797 errMsg = "The image format does not mastch.";
1798 break;
1799 case ERR_IMAGE_UNKNOWN_FORMAT:
1800 errMsg = "Unknown image format.";
1801 break;
1802 case ERR_IMAGE_INVALID_PARAMETER:
1803 errMsg = "Invalid image parameter.";
1804 break;
1805 case ERR_IMAGE_DECODE_FAILED:
1806 errMsg = "Failed to decode the image.";
1807 break;
1808 case ERR_IMAGE_PLUGIN_CREATE_FAILED:
1809 errMsg = "Failed to create the image plugin.";
1810 break;
1811 case ERR_IMAGE_DECODE_HEAD_ABNORMAL:
1812 errMsg = "Failed to decode the image header.";
1813 break;
1814 case ERR_MEDIA_VALUE_INVALID:
1815 errMsg = "The EXIF value is invalid.";
1816 break;
1817 default:
1818 errMsg = "There is unknown error happened.";
1819 }
1820 }
1821
GetImagePropertyComplete(napi_env env,napi_status status,ImageSourceAsyncContext * context)1822 static void GetImagePropertyComplete(napi_env env, napi_status status, ImageSourceAsyncContext *context)
1823 {
1824 if (context == nullptr) {
1825 IMAGE_LOGE("context is nullptr");
1826 return;
1827 }
1828
1829 napi_value result[NUM_2] = {0};
1830 napi_value retVal;
1831 napi_value callback = nullptr;
1832
1833 napi_get_undefined(env, &result[NUM_0]);
1834 napi_get_undefined(env, &result[NUM_1]);
1835
1836 if (context->status == SUCCESS) {
1837 if (context->isBatch) {
1838 result[NUM_1] = SetRecordParametersInfo(env, context->kVStrArray);
1839 } else {
1840 napi_create_string_utf8(env, context->valueStr.c_str(), context->valueStr.length(), &result[NUM_1]);
1841 }
1842 } else {
1843 if (context->isBatch) {
1844 result[NUM_0] = CreateObtainErrorArray(env, context->errMsgArray);
1845 } else {
1846 std::string errMsg;
1847 GenerateErrMsg(context, errMsg);
1848 ImageNapiUtils::CreateErrorObj(env, result[NUM_0], context->status, errMsg);
1849
1850 if (!context->defaultValueStr.empty()) {
1851 napi_create_string_utf8(env, context->defaultValueStr.c_str(),
1852 context->defaultValueStr.length(), &result[NUM_1]);
1853 context->status = SUCCESS;
1854 }
1855 }
1856 }
1857
1858 if (context->deferred) {
1859 if (context->status == SUCCESS) {
1860 napi_resolve_deferred(env, context->deferred, result[NUM_1]);
1861 } else {
1862 napi_reject_deferred(env, context->deferred, result[NUM_0]);
1863 }
1864 } else {
1865 IMAGE_LOGD("call callback function");
1866 napi_get_reference_value(env, context->callbackRef, &callback);
1867 napi_call_function(env, nullptr, callback, NUM_2, result, &retVal);
1868 napi_delete_reference(env, context->callbackRef);
1869 }
1870
1871 napi_delete_async_work(env, context->work);
1872 delete context;
1873 context = nullptr;
1874 }
1875
UnwrapContext(napi_env env,napi_callback_info info)1876 static std::unique_ptr<ImageSourceAsyncContext> UnwrapContext(napi_env env, napi_callback_info info)
1877 {
1878 int32_t refCount = 1;
1879 napi_status status;
1880 napi_value thisVar = nullptr;
1881 napi_value argValue[NUM_3] = {0};
1882 size_t argCount = NUM_3;
1883 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
1884 IMAGE_LOGD("GetImageProperty argCount is [%{public}zu]", argCount);
1885
1886 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
1887
1888 std::unique_ptr<ImageSourceAsyncContext> context = std::make_unique<ImageSourceAsyncContext>();
1889 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&context->constructor_));
1890
1891 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_),
1892 nullptr, IMAGE_LOGE("fail to unwrap context"));
1893
1894 context->rImageSource = context->constructor_->nativeImgSrc;
1895
1896 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->rImageSource),
1897 nullptr, IMAGE_LOGE("empty native rImageSource"));
1898
1899 if (argCount < NUM_1 || argCount > NUM_3) {
1900 IMAGE_LOGE("argCount mismatch");
1901 return nullptr;
1902 }
1903 if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_string) {
1904 context->keyStr = GetStringArgument(env, argValue[NUM_0]);
1905 } else if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_object) {
1906 context->keyStrArray = GetStringArrayArgument(env, argValue[NUM_0]);
1907 if (context->keyStrArray.size() == 0) {
1908 return nullptr;
1909 }
1910 context->isBatch = true;
1911 } else {
1912 IMAGE_LOGE("arg 0 type mismatch");
1913 return nullptr;
1914 }
1915 if (argCount == NUM_2 || argCount == NUM_3) {
1916 if (ImageNapiUtils::getType(env, argValue[NUM_1]) == napi_object) {
1917 IMG_NAPI_CHECK_RET_D(ParsePropertyOptions(env, argValue[NUM_1], context.get()),
1918 nullptr, IMAGE_LOGE("PropertyOptions mismatch"));
1919 }
1920 if (ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
1921 napi_create_reference(env, argValue[argCount - 1], refCount, &context->callbackRef);
1922 }
1923 }
1924 return context;
1925 }
1926
CheckExifDataValue(const std::string & key,const std::string & value,std::string & errorInfo)1927 static uint32_t CheckExifDataValue(const std::string &key, const std::string &value, std::string &errorInfo)
1928 {
1929 auto status = static_cast<uint32_t>(ExifMetadatFormatter::Validate(key, value));
1930 if (status != SUCCESS) {
1931 errorInfo = key + " has invalid exif value: ";
1932 errorInfo.append(value);
1933 }
1934 return status;
1935 }
1936
ModifyImagePropertiesExecute(napi_env env,void * data)1937 static void ModifyImagePropertiesExecute(napi_env env, void *data)
1938 {
1939 auto context = static_cast<ImageSourceAsyncContext*>(data);
1940 if (context == nullptr) {
1941 IMAGE_LOGE("empty context");
1942 return;
1943 }
1944 uint32_t status = SUCCESS;
1945 for (auto recordIterator = context->kVStrArray.begin(); recordIterator != context->kVStrArray.end();
1946 ++recordIterator) {
1947 IMAGE_LOGD("CheckExifDataValue");
1948 status = CheckExifDataValue(recordIterator->first, recordIterator->second, context->errMsg);
1949 IMAGE_LOGD("Check ret status: %{public}d", status);
1950 if (status != SUCCESS) {
1951 IMAGE_LOGE("There is invalid exif data parameter");
1952 context->errMsgArray.insert(std::make_pair(status, context->errMsg));
1953 continue;
1954 }
1955 if (!IsSameTextStr(context->pathName, "")) {
1956 status = context->rImageSource->ModifyImageProperty(0, recordIterator->first,
1957 recordIterator->second, context->pathName);
1958 } else if (context->fdIndex != -1) {
1959 status = context->rImageSource->ModifyImageProperty(0, recordIterator->first,
1960 recordIterator->second, context->fdIndex);
1961 } else if (context->sourceBuffer != nullptr) {
1962 status = context->rImageSource->ModifyImageProperty(0, recordIterator->first,
1963 recordIterator->second, static_cast<uint8_t *>(context->sourceBuffer),
1964 context->sourceBufferSize);
1965 } else {
1966 context->errMsgArray.insert(std::make_pair(ERROR, recordIterator->first));
1967 IMAGE_LOGE("There is no image source!");
1968 continue;
1969 }
1970 if (status != SUCCESS) {
1971 context->errMsgArray.insert(std::make_pair(status, recordIterator->first));
1972 }
1973 }
1974 context->status = context->errMsgArray.size() > 0 ? ERROR : SUCCESS;
1975 }
1976
ModifyImagePropertyExecute(napi_env env,void * data)1977 static void ModifyImagePropertyExecute(napi_env env, void *data)
1978 {
1979 auto context = static_cast<ImageSourceAsyncContext*>(data);
1980 if (context == nullptr) {
1981 IMAGE_LOGE("empty context");
1982 return;
1983 }
1984 IMAGE_LOGD("ModifyImagePropertyExecute CheckExifDataValue");
1985 uint32_t status = CheckExifDataValue(context->keyStr, context->valueStr, context->errMsg);
1986 IMAGE_LOGD("ModifyImagePropertyExecute Check ret status: %{public}d", status);
1987 if (status != SUCCESS) {
1988 IMAGE_LOGE("There is invalid exif data parameter");
1989 context->status = status;
1990 return;
1991 }
1992 if (!IsSameTextStr(context->pathName, "")) {
1993 context->status = context->rImageSource->ModifyImageProperty(context->index,
1994 context->keyStr, context->valueStr, context->pathName);
1995 } else if (context->fdIndex != -1) {
1996 context->status = context->rImageSource->ModifyImageProperty(context->index,
1997 context->keyStr, context->valueStr, context->fdIndex);
1998 } else if (context->sourceBuffer != nullptr) {
1999 context->status = context->rImageSource->ModifyImageProperty(context->index,
2000 context->keyStr, context->valueStr, static_cast<uint8_t *>(context->sourceBuffer),
2001 context->sourceBufferSize);
2002 } else {
2003 context->status = ERROR;
2004 IMAGE_LOGE("There is no image source!");
2005 }
2006 }
2007
GetImagePropertiesExecute(napi_env env,void * data)2008 static void GetImagePropertiesExecute(napi_env env, void *data)
2009 {
2010 auto context = static_cast<ImageSourceAsyncContext*>(data);
2011 if (context == nullptr) {
2012 IMAGE_LOGE("empty context");
2013 return;
2014 }
2015 uint32_t status = SUCCESS;
2016 for (auto keyStrIt = context->keyStrArray.begin(); keyStrIt != context->keyStrArray.end(); ++keyStrIt) {
2017 std::string valueStr = "";
2018 status = context->rImageSource->GetImagePropertyString(0, *keyStrIt, valueStr);
2019 if (status == SUCCESS) {
2020 context->kVStrArray.emplace_back(std::make_pair(*keyStrIt, valueStr));
2021 } else {
2022 context->kVStrArray.emplace_back(std::make_pair(*keyStrIt, ""));
2023 context->errMsgArray.insert(std::make_pair(status, *keyStrIt));
2024 IMAGE_LOGE("errCode: %{public}u , exif key: %{public}s", status, keyStrIt->c_str());
2025 }
2026 }
2027 context->status = context->kVStrArray.size() == context->errMsgArray.size() ? ERROR : SUCCESS;
2028 }
2029
UnwrapContextForModify(napi_env env,napi_callback_info info)2030 static std::unique_ptr<ImageSourceAsyncContext> UnwrapContextForModify(napi_env env, napi_callback_info info)
2031 {
2032 int32_t refCount = 1;
2033 napi_status status;
2034 napi_value thisVar = nullptr;
2035 napi_value argValue[NUM_4] = {0};
2036 size_t argCount = NUM_4;
2037 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2038 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
2039 std::unique_ptr<ImageSourceAsyncContext> context = std::make_unique<ImageSourceAsyncContext>();
2040 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&context->constructor_));
2041 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_), nullptr, IMAGE_LOGE("fail to unwrap context"));
2042 context->rImageSource = context->constructor_->nativeImgSrc;
2043 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->rImageSource), nullptr, IMAGE_LOGE("empty native rImageSource"));
2044 if (argCount < NUM_1 || argCount > NUM_4) {
2045 IMAGE_LOGE("argCount mismatch");
2046 return nullptr;
2047 }
2048 if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_string) {
2049 context->keyStr = GetStringArgument(env, argValue[NUM_0]);
2050 } else if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_object) {
2051 context->kVStrArray = GetRecordArgument(env, argValue[NUM_0]);
2052 if (context->kVStrArray.size() == 0) {
2053 return nullptr;
2054 }
2055 context->isBatch = true;
2056 } else {
2057 IMAGE_LOGE("arg 0 type mismatch");
2058 return nullptr;
2059 }
2060 if (argCount == NUM_2 || argCount == NUM_3 || argCount == NUM_4) {
2061 if (ImageNapiUtils::getType(env, argValue[NUM_1]) == napi_string) {
2062 context->valueStr = GetStringArgument(env, argValue[NUM_1]);
2063 } else {
2064 IMAGE_LOGE("arg 1 type mismatch");
2065 return nullptr;
2066 }
2067 }
2068 if (argCount == NUM_3 || argCount == NUM_4) {
2069 if (ImageNapiUtils::getType(env, argValue[NUM_2]) == napi_object) {
2070 IMG_NAPI_CHECK_RET_D(ParsePropertyOptions(env, argValue[NUM_2], context.get()),
2071 nullptr, IMAGE_LOGE("PropertyOptions mismatch"));
2072 }
2073 if (ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
2074 napi_create_reference(env, argValue[argCount - 1], refCount, &context->callbackRef);
2075 }
2076 }
2077 context->pathName = ImageSourceNapi::filePath_;
2078 context->fdIndex = ImageSourceNapi::fileDescriptor_;
2079 context->sourceBuffer = ImageSourceNapi::fileBuffer_;
2080 context->sourceBufferSize = ImageSourceNapi::fileBufferSize_;
2081 return context;
2082 }
2083
ModifyImageProperty(napi_env env,napi_callback_info info)2084 napi_value ImageSourceNapi::ModifyImageProperty(napi_env env, napi_callback_info info)
2085 {
2086 napi_value result = nullptr;
2087 napi_get_undefined(env, &result);
2088
2089 napi_status status;
2090 std::unique_ptr<ImageSourceAsyncContext> asyncContext = UnwrapContextForModify(env, info);
2091 if (asyncContext == nullptr) {
2092 return ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "async context unwrap failed");
2093 }
2094
2095 if (asyncContext->callbackRef == nullptr) {
2096 napi_create_promise(env, &(asyncContext->deferred), &result);
2097 } else {
2098 napi_get_undefined(env, &result);
2099 }
2100 if (asyncContext->isBatch) {
2101 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ModifyImageProperties",
2102 ModifyImagePropertiesExecute,
2103 reinterpret_cast<napi_async_complete_callback>(ModifyImagePropertyComplete),
2104 asyncContext,
2105 asyncContext->work);
2106 } else {
2107 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "ModifyImageProperty",
2108 ModifyImagePropertyExecute,
2109 reinterpret_cast<napi_async_complete_callback>(ModifyImagePropertyComplete),
2110 asyncContext,
2111 asyncContext->work);
2112 }
2113
2114 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
2115 nullptr, IMAGE_LOGE("fail to create async work"));
2116 return result;
2117 }
2118
GetImageProperty(napi_env env,napi_callback_info info)2119 napi_value ImageSourceNapi::GetImageProperty(napi_env env, napi_callback_info info)
2120 {
2121 ImageTrace imageTrace("ImageSourceNapi::GetImageProperty");
2122 napi_value result = nullptr;
2123 napi_get_undefined(env, &result);
2124
2125 napi_status status;
2126 std::unique_ptr<ImageSourceAsyncContext> asyncContext = UnwrapContext(env, info);
2127 if (asyncContext == nullptr) {
2128 return ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "async context unwrap failed");
2129 }
2130
2131 if (asyncContext->callbackRef == nullptr) {
2132 napi_create_promise(env, &(asyncContext->deferred), &result);
2133 } else {
2134 napi_get_undefined(env, &result);
2135 }
2136
2137 if (asyncContext->isBatch) {
2138 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageProperties",
2139 GetImagePropertiesExecute,
2140 reinterpret_cast<napi_async_complete_callback>(GetImagePropertyComplete),
2141 asyncContext,
2142 asyncContext->work);
2143 } else {
2144 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetImageProperty",
2145 [](napi_env env, void *data) {
2146 auto context = static_cast<ImageSourceAsyncContext*>(data);
2147 context->status = context->rImageSource->GetImagePropertyString(context->index,
2148 context->keyStr,
2149 context->valueStr);
2150 },
2151 reinterpret_cast<napi_async_complete_callback>(GetImagePropertyComplete),
2152 asyncContext,
2153 asyncContext->work);
2154 }
2155
2156 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
2157 nullptr, IMAGE_LOGE("fail to create async work"));
2158 return result;
2159 }
2160
UpdateDataExecute(napi_env env,void * data)2161 static void UpdateDataExecute(napi_env env, void *data)
2162 {
2163 auto context = static_cast<ImageSourceAsyncContext*>(data);
2164 uint8_t *buffer = static_cast<uint8_t*>(context->updataBuffer);
2165 if (context->updataBufferOffset < context->updataBufferSize) {
2166 buffer = buffer + context->updataBufferOffset;
2167 }
2168
2169 uint32_t lastSize = context->updataBufferSize - context->updataBufferOffset;
2170 uint32_t size = context->updataLength < lastSize ? context->updataLength : lastSize;
2171
2172 uint32_t res = context->rImageSource->UpdateData(buffer, size,
2173 context->isCompleted);
2174 context->isSuccess = res == 0;
2175 if (context->isSuccess && context->constructor_ != nullptr) {
2176 auto incPixelMap = context->constructor_->GetIncrementalPixelMap();
2177 if (incPixelMap != nullptr) {
2178 uint8_t decodeProgress = 0;
2179 uint32_t err = incPixelMap->PromoteDecoding(decodeProgress);
2180 if (!(err == SUCCESS || (err == ERR_IMAGE_SOURCE_DATA_INCOMPLETE && !context->isCompleted))) {
2181 IMAGE_LOGE("UpdateData PromoteDecoding error");
2182 context->isSuccess = false;
2183 }
2184 if (context->isCompleted) {
2185 incPixelMap->DetachFromDecoding();
2186 }
2187 }
2188 }
2189 }
2190
UpdateDataComplete(napi_env env,napi_status status,void * data)2191 static void UpdateDataComplete(napi_env env, napi_status status, void *data)
2192 {
2193 napi_value result = nullptr;
2194 napi_create_object(env, &result);
2195
2196 auto context = static_cast<ImageSourceAsyncContext*>(data);
2197
2198 napi_get_boolean(env, context->isSuccess, &result);
2199 ImageSourceCallbackRoutine(env, context, result);
2200 }
2201
isNapiTypedArray(napi_env env,napi_value val)2202 static bool isNapiTypedArray(napi_env env, napi_value val)
2203 {
2204 bool res = false;
2205 napi_is_typedarray(env, val, &res);
2206 IMAGE_LOGD("isNapiTypedArray %{public}d", res);
2207 return res;
2208 }
2209
UpdateData(napi_env env,napi_callback_info info)2210 napi_value ImageSourceNapi::UpdateData(napi_env env, napi_callback_info info)
2211 {
2212 napi_value result = nullptr;
2213 napi_get_undefined(env, &result);
2214
2215 int32_t refCount = 1;
2216 napi_status status;
2217 napi_value thisVar = nullptr;
2218 napi_value argValue[NUM_5] = {0};
2219 size_t argCount = 5;
2220 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2221 IMAGE_LOGD("UpdateData argCount is [%{public}zu]", argCount);
2222
2223 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
2224
2225 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
2226 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
2227
2228 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_),
2229 nullptr, IMAGE_LOGE("fail to unwrap context"));
2230
2231 asyncContext->rImageSource = asyncContext->constructor_->nativeImgSrc;
2232
2233 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rImageSource),
2234 nullptr, IMAGE_LOGE("empty native rImageSource"));
2235 IMAGE_LOGD("UpdateData argCount %{public}zu", argCount);
2236 if (argCount > NUM_0 && isNapiTypedArray(env, argValue[NUM_0])) {
2237 IMAGE_LOGI("UpdateData napi_get_arraybuffer_info ");
2238 napi_typedarray_type type;
2239 napi_value arraybuffer;
2240 size_t offset;
2241 status = napi_get_typedarray_info(env, argValue[NUM_0], &type,
2242 &(asyncContext->updataBufferSize), &(asyncContext->updataBuffer),
2243 &arraybuffer, &offset);
2244 }
2245
2246 if (argCount >= NUM_2 && ImageNapiUtils::getType(env, argValue[NUM_1]) == napi_boolean) {
2247 status = napi_get_value_bool(env, argValue[NUM_1], &(asyncContext->isCompleted));
2248 }
2249
2250 if (argCount >= NUM_3 && ImageNapiUtils::getType(env, argValue[NUM_2]) == napi_number) {
2251 asyncContext->updataBufferOffset = 0;
2252 status = napi_get_value_uint32(env, argValue[NUM_2], &(asyncContext->updataBufferOffset));
2253 IMAGE_LOGD("asyncContext->updataBufferOffset is [%{public}u]", asyncContext->updataBufferOffset);
2254 }
2255
2256 if (argCount >= NUM_4 && ImageNapiUtils::getType(env, argValue[NUM_3]) == napi_number) {
2257 asyncContext->updataLength = 0;
2258 status = napi_get_value_uint32(env, argValue[NUM_3], &(asyncContext->updataLength));
2259 IMAGE_LOGD("asyncContext->updataLength is [%{public}u]", asyncContext->updataLength);
2260 }
2261
2262 if (!IMG_IS_OK(status)) {
2263 IMAGE_LOGE("fail to UpdateData");
2264 napi_get_undefined(env, &result);
2265 return result;
2266 }
2267
2268 if (argCount == NUM_5 && ImageNapiUtils::getType(env, argValue[NUM_4]) == napi_function) {
2269 napi_create_reference(env, argValue[NUM_4], refCount, &asyncContext->callbackRef);
2270 }
2271
2272 if (argCount == NUM_3 && ImageNapiUtils::getType(env, argValue[NUM_2]) == napi_function) {
2273 napi_create_reference(env, argValue[NUM_2], refCount, &asyncContext->callbackRef);
2274 }
2275
2276 if (asyncContext->callbackRef == nullptr) {
2277 napi_create_promise(env, &(asyncContext->deferred), &result);
2278 } else {
2279 napi_get_undefined(env, &result);
2280 }
2281
2282 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "UpdateData",
2283 UpdateDataExecute, UpdateDataComplete, asyncContext, asyncContext->work);
2284
2285 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
2286 nullptr, IMAGE_LOGE("fail to create async work"));
2287 return result;
2288 }
2289
ReleaseComplete(napi_env env,napi_status status,void * data)2290 static void ReleaseComplete(napi_env env, napi_status status, void *data)
2291 {
2292 napi_value result = nullptr;
2293 napi_get_undefined(env, &result);
2294
2295 auto context = static_cast<ImageSourceAsyncContext*>(data);
2296 delete context->constructor_;
2297 context->constructor_ = nullptr;
2298 ImageSourceCallbackRoutine(env, context, result);
2299 }
2300
Release(napi_env env,napi_callback_info info)2301 napi_value ImageSourceNapi::Release(napi_env env, napi_callback_info info)
2302 {
2303 IMAGE_LOGD("Release enter");
2304 napi_value result = nullptr;
2305 napi_get_undefined(env, &result);
2306
2307 int32_t refCount = 1;
2308 napi_status status;
2309 napi_value thisVar = nullptr;
2310 napi_value argValue[NUM_1] = {0};
2311 size_t argCount = 1;
2312
2313 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2314 IMAGE_LOGD("Release argCount is [%{public}zu]", argCount);
2315 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), result, IMAGE_LOGE("fail to napi_get_cb_info"));
2316
2317 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
2318 status = napi_remove_wrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
2319
2320 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_), result,
2321 IMAGE_LOGE("fail to unwrap context"));
2322
2323 IMAGE_LOGD("Release argCount is [%{public}zu]", argCount);
2324 if (argCount == 1 && ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_function) {
2325 napi_create_reference(env, argValue[NUM_0], refCount, &asyncContext->callbackRef);
2326 }
2327
2328 if (asyncContext->callbackRef == nullptr) {
2329 napi_create_promise(env, &(asyncContext->deferred), &result);
2330 }
2331
2332 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "Release",
2333 [](napi_env env, void *data) {}, ReleaseComplete, asyncContext, asyncContext->work);
2334 IMAGE_LOGD("Release exit");
2335 return result;
2336 }
2337
release()2338 void ImageSourceNapi::release()
2339 {
2340 if (!isRelease) {
2341 if (nativeImgSrc != nullptr) {
2342 nativeImgSrc = nullptr;
2343 }
2344 isRelease = true;
2345 }
2346 }
2347
UnwrapContextForList(napi_env env,napi_callback_info info)2348 static std::unique_ptr<ImageSourceAsyncContext> UnwrapContextForList(napi_env env, napi_callback_info info)
2349 {
2350 int32_t refCount = 1;
2351 napi_status status;
2352 napi_value thisVar = nullptr;
2353 napi_value argValue[NUM_3] = {0};
2354 size_t argCount = NUM_3;
2355
2356 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2357 IMAGE_LOGD("UnwrapContextForList argCount is [%{public}zu]", argCount);
2358
2359 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
2360
2361 std::unique_ptr<ImageSourceAsyncContext> context = std::make_unique<ImageSourceAsyncContext>();
2362 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&context->constructor_));
2363
2364 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->constructor_),
2365 nullptr, IMAGE_LOGE("fail to unwrap context"));
2366
2367 context->rImageSource = context->constructor_->nativeImgSrc;
2368
2369 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, context->rImageSource),
2370 nullptr, IMAGE_LOGE("empty native rImageSource"));
2371
2372 if (argCount > NUM_2) {
2373 IMAGE_LOGE("argCount mismatch");
2374 return nullptr;
2375 }
2376
2377 if (argCount > NUM_0) {
2378 if (ImageNapiUtils::getType(env, argValue[NUM_0]) == napi_object) {
2379 IMAGE_LOGD("UnwrapContextForList object");
2380 if (!ParseDecodeOptions(env, argValue[NUM_0], &(context->decodeOpts),
2381 &(context->index), context->errMsg)) {
2382 IMAGE_LOGE("DecodeOptions mismatch");
2383 }
2384 }
2385
2386 if (ImageNapiUtils::getType(env, argValue[argCount - 1]) == napi_function) {
2387 IMAGE_LOGD("UnwrapContextForList function");
2388 napi_create_reference(env, argValue[argCount - 1], refCount, &context->callbackRef);
2389 }
2390 }
2391
2392 return context;
2393 }
2394
CheckAsyncContext(ImageSourceAsyncContext * context,bool check)2395 static ImageSourceAsyncContext* CheckAsyncContext(ImageSourceAsyncContext* context, bool check)
2396 {
2397 if (context == nullptr) {
2398 IMAGE_LOGE("context is nullptr");
2399 return nullptr;
2400 }
2401
2402 if (check) {
2403 if (context->errMsg.size() > 0) {
2404 IMAGE_LOGE("mismatch args");
2405 context->status = ERROR;
2406 return nullptr;
2407 }
2408
2409 if (context->rImageSource == nullptr) {
2410 IMAGE_LOGE("empty context rImageSource");
2411 context->status = ERROR;
2412 return nullptr;
2413 }
2414 }
2415
2416 return context;
2417 }
2418
STATIC_EXEC_FUNC(CreatePixelMapList)2419 STATIC_EXEC_FUNC(CreatePixelMapList)
2420 {
2421 if (data == nullptr) {
2422 IMAGE_LOGE("data is nullptr");
2423 return;
2424 }
2425
2426 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), true);
2427 if (context == nullptr) {
2428 IMAGE_LOGE("check async context fail");
2429 return;
2430 }
2431
2432 context->pixelMaps = nullptr;
2433 uint32_t errorCode = 0;
2434 uint32_t frameCount = context->rImageSource->GetFrameCount(errorCode);
2435 if ((errorCode == SUCCESS) && (context->index >= NUM_0) && (context->index < frameCount)) {
2436 context->decodeOpts.invokeType = JS_INTERFACE;
2437 context->pixelMaps = context->rImageSource->CreatePixelMapList(context->decodeOpts, errorCode);
2438 }
2439 if ((errorCode == SUCCESS) && IMG_NOT_NULL(context->pixelMaps)) {
2440 context->status = SUCCESS;
2441 } else {
2442 IMAGE_LOGE("Create PixelMap List error, error=%{public}u", errorCode);
2443 context->errMsg = "Create PixelMap List error";
2444 context->status = (errorCode != SUCCESS) ? errorCode : ERROR;
2445 }
2446 }
2447
STATIC_COMPLETE_FUNC(CreatePixelMapList)2448 STATIC_COMPLETE_FUNC(CreatePixelMapList)
2449 {
2450 if (data == nullptr) {
2451 IMAGE_LOGE("data is nullptr");
2452 return;
2453 }
2454
2455 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), false);
2456 if (context == nullptr) {
2457 IMAGE_LOGE("check async context fail");
2458 return;
2459 }
2460
2461 napi_value result = nullptr;
2462 if ((context->status == SUCCESS) && IMG_NOT_NULL(context->pixelMaps)) {
2463 IMAGE_LOGD("CreatePixelMapListComplete array");
2464 napi_create_array(env, &result);
2465 size_t i = 0;
2466 for (auto &pixelMap : *context->pixelMaps.get()) {
2467 auto napiPixelMap = PixelMapNapi::CreatePixelMap(env, std::move(pixelMap));
2468 napi_set_element(env, result, i, napiPixelMap);
2469 i++;
2470 }
2471 } else {
2472 IMAGE_LOGD("CreatePixelMapListComplete undefined");
2473 napi_get_undefined(env, &result);
2474 }
2475
2476 IMAGE_LOGD("CreatePixelMapListComplete set to nullptr");
2477 context->pixelMaps = nullptr;
2478
2479 ImageSourceCallbackWithErrorObj(env, context, result);
2480 }
2481
CreatePixelMapList(napi_env env,napi_callback_info info)2482 napi_value ImageSourceNapi::CreatePixelMapList(napi_env env, napi_callback_info info)
2483 {
2484 ImageTrace imageTrace("ImageSourceNapi::CreatePixelMapList");
2485
2486 auto asyncContext = UnwrapContextForList(env, info);
2487 if (asyncContext == nullptr) {
2488 return ImageNapiUtils::ThrowExceptionError(env, ERR_IMAGE_DATA_ABNORMAL,
2489 "async context unwrap failed");
2490 }
2491
2492 napi_value result = nullptr;
2493 napi_get_undefined(env, &result);
2494 if (asyncContext->callbackRef == nullptr) {
2495 napi_create_promise(env, &(asyncContext->deferred), &result);
2496 } else {
2497 napi_get_undefined(env, &result);
2498 }
2499
2500 ImageNapiUtils::HicheckerReport();
2501
2502 napi_status status;
2503 IMG_CREATE_CREATE_ASYNC_WORK_WITH_QOS(env, status, "CreatePixelMapList", CreatePixelMapListExec,
2504 CreatePixelMapListComplete, asyncContext, asyncContext->work, napi_qos_user_initiated);
2505 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to create async work"));
2506
2507 return result;
2508 }
2509
STATIC_EXEC_FUNC(GetDelayTime)2510 STATIC_EXEC_FUNC(GetDelayTime)
2511 {
2512 if (data == nullptr) {
2513 IMAGE_LOGE("data is nullptr");
2514 return;
2515 }
2516
2517 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), true);
2518 if (context == nullptr) {
2519 IMAGE_LOGE("check async context fail");
2520 return;
2521 }
2522
2523 uint32_t errorCode = 0;
2524 context->delayTimes = context->rImageSource->GetDelayTime(errorCode);
2525 if ((errorCode == SUCCESS) && IMG_NOT_NULL(context->delayTimes)) {
2526 context->status = SUCCESS;
2527 } else {
2528 IMAGE_LOGE("Get DelayTime error, error=%{public}u", errorCode);
2529 context->errMsg = "Get DelayTime error";
2530 context->status = (errorCode != SUCCESS) ? errorCode : ERROR;
2531 }
2532 }
2533
STATIC_COMPLETE_FUNC(GetDelayTime)2534 STATIC_COMPLETE_FUNC(GetDelayTime)
2535 {
2536 if (data == nullptr) {
2537 IMAGE_LOGE("data is nullptr");
2538 return;
2539 }
2540
2541 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), false);
2542 if (context == nullptr) {
2543 IMAGE_LOGE("check async context fail");
2544 return;
2545 }
2546
2547 napi_value result = nullptr;
2548 if (context->status == SUCCESS && IMG_NOT_NULL(context->delayTimes)) {
2549 IMAGE_LOGD("GetDelayTimeComplete array");
2550 napi_create_array(env, &result);
2551 size_t i = 0;
2552 for (auto delayTime : *context->delayTimes) {
2553 napi_value napiDelayTime = nullptr;
2554 napi_create_uint32(env, delayTime, &napiDelayTime);
2555 napi_set_element(env, result, i, napiDelayTime);
2556 i++;
2557 }
2558 } else {
2559 IMAGE_LOGD("GetDelayTimeComplete undefined");
2560 napi_get_undefined(env, &result);
2561 }
2562
2563 IMAGE_LOGD("GetDelayTimeComplete set to nullptr");
2564 context->delayTimes = nullptr;
2565 ImageSourceCallbackWithErrorObj(env, context, result);
2566 }
2567
GetDelayTime(napi_env env,napi_callback_info info)2568 napi_value ImageSourceNapi::GetDelayTime(napi_env env, napi_callback_info info)
2569 {
2570 ImageTrace imageTrace("ImageSourceNapi::GetDelayTime");
2571
2572 auto asyncContext = UnwrapContextForList(env, info);
2573 if (asyncContext == nullptr) {
2574 return ImageNapiUtils::ThrowExceptionError(env, ERR_IMAGE_DATA_ABNORMAL,
2575 "async context unwrap failed");
2576 }
2577
2578 napi_value result = nullptr;
2579 napi_get_undefined(env, &result);
2580 if (asyncContext->callbackRef == nullptr) {
2581 napi_create_promise(env, &(asyncContext->deferred), &result);
2582 } else {
2583 napi_get_undefined(env, &result);
2584 }
2585
2586 napi_status status;
2587 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetDelayTime", GetDelayTimeExec,
2588 GetDelayTimeComplete, asyncContext, asyncContext->work);
2589 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to create async work"));
2590
2591 return result;
2592 }
2593
STATIC_EXEC_FUNC(GetDisposalType)2594 STATIC_EXEC_FUNC(GetDisposalType)
2595 {
2596 if (data == nullptr) {
2597 IMAGE_LOGE("data is nullptr");
2598 return;
2599 }
2600
2601 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), true);
2602 if (context == nullptr) {
2603 IMAGE_LOGE("check async context fail");
2604 return;
2605 }
2606
2607 uint32_t errorCode = 0;
2608 context->disposalType = context->rImageSource->GetDisposalType(errorCode);
2609 if ((errorCode == SUCCESS) && IMG_NOT_NULL(context->disposalType)) {
2610 context->status = SUCCESS;
2611 } else {
2612 IMAGE_LOGE("Get DisposalType error, error=%{public}u", errorCode);
2613 context->errMsg = "Get DisposalType error";
2614 context->status = (errorCode != SUCCESS) ? errorCode : ERROR;
2615 }
2616 }
2617
STATIC_COMPLETE_FUNC(GetDisposalType)2618 STATIC_COMPLETE_FUNC(GetDisposalType)
2619 {
2620 if (data == nullptr) {
2621 IMAGE_LOGE("data is nullptr");
2622 return;
2623 }
2624
2625 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), false);
2626 if (context == nullptr) {
2627 IMAGE_LOGE("check async context fail");
2628 return;
2629 }
2630
2631 napi_value result = nullptr;
2632 if (context->status == SUCCESS && IMG_NOT_NULL(context->disposalType)) {
2633 IMAGE_LOGD("GetDisposalTypeComplete array");
2634 napi_create_array(env, &result);
2635 size_t i = 0;
2636 for (auto disposalType : *context->disposalType) {
2637 napi_value napiDisposalType = nullptr;
2638 napi_create_uint32(env, disposalType, &napiDisposalType);
2639 napi_set_element(env, result, i, napiDisposalType);
2640 i++;
2641 }
2642 } else {
2643 IMAGE_LOGD("GetDisposalTypeComplete undefined");
2644 napi_get_undefined(env, &result);
2645 }
2646
2647 IMAGE_LOGD("GetDisposalTypeComplete set to nullptr");
2648 context->disposalType = nullptr;
2649 ImageSourceCallbackWithErrorObj(env, context, result);
2650 }
2651
GetDisposalType(napi_env env,napi_callback_info info)2652 napi_value ImageSourceNapi::GetDisposalType(napi_env env, napi_callback_info info)
2653 {
2654 ImageTrace imageTrace("ImageSourceNapi::GetDisposalType");
2655
2656 auto asyncContext = UnwrapContextForList(env, info);
2657 if (asyncContext == nullptr) {
2658 return ImageNapiUtils::ThrowExceptionError(env, ERR_IMAGE_DATA_ABNORMAL,
2659 "async context unwrap failed");
2660 }
2661
2662 napi_value result = nullptr;
2663 napi_get_undefined(env, &result);
2664 if (asyncContext->callbackRef == nullptr) {
2665 napi_create_promise(env, &(asyncContext->deferred), &result);
2666 } else {
2667 napi_get_undefined(env, &result);
2668 }
2669
2670 napi_status status;
2671 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetDisposalType", GetDisposalTypeExec,
2672 GetDisposalTypeComplete, asyncContext, asyncContext->work);
2673 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to create async work"));
2674
2675 return result;
2676 }
2677
STATIC_EXEC_FUNC(GetFrameCount)2678 STATIC_EXEC_FUNC(GetFrameCount)
2679 {
2680 if (data == nullptr) {
2681 IMAGE_LOGE("data is nullptr");
2682 return;
2683 }
2684
2685 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), true);
2686 if (context == nullptr) {
2687 IMAGE_LOGE("check async context fail");
2688 return;
2689 }
2690
2691 uint32_t errorCode = 0;
2692 context->frameCount = context->rImageSource->GetFrameCount(errorCode);
2693 IMAGE_LOGD("GetFrameCountExec count=%{public}u, error=%{public}u", context->frameCount, errorCode);
2694 if (errorCode == SUCCESS) {
2695 context->status = SUCCESS;
2696 } else {
2697 IMAGE_LOGE("Get FrameCount error, error=%{public}u", errorCode);
2698 context->errMsg = "Get FrameCount error";
2699 context->status = errorCode;
2700 }
2701 }
2702
STATIC_COMPLETE_FUNC(GetFrameCount)2703 STATIC_COMPLETE_FUNC(GetFrameCount)
2704 {
2705 if (data == nullptr) {
2706 IMAGE_LOGE("data is nullptr");
2707 return;
2708 }
2709
2710 auto context = CheckAsyncContext(static_cast<ImageSourceAsyncContext*>(data), false);
2711 if (context == nullptr) {
2712 IMAGE_LOGE("check async context fail");
2713 return;
2714 }
2715
2716 napi_value result = nullptr;
2717 if (context->status == SUCCESS) {
2718 IMAGE_LOGD("GetFrameCountComplete uint");
2719 napi_create_uint32(env, context->frameCount, &result);
2720 } else {
2721 IMAGE_LOGD("GetFrameCountComplete undefined");
2722 napi_get_undefined(env, &result);
2723 }
2724
2725 context->frameCount = 0;
2726 ImageSourceCallbackWithErrorObj(env, context, result);
2727 }
2728
GetFrameCount(napi_env env,napi_callback_info info)2729 napi_value ImageSourceNapi::GetFrameCount(napi_env env, napi_callback_info info)
2730 {
2731 ImageTrace imageTrace("ImageSourceNapi::GetFrameCount");
2732
2733 auto asyncContext = UnwrapContextForList(env, info);
2734 if (asyncContext == nullptr) {
2735 return ImageNapiUtils::ThrowExceptionError(env, ERR_IMAGE_DATA_ABNORMAL,
2736 "async context unwrap failed");
2737 }
2738
2739 napi_value result = nullptr;
2740 napi_get_undefined(env, &result);
2741 if (asyncContext->callbackRef == nullptr) {
2742 napi_create_promise(env, &(asyncContext->deferred), &result);
2743 } else {
2744 napi_get_undefined(env, &result);
2745 }
2746
2747 napi_status status;
2748 IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetFrameCount", GetFrameCountExec,
2749 GetFrameCountComplete, asyncContext, asyncContext->work);
2750 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to create async work"));
2751
2752 return result;
2753 }
2754
CreateImageSourceNapi(napi_env env,napi_value * result)2755 int32_t ImageSourceNapi::CreateImageSourceNapi(napi_env env, napi_value* result)
2756 {
2757 napi_value constructor = nullptr;
2758 napi_status status = napi_ok;
2759 PrepareNapiEnv(env);
2760
2761 status = napi_get_reference_value(env, sConstructor_, &constructor);
2762 if (status == napi_ok && constructor != nullptr) {
2763 status = napi_new_instance(env, constructor, NUM_0, nullptr, result);
2764 }
2765
2766 if (status != napi_ok || result == nullptr) {
2767 IMAGE_LOGE("CreateImageSourceNapi new instance failed");
2768 napi_get_undefined(env, result);
2769 return ERR_IMAGE_DATA_ABNORMAL;
2770 }
2771 return SUCCESS;
2772 }
2773
SetIncrementalPixelMap(std::shared_ptr<IncrementalPixelMap> incrementalPixelMap)2774 void ImageSourceNapi::SetIncrementalPixelMap(std::shared_ptr<IncrementalPixelMap> incrementalPixelMap)
2775 {
2776 navIncPixelMap_ = incrementalPixelMap;
2777 }
2778
SetNativeImageSource(std::shared_ptr<ImageSource> imageSource)2779 void ImageSourceNapi::SetNativeImageSource(std::shared_ptr<ImageSource> imageSource)
2780 {
2781 nativeImgSrc = imageSource;
2782 }
2783
SetImageResource(ImageResource resource)2784 void ImageSourceNapi::SetImageResource(ImageResource resource)
2785 {
2786 resource_.type = resource.type;
2787 resource_.fd = resource.fd;
2788 resource_.path = resource.path;
2789 resource_.buffer = resource.buffer;
2790 resource_.bufferSize = resource.bufferSize;
2791 }
2792
GetImageResource()2793 ImageResource ImageSourceNapi::GetImageResource()
2794 {
2795 return resource_;
2796 }
2797
2798 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
CreatePictureExecute(napi_env env,void * data)2799 static void CreatePictureExecute(napi_env env, void *data)
2800 {
2801 IMAGE_LOGD("CreatePictureExecute IN");
2802 if (data == nullptr) {
2803 IMAGE_LOGE("data is nullptr");
2804 return;
2805 }
2806 auto context = static_cast<ImageSourceAsyncContext*>(data);
2807 if (context == nullptr) {
2808 IMAGE_LOGE("empty context");
2809 return;
2810 }
2811
2812 if (context->errMsg.size() > 0) {
2813 IMAGE_LOGE("mismatch args");
2814 context->status = ERROR;
2815 return;
2816 }
2817
2818 uint32_t errorCode;
2819 context->rPicture = context->rImageSource->CreatePicture(context->decodingOptsForPicture, errorCode);
2820 if (context->rPicture != nullptr) {
2821 context->status = SUCCESS;
2822 } else {
2823 context->status = ERROR;
2824 }
2825
2826 IMAGE_LOGD("CreatePictureExecute OUT");
2827 }
2828
CreatePictureComplete(napi_env env,napi_status status,void * data)2829 static void CreatePictureComplete(napi_env env, napi_status status, void *data)
2830 {
2831 IMAGE_LOGD("CreatePictureComplete IN");
2832 napi_value result = nullptr;
2833 auto context = static_cast<ImageSourceAsyncContext*>(data);
2834
2835 if (context->status == SUCCESS) {
2836 result = PictureNapi::CreatePicture(env, context->rPicture);
2837 } else {
2838 std::pair<int32_t, std::string> errorMsg(static_cast<int32_t>(IMAGE_DECODE_FAILED), "Create Picture error");
2839 context->errMsgArray.insert(errorMsg);
2840 napi_get_undefined(env, &result);
2841 }
2842 IMAGE_LOGD("CreatePictureComplete OUT");
2843 ImageSourceCallbackRoutine(env, context, result);
2844 }
2845
ParseDecodingOptionsForPicture(napi_env env,napi_value root,DecodingOptionsForPicture * opts)2846 static bool ParseDecodingOptionsForPicture(napi_env env, napi_value root, DecodingOptionsForPicture* opts)
2847 {
2848 napi_value tmpValue = nullptr;
2849 if (napi_get_named_property(env, root, "desiredAuxiliaryPictures", &tmpValue) != napi_ok) {
2850 IMAGE_LOGE("fail to named property desiredAuxiliaryPictures");
2851 return false;
2852 }
2853
2854 uint32_t arrayLen = 0;
2855 napi_status status = napi_get_array_length(env, tmpValue, &arrayLen);
2856 if (status != napi_ok) {
2857 IMAGE_LOGE("Get array length failed: %{public}d", status);
2858 return false;
2859 }
2860
2861 napi_value element;
2862 uint32_t type;
2863 for (uint32_t i = 0; i < arrayLen; i++) {
2864 if (napi_get_element(env, tmpValue, i, &element) != napi_ok) {
2865 IMAGE_LOGE("get array element failed");
2866 return false;
2867 }
2868 if (napi_get_value_uint32(env, element, &type) != napi_ok) {
2869 IMAGE_LOGE("get type from element failed");
2870 return false;
2871 }
2872 if (type <= static_cast<uint32_t>(AuxiliaryPictureType::FRAGMENT_MAP)) {
2873 opts->desireAuxiliaryPictures.insert(AuxiliaryPictureType(type));
2874 IMAGE_LOGD("desireAuxiliaryPictures[%{public}d]: %{public}d", i, type);
2875 } else {
2876 IMAGE_LOGE("unknown auxiliary picture type");
2877 return false;
2878 }
2879 }
2880 return true;
2881 }
2882
CreatePicture(napi_env env,napi_callback_info info)2883 napi_value ImageSourceNapi::CreatePicture(napi_env env, napi_callback_info info)
2884 {
2885 napi_value result = nullptr;
2886 napi_get_undefined(env, &result);
2887
2888 napi_status status;
2889 napi_value thisVar = nullptr;
2890 napi_value argValue[NUM_1] = {0};
2891 size_t argCount = NUM_1;
2892 IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar);
2893 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, thisVar), nullptr, IMAGE_LOGE("fail to get thisVar"));
2894 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("fail to napi_get_cb_info"));
2895
2896 std::unique_ptr<ImageSourceAsyncContext> asyncContext = std::make_unique<ImageSourceAsyncContext>();
2897
2898 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->constructor_));
2899 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_),
2900 nullptr, IMAGE_LOGE("fail to unwrap context"));
2901 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->constructor_->nativeImgSrc),
2902 nullptr, IMAGE_LOGE("fail to unwrap nativeImgSrc"));
2903 asyncContext->rImageSource = asyncContext->constructor_->nativeImgSrc;
2904 IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rImageSource),
2905 nullptr, IMAGE_LOGE("empty native rImageSource"));
2906
2907 if (argCount == NUM_0) {
2908 for (int32_t type = static_cast<int32_t>(AuxiliaryPictureType::GAINMAP);
2909 type <= static_cast<int32_t>(AuxiliaryPictureType::FRAGMENT_MAP); type++) {
2910 asyncContext->decodingOptsForPicture.desireAuxiliaryPictures.insert(AuxiliaryPictureType(type));
2911 }
2912 } else if (argCount == NUM_1) {
2913 if (!ParseDecodingOptionsForPicture(env, argValue[NUM_0], &(asyncContext->decodingOptsForPicture))) {
2914 return ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER,
2915 "DecodingOptionsForPicture mismatch");
2916 }
2917 }
2918
2919 napi_create_promise(env, &(asyncContext->deferred), &result);
2920
2921 ImageNapiUtils::HicheckerReport();
2922 IMG_CREATE_CREATE_ASYNC_WORK_WITH_QOS(env, status, "CreatePicture", CreatePictureExecute,
2923 CreatePictureComplete, asyncContext, asyncContext->work, napi_qos_user_initiated);
2924
2925 IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status),
2926 nullptr, IMAGE_LOGE("fail to create async work"));
2927 return result;
2928 }
2929 #endif
2930
2931 } // namespace Media
2932 } // namespace OHOS
2933