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