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