• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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