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