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