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