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