• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 "ani_color_space_object_convertor.h"
17 #include "image_common.h"
18 #include "image_dfx.h"
19 #include "image_log.h"
20 #include "image_source_taihe.h"
21 #include "image_taihe_utils.h"
22 #include "image_trace.h"
23 #include "image_type.h"
24 #include "jpeg_decoder_yuv.h"
25 #include "media_errors.h"
26 #include "pixel_map_taihe.h"
27 #include "exif_metadata_formatter.h"
28 
29 using namespace ANI::Image;
30 using JpegYuvDecodeError = OHOS::ImagePlugin::JpegYuvDecodeError;
31 
32 namespace {
33     constexpr int INVALID_FD = -1;
34     constexpr uint32_t NUM_0 = 0;
35 }
36 
37 namespace ANI::Image {
38 static const std::string FILE_URL_PREFIX = "file://";
39 thread_local std::string ImageSourceImpl::filePath_ = "";
40 thread_local int ImageSourceImpl::fileDescriptor_ = -1;
41 thread_local void* ImageSourceImpl::fileBuffer_ = nullptr;
42 thread_local size_t ImageSourceImpl::fileBufferSize_ = 0;
43 
44 static std::mutex imageSourceCrossThreadMutex_;
45 
46 struct ImageSourceTaiheContext {
47     ImageSourceImpl *thisPtr;
48     uint32_t status;
49     std::string pathName = "";
50     int fdIndex = INVALID_FD;
51     void* sourceBuffer = nullptr;
52     size_t sourceBufferSize = NUM_0;
53     std::string keyStr;
54     std::string valueStr;
55     std::vector<std::string> keyStrArray;
56     std::vector<std::pair<std::string, std::string>> kVStrArray;
57     std::string defaultValueStr;
58     uint32_t index = 0;
59     bool isBatch = false;
60     OHOS::Media::DecodeOptions decodeOpts;
61     std::shared_ptr<OHOS::Media::ImageSource> rImageSource;
62     std::shared_ptr<OHOS::Media::PixelMap> rPixelMap;
63     std::string errMsg;
64     std::multimap<std::int32_t, std::string> errMsgArray;
65     std::unique_ptr<std::vector<std::unique_ptr<OHOS::Media::PixelMap>>> pixelMaps;
66     std::unique_ptr<std::vector<int32_t>> delayTimes;
67 };
68 
69 static const std::map<int32_t, Image_ErrorCode> ERROR_CODE_MAP = {
70     {OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, Image_ErrorCode::IMAGE_BAD_PARAMETER},
71     {OHOS::Media::COMMON_ERR_INVALID_PARAMETER, Image_ErrorCode::IMAGE_BAD_PARAMETER},
72     {JpegYuvDecodeError::JpegYuvDecodeError_InvalidParameter, Image_ErrorCode::IMAGE_BAD_PARAMETER},
73     {OHOS::Media::ERR_IMAGE_SOURCE_DATA, Image_ErrorCode::IMAGE_BAD_SOURCE},
74     {OHOS::Media::ERR_IMAGE_SOURCE_DATA_INCOMPLETE, Image_ErrorCode::IMAGE_BAD_SOURCE},
75     {OHOS::Media::ERR_IMAGE_GET_DATA_ABNORMAL, Image_ErrorCode::IMAGE_BAD_SOURCE},
76     {OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, Image_ErrorCode::IMAGE_BAD_SOURCE},
77     {OHOS::Media::ERROR, Image_ErrorCode::IMAGE_BAD_SOURCE},
78     {JpegYuvDecodeError::JpegYuvDecodeError_BadImage, Image_ErrorCode::IMAGE_BAD_SOURCE},
79     {OHOS::Media::ERR_IMAGE_MISMATCHED_FORMAT, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_MIMETYPE},
80     {OHOS::Media::ERR_IMAGE_UNKNOWN_FORMAT, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_MIMETYPE},
81     {OHOS::Media::ERR_IMAGE_DECODE_HEAD_ABNORMAL, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_MIMETYPE},
82     {OHOS::Media::ERR_IMAGE_TOO_LARGE, Image_ErrorCode::IMAGE_SOURCE_TOO_LARGE},
83     {OHOS::Media::ERR_MEDIA_INVALID_OPERATION, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_ALLOCATOR_TYPE},
84     {OHOS::Media::IMAGE_RESULT_FORMAT_CONVERT_FAILED, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS},
85     {OHOS::Media::ERR_MEDIA_FORMAT_UNSUPPORT, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS},
86     {OHOS::Media::ERR_IMAGE_PIXELMAP_CREATE_FAILED, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS},
87     {JpegYuvDecodeError::JpegYuvDecodeError_ConvertError, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS},
88     {OHOS::Media::ERR_IMAGE_CROP, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS},
89     {OHOS::Media::ERR_IMAGE_DECODE_FAILED, Image_ErrorCode::IMAGE_DECODE_FAILED},
90     {OHOS::Media::ERR_IMAGE_DECODE_ABNORMAL, Image_ErrorCode::IMAGE_DECODE_FAILED},
91     {OHOS::Media::ERR_IMAGE_PLUGIN_CREATE_FAILED, Image_ErrorCode::IMAGE_DECODE_FAILED},
92     {JpegYuvDecodeError::JpegYuvDecodeError_DecodeFailed, Image_ErrorCode::IMAGE_DECODE_FAILED},
93     {JpegYuvDecodeError::JpegYuvDecodeError_MemoryNotEnoughToSaveResult, Image_ErrorCode::IMAGE_DECODE_FAILED},
94     {OHOS::Media::ERR_IMAGE_MALLOC_ABNORMAL, Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED},
95     {OHOS::Media::ERR_IMAGE_DATA_UNSUPPORT, Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED},
96     {OHOS::Media::ERR_DMA_NOT_EXIST, Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED},
97     {OHOS::Media::ERR_DMA_DATA_ABNORMAL, Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED},
98     {OHOS::Media::ERR_SHAMEM_DATA_ABNORMAL, Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED}
99 };
100 
101 static const std::map<Image_ErrorCode, std::string> ERROR_CODE_MESSAGE_MAP = {
102     {Image_ErrorCode::IMAGE_BAD_PARAMETER, "Parameter error. Possible causes:"
103         "1.Mandatory parameters are left unspecified. 2.Incorrect parameter types. 3.Parameter verification failed."},
104     {Image_ErrorCode::IMAGE_BAD_SOURCE, "Bad source. e.g.,1.Image has invalid width or height."
105         "2.Image source incomplete. 3.Read image data failed. 4. Codec create failed."
106         "5.The sourceOption specifies an odd width, causing the YUV420 PixelMap conversion to RGBA failed."},
107     {Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_MIMETYPE, "Unsupported mimetype."},
108     {Image_ErrorCode::IMAGE_SOURCE_TOO_LARGE, "Image too large."},
109     {Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_ALLOCATOR_TYPE, "Unsupported allocator type. e.g.,"
110         "use share memory to decode a HDR image as only DMA supported hdr metadata."},
111     {Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS, "Unsupported options. e.g.,"
112         "1.Convert image into desired pixelFormat failed. 2.Crop pixelMap failed."},
113     {Image_ErrorCode::IMAGE_DECODE_FAILED, "Decode failed. e.g.,Decode image header failed."},
114     {Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED, "Memory allocation failed."}
115 };
116 
ConvertToErrorCode(int32_t errorCode)117 static Image_ErrorCode ConvertToErrorCode(int32_t errorCode)
118 {
119     Image_ErrorCode apiErrorCode = Image_ErrorCode::IMAGE_DECODE_FAILED;
120     auto iter = ERROR_CODE_MAP.find(errorCode);
121     if (iter != ERROR_CODE_MAP.end()) {
122         apiErrorCode = iter->second;
123     }
124     return apiErrorCode;
125 }
126 
GetErrorCodeMsg(Image_ErrorCode apiErrorCode)127 static std::string GetErrorCodeMsg(Image_ErrorCode apiErrorCode)
128 {
129     std::string errMsg = "Decode failed.";
130     auto iter = ERROR_CODE_MESSAGE_MAP.find(apiErrorCode);
131     if (iter != ERROR_CODE_MESSAGE_MAP.end()) {
132         errMsg = iter->second;
133     }
134     return errMsg;
135 }
136 
ImageSourceImpl()137 ImageSourceImpl::ImageSourceImpl() {}
138 
ImageSourceImpl(std::shared_ptr<OHOS::Media::ImageSource> imageSource)139 ImageSourceImpl::ImageSourceImpl(std::shared_ptr<OHOS::Media::ImageSource> imageSource)
140 {
141     nativeImgSrc = imageSource;
142 }
143 
~ImageSourceImpl()144 ImageSourceImpl::~ImageSourceImpl()
145 {
146     ReleaseSync();
147 }
148 
GetImplPtr()149 int64_t ImageSourceImpl::GetImplPtr()
150 {
151     return reinterpret_cast<uintptr_t>(this);
152 }
153 
GetImageInfoSyncWithIndex(uint32_t index)154 ImageInfo ImageSourceImpl::GetImageInfoSyncWithIndex(uint32_t index)
155 {
156     OHOS::Media::ImageInfo imageinfo;
157     bool isHdr = false;
158     if (nativeImgSrc != nullptr) {
159         index = index >= NUM_0 ? index : NUM_0;
160         nativeImgSrc->GetImageInfo(index, imageinfo);
161         isHdr = nativeImgSrc->IsHdrImage();
162     } else {
163         ImageTaiheUtils::ThrowExceptionError("nativeImgSrc is nullptr");
164     }
165     return ImageTaiheUtils::ToTaiheImageInfo(imageinfo, isHdr);
166 }
167 
GetImageInfoSync()168 ImageInfo ImageSourceImpl::GetImageInfoSync()
169 {
170     uint32_t index = 0;
171     return GetImageInfoSyncWithIndex(index);
172 }
173 
ParseRotate(DecodingOptions const & options,OHOS::Media::DecodeOptions & dst,std::string & errMsg)174 static bool ParseRotate(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst, std::string &errMsg)
175 {
176     if (options.rotate.has_value()) {
177         dst.rotateNewDegrees = options.rotate.value();
178         if (dst.rotateNewDegrees >= 0 && dst.rotateNewDegrees <= 360) { // 360 is the maximum rotation angle.
179             dst.rotateDegrees = static_cast<float>(dst.rotateNewDegrees);
180             IMAGE_LOGD("rotateDegrees: %{public}f", dst.rotateDegrees);
181         } else {
182             IMAGE_LOGD("Invalid rotate %{public}d", dst.rotateNewDegrees);
183             errMsg = "DecodeOptions mismatch";
184             return false;
185         }
186     }
187     return true;
188 }
189 
ParseDesiredRegion(DecodingOptions const & options)190 static OHOS::Media::Rect ParseDesiredRegion(DecodingOptions const& options)
191 {
192     OHOS::Media::Rect rect {};
193     if (options.desiredRegion.has_value()) {
194         auto &region = options.desiredRegion.value();
195         rect.left = region.x;
196         rect.top = region.y;
197         rect.width = region.size.width;
198         rect.height = region.size.height;
199         IMAGE_LOGD("desiredRegion: %{public}d, %{public}d, %{public}d, %{public}d",
200             rect.left, rect.top, rect.width, rect.height);
201     }
202     return rect;
203 }
204 
IsAstc(int32_t val)205 static bool IsAstc(int32_t val)
206 {
207     if (val >= static_cast<int32_t>(OHOS::Media::PixelFormat::ASTC_4x4) &&
208         val <= static_cast<int32_t>(OHOS::Media::PixelFormat::ASTC_8x8)) {
209         return true;
210     }
211     return false;
212 }
213 
IsSupportPixelFormat(int32_t val)214 static bool IsSupportPixelFormat(int32_t val)
215 {
216     if (IsAstc(val)) {
217         return true;
218     }
219     if (val >= static_cast<int32_t>(OHOS::Media::PixelFormat::UNKNOWN) &&
220         val < static_cast<int32_t>(OHOS::Media::PixelFormat::EXTERNAL_MAX)) {
221         return true;
222     }
223 
224     return false;
225 }
226 
ParsePixelFormat(int32_t val)227 static OHOS::Media::PixelFormat ParsePixelFormat(int32_t val)
228 {
229     if (IsAstc(val)) {
230         return OHOS::Media::PixelFormat(val);
231     }
232     if (val < static_cast<int32_t>(OHOS::Media::PixelFormat::EXTERNAL_MAX)) {
233         return OHOS::Media::PixelFormat(val);
234     }
235 
236     return OHOS::Media::PixelFormat::UNKNOWN;
237 }
238 
ParsePixelFormat(optional<PixelMapFormat> val,OHOS::Media::PixelFormat & dst,const std::string & name,std::string & errMsg)239 static bool ParsePixelFormat(optional<PixelMapFormat> val, OHOS::Media::PixelFormat &dst, const std::string &name,
240     std::string &errMsg)
241 {
242     if (!val.has_value()) {
243         IMAGE_LOGD("no %{public}s", name.c_str());
244     } else {
245         int32_t pixelFormat = val->get_value();
246         if (IsSupportPixelFormat(pixelFormat)) {
247             dst = ParsePixelFormat(pixelFormat);
248             IMAGE_LOGD("PixelFormat: %{public}d", dst);
249         } else {
250             IMAGE_LOGD("Invalid %{public}s %{public}d", name.c_str(), pixelFormat);
251             errMsg = "DecodeOptions mismatch";
252             return false;
253         }
254     }
255     return true;
256 }
257 
ParseDesiredColorSpace(DecodingOptions const & options,OHOS::Media::DecodeOptions & dst)258 static void ParseDesiredColorSpace(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst)
259 {
260     if (options.desiredColorSpace.has_value()) {
261         ani_object desiredColorSpaceObj = reinterpret_cast<ani_object>(options.desiredColorSpace.value());
262         dst.desiredColorSpaceInfo = OHOS::ColorManager::GetColorSpaceByAniObject(get_env(), desiredColorSpaceObj);
263         IMAGE_LOGD("desiredColorSpace parse finished");
264     }
265     if (dst.desiredColorSpaceInfo == nullptr) {
266         IMAGE_LOGD("no desiredColorSpace");
267     }
268 }
269 
ParseDynamicRange(DecodingOptions const & options)270 static OHOS::Media::DecodeDynamicRange ParseDynamicRange(DecodingOptions const& options)
271 {
272     if (options.desiredDynamicRange.has_value()) {
273         int32_t desiredDynamicRange = options.desiredDynamicRange->get_value();
274         if (desiredDynamicRange <= static_cast<int32_t>(OHOS::Media::DecodeDynamicRange::HDR)) {
275             IMAGE_LOGD("desiredDynamicRange: %{public}d", desiredDynamicRange);
276             return OHOS::Media::DecodeDynamicRange(desiredDynamicRange);
277         }
278     }
279     return OHOS::Media::DecodeDynamicRange::SDR;
280 }
281 
ParseResolutionQuality(DecodingOptions const & options)282 static OHOS::Media::ResolutionQuality ParseResolutionQuality(DecodingOptions const& options)
283 {
284     if (options.resolutionQuality.has_value()) {
285         int32_t resolutionQuality = options.resolutionQuality->get_value();
286         if (resolutionQuality <= static_cast<int32_t>(OHOS::Media::ResolutionQuality::HIGH) &&
287             (resolutionQuality >= static_cast<int32_t>(OHOS::Media::ResolutionQuality::UNKNOWN))) {
288             IMAGE_LOGD("resolutionQuality: %{public}d", resolutionQuality);
289             return OHOS::Media::ResolutionQuality(resolutionQuality);
290         }
291     }
292     return OHOS::Media::ResolutionQuality::UNKNOWN;
293 }
294 
IsCropStrategyVaild(int32_t strategy)295 static inline bool IsCropStrategyVaild(int32_t strategy)
296 {
297     return strategy >= static_cast<int32_t>(OHOS::Media::CropAndScaleStrategy::SCALE_FIRST) &&
298         strategy <= static_cast<int32_t>(OHOS::Media::CropAndScaleStrategy::CROP_FIRST);
299 }
300 
ParseCropAndScaleStrategy(DecodingOptions const & options,OHOS::Media::DecodeOptions & dst)301 static void ParseCropAndScaleStrategy(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst)
302 {
303     if (options.cropAndScaleStrategy.has_value() && IsCropStrategyVaild(options.cropAndScaleStrategy->get_value())) {
304         IMAGE_LOGI("The strategy has taken effect");
305         dst.cropAndScaleStrategy = OHOS::Media::CropAndScaleStrategy(options.cropAndScaleStrategy->get_value());
306         IMAGE_LOGD("cropAndScaleStrategy: %{public}d", dst.cropAndScaleStrategy);
307         return;
308     }
309     IMAGE_LOGI("default cropAndScaleStrategy");
310 }
311 
ParseReusePixelMap(DecodingOptions const & options,OHOS::Media::DecodeOptions & dst)312 static void ParseReusePixelMap(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst)
313 {
314     if (options.reusePixelmap.has_value()) {
315         PixelMap etsPixelMap = options.reusePixelmap.value();
316         std::shared_ptr<OHOS::Media::PixelMap> rPixelMap = PixelMapImpl::GetPixelMap(etsPixelMap);
317         if (rPixelMap != nullptr) {
318             dst.reusePixelmap = rPixelMap;
319             IMAGE_LOGD("reusePixelmap parse finished");
320         }
321     }
322 }
323 
ParseDecodeOptions2(DecodingOptions const & options,OHOS::Media::DecodeOptions & dst,std::string & errMsg)324 static bool ParseDecodeOptions2(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst, std::string &errMsg)
325 {
326     if (!ParsePixelFormat(options.desiredPixelFormat, dst.desiredPixelFormat, "desiredPixelFormat", errMsg) ||
327         !ParsePixelFormat(options.photoDesiredPixelFormat, dst.photoDesiredPixelFormat,
328         "photoDesiredPixelFormat", errMsg)) {
329         return false;
330     }
331 
332     if (options.fitDensity.has_value()) {
333         dst.fitDensity = options.fitDensity.value();
334         IMAGE_LOGD("fitDensity: %{public}d", dst.fitDensity);
335     }
336 
337     if (options.fillColor.has_value()) {
338         dst.SVGOpts.fillColor.isValidColor = true;
339         dst.SVGOpts.fillColor.color = options.fillColor.value();
340         IMAGE_LOGD("fillColor: %{public}d", dst.SVGOpts.fillColor.color);
341     }
342 
343     if (options.SVGResize.has_value()) {
344         dst.SVGOpts.SVGResize.isValidPercentage = true;
345         dst.SVGOpts.SVGResize.resizePercentage = options.SVGResize.value();
346         IMAGE_LOGD("SVGResize: %{public}d", dst.SVGOpts.SVGResize.resizePercentage);
347     }
348 
349     ParseDesiredColorSpace(options, dst);
350     if (dst.desiredColorSpaceInfo == nullptr) {
351         IMAGE_LOGD("no desiredColorSpace");
352     }
353 
354     dst.desiredDynamicRange = ParseDynamicRange(options);
355     dst.resolutionQuality = ParseResolutionQuality(options);
356     ParseCropAndScaleStrategy(options, dst);
357     ParseReusePixelMap(options, dst);
358     return true;
359 }
360 
ParseDecodeOptions(DecodingOptions const & options,OHOS::Media::DecodeOptions & dst,uint32_t & index,std::string & errMsg)361 static bool ParseDecodeOptions(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst, uint32_t &index,
362     std::string &errMsg)
363 {
364     if (options.index.has_value()) {
365         index = options.index.value();
366         IMAGE_LOGD("index: %{public}d", index);
367     }
368 
369     if (options.sampleSize.has_value()) {
370         dst.sampleSize = options.sampleSize.value();
371         IMAGE_LOGD("sampleSize: %{public}d", dst.sampleSize);
372     }
373 
374     CHECK_ERROR_RETURN_RET_LOG(!ParseRotate(options, dst, errMsg), false, "%{public}s ParseRotate failed", __func__);
375 
376     if (options.editable.has_value()) {
377         dst.editable = options.editable.value();
378         IMAGE_LOGD("editable: %{public}d", dst.editable);
379     }
380 
381     if (options.desiredSize.has_value()) {
382         dst.desiredSize.width = options.desiredSize.value().width;
383         dst.desiredSize.height = options.desiredSize.value().height;
384         IMAGE_LOGD("desiredSize: %{public}d, %{public}d", dst.desiredSize.width, dst.desiredSize.height);
385     }
386 
387     dst.desiredRegion = ParseDesiredRegion(options);
388     return ParseDecodeOptions2(options, dst, errMsg);
389 }
390 
CreatePixelMapInner(ImageSourceImpl * const thisPtr,std::shared_ptr<OHOS::Media::ImageSource> imageSource,uint32_t index,OHOS::Media::DecodeOptions decodeOpts,uint32_t & status)391 static std::shared_ptr<OHOS::Media::PixelMap> CreatePixelMapInner(ImageSourceImpl *const thisPtr,
392     std::shared_ptr<OHOS::Media::ImageSource> imageSource, uint32_t index, OHOS::Media::DecodeOptions decodeOpts,
393     uint32_t &status)
394 {
395     if (thisPtr == nullptr || imageSource == nullptr) {
396         IMAGE_LOGE("Invailed args");
397         status = OHOS::Media::ERROR;
398     }
399 
400     std::shared_ptr<OHOS::Media::PixelMap> pixelMap;
401     auto incPixelMap = (thisPtr == nullptr) ? nullptr : thisPtr->GetIncrementalPixelMap();
402     if (incPixelMap != nullptr) {
403         IMAGE_LOGD("Get Incremental PixelMap!!!");
404         pixelMap = incPixelMap;
405     } else {
406         decodeOpts.invokeType = OHOS::Media::JS_INTERFACE;
407         pixelMap = (imageSource == nullptr) ? nullptr : imageSource->CreatePixelMapEx((index >= NUM_0) ? index : NUM_0,
408             decodeOpts, status);
409     }
410 
411     if (status != OHOS::Media::SUCCESS || pixelMap == nullptr) {
412         IMAGE_LOGE("Create PixelMap error");
413     }
414 
415     return pixelMap;
416 }
417 
CreatePixelMapExecute(std::unique_ptr<ImageSourceTaiheContext> & taiheContext)418 static void CreatePixelMapExecute(std::unique_ptr<ImageSourceTaiheContext> &taiheContext)
419 {
420     IMAGE_LOGD("CreatePixelMapExecute IN");
421     if (taiheContext == nullptr) {
422         IMAGE_LOGE("%{public}s taiheContext is nullptr", __func__);
423         return;
424     }
425 
426     if (taiheContext->errMsg.size() > 0) {
427         IMAGE_LOGE("%{public}s errMsg: %{public}s", __func__, taiheContext->errMsg.c_str());
428         return;
429     }
430 
431     taiheContext->rPixelMap = CreatePixelMapInner(taiheContext->thisPtr, taiheContext->rImageSource,
432         taiheContext->index, taiheContext->decodeOpts, taiheContext->status);
433 
434     if (taiheContext->status != OHOS::Media::SUCCESS) {
435         taiheContext->errMsg = "Create PixelMap error";
436         IMAGE_LOGE("Create PixelMap error");
437     }
438     IMAGE_LOGD("CreatePixelMapExecute OUT");
439 }
440 
CreatePixelMapComplete(std::unique_ptr<ImageSourceTaiheContext> & taiheContext)441 static PixelMap CreatePixelMapComplete(std::unique_ptr<ImageSourceTaiheContext> &taiheContext)
442 {
443     IMAGE_LOGD("CreatePixelMapComplete IN");
444     if (taiheContext->status == OHOS::Media::SUCCESS && taiheContext->rPixelMap != nullptr) {
445         return PixelMapImpl::CreatePixelMap(taiheContext->rPixelMap);
446     }
447     IMAGE_LOGD("CreatePixelMapComplete OUT");
448     ImageTaiheUtils::ThrowExceptionError(taiheContext->errMsg);
449     return make_holder<PixelMapImpl, PixelMap>();
450 }
451 
CreatePixelMapSyncWithOptions(DecodingOptions const & options)452 PixelMap ImageSourceImpl::CreatePixelMapSyncWithOptions(DecodingOptions const& options)
453 {
454     std::unique_ptr<ImageSourceTaiheContext> taiheContext = std::make_unique<ImageSourceTaiheContext>();
455     taiheContext->rImageSource = nativeImgSrc;
456     if (taiheContext->rImageSource == nullptr) {
457         IMAGE_LOGE("%{public}s nativeImgSrc is nullptr", __func__);
458         ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "nativeImgSrc is nullptr");
459         return make_holder<PixelMapImpl, PixelMap>();
460     }
461 
462     taiheContext->thisPtr = this;
463     if (taiheContext->thisPtr == nullptr) {
464         IMAGE_LOGE("%{public}s thisPtr is nullptr", __func__);
465         ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "thisPtr is nullptr");
466         return make_holder<PixelMapImpl, PixelMap>();
467     }
468 
469     if (!ParseDecodeOptions(options, taiheContext->decodeOpts, taiheContext->index,
470         taiheContext->errMsg)) {
471         IMAGE_LOGE("%{public}s ParseDecodeOptions failed", __func__);
472     }
473 
474     ImageTaiheUtils::HicheckerReport();
475     CreatePixelMapExecute(taiheContext);
476     return CreatePixelMapComplete(taiheContext);
477 }
478 
CreatePixelMapSync()479 PixelMap ImageSourceImpl::CreatePixelMapSync()
480 {
481     DecodingOptions options {};
482     return CreatePixelMapSyncWithOptions(options);
483 }
484 
CreatePixelMapUsingAllocatorSyncExecute(std::unique_ptr<ImageSourceTaiheContext> & taiheContext)485 static void CreatePixelMapUsingAllocatorSyncExecute(std::unique_ptr<ImageSourceTaiheContext> &taiheContext)
486 {
487     if (taiheContext == nullptr) {
488         IMAGE_LOGE("%{public}s taiheContext is nullptr", __func__);
489         return;
490     }
491 
492     taiheContext->rPixelMap = CreatePixelMapInner(taiheContext->thisPtr, taiheContext->rImageSource,
493         taiheContext->index, taiheContext->decodeOpts, taiheContext->status);
494     if (taiheContext->status != OHOS::Media::SUCCESS) {
495         Image_ErrorCode apiErrorCode = ConvertToErrorCode(taiheContext->status);
496         std::string apiErrorMsg = GetErrorCodeMsg(apiErrorCode);
497         taiheContext->errMsgArray.emplace(apiErrorCode, apiErrorMsg);
498     }
499 }
500 
CreatePixelMapUsingAllocatorSyncComplete(std::unique_ptr<ImageSourceTaiheContext> & taiheContext)501 static PixelMap CreatePixelMapUsingAllocatorSyncComplete(std::unique_ptr<ImageSourceTaiheContext> &taiheContext)
502 {
503     if (taiheContext->status == OHOS::Media::SUCCESS && taiheContext->rPixelMap != nullptr) {
504         return PixelMapImpl::CreatePixelMap(taiheContext->rPixelMap);
505     }
506     for (const auto &[errorCode, errMsg] : taiheContext->errMsgArray) {
507         ImageTaiheUtils::ThrowExceptionError(errorCode, errMsg);
508     }
509     return make_holder<PixelMapImpl, PixelMap>();
510 }
511 
CreatePixelMapUsingAllocatorSync(optional_view<DecodingOptions> options,optional_view<AllocatorType> allocatorType)512 PixelMap ImageSourceImpl::CreatePixelMapUsingAllocatorSync(optional_view<DecodingOptions> options,
513     optional_view<AllocatorType> allocatorType)
514 {
515     std::unique_ptr<ImageSourceTaiheContext> taiheContext = std::make_unique<ImageSourceTaiheContext>();
516     taiheContext->rImageSource = nativeImgSrc;
517     if (taiheContext->rImageSource == nullptr) {
518         IMAGE_LOGE("%{public}s nativeImgSrc is nullptr", __func__);
519         return make_holder<PixelMapImpl, PixelMap>();
520     }
521 
522     taiheContext->thisPtr = this;
523     if (taiheContext->thisPtr == nullptr) {
524         IMAGE_LOGE("%{public}s thisPtr is nullptr", __func__);
525         return make_holder<PixelMapImpl, PixelMap>();
526     }
527 
528     DecodingOptions opts = options.value_or(DecodingOptions {});
529     if (!ParseDecodeOptions(opts, taiheContext->decodeOpts, taiheContext->index,
530         taiheContext->errMsg)) {
531         IMAGE_LOGE("DecodeOptions mismatch.");
532         ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "DecodeOptions mismatch.");
533         return make_holder<PixelMapImpl, PixelMap>();
534     }
535 
536     int32_t allocatorTypeInner = allocatorType.value_or(AllocatorType::key_t::AUTO);
537     if (!taiheContext->rImageSource->IsSupportAllocatorType(taiheContext->decodeOpts, allocatorTypeInner)) {
538         IMAGE_LOGE("Unsupported allocator type.");
539         ImageTaiheUtils::ThrowExceptionError(IMAGE_SOURCE_UNSUPPORTED_ALLOCATOR_TYPE, "Unsupported allocator type.");
540         return make_holder<PixelMapImpl, PixelMap>();
541     }
542 
543     CreatePixelMapUsingAllocatorSyncExecute(taiheContext);
544     return CreatePixelMapUsingAllocatorSyncComplete(taiheContext);
545 }
546 
CheckAsyncContext(std::unique_ptr<ImageSourceTaiheContext> & taiheContext,bool check)547 static bool CheckAsyncContext(std::unique_ptr<ImageSourceTaiheContext> &taiheContext, bool check)
548 {
549     if (taiheContext == nullptr) {
550         IMAGE_LOGE("context is nullptr");
551         return false;
552     }
553 
554     if (check) {
555         if (taiheContext->errMsg.size() > 0) {
556             IMAGE_LOGE("mismatch args");
557             taiheContext->status = OHOS::Media::ERROR;
558             return false;
559         }
560 
561         if (taiheContext->rImageSource == nullptr) {
562             IMAGE_LOGE("empty context rImageSource");
563             taiheContext->status = OHOS::Media::ERROR;
564             return false;
565         }
566     }
567 
568     return true;
569 }
570 
CreatePixelMapListSyncWithOptionsExecute(std::unique_ptr<ImageSourceTaiheContext> & taiheContext)571 static void CreatePixelMapListSyncWithOptionsExecute(std::unique_ptr<ImageSourceTaiheContext> &taiheContext)
572 {
573     if (!CheckAsyncContext(taiheContext, true)) {
574         IMAGE_LOGE("check taiheContext fail");
575         return;
576     }
577 
578     taiheContext->pixelMaps = nullptr;
579     uint32_t errorCode = 0;
580     uint32_t frameCount = taiheContext->rImageSource->GetFrameCount(errorCode);
581     if ((errorCode == OHOS::Media::SUCCESS) && (taiheContext->index >= NUM_0) && (taiheContext->index < frameCount)) {
582         taiheContext->decodeOpts.invokeType = OHOS::Media::JS_INTERFACE;
583         taiheContext->pixelMaps = taiheContext->rImageSource->CreatePixelMapList(taiheContext->decodeOpts, errorCode);
584     }
585 
586     if ((errorCode == OHOS::Media::SUCCESS) && taiheContext->pixelMaps != nullptr) {
587         taiheContext->status = OHOS::Media::SUCCESS;
588     } else {
589         IMAGE_LOGE("Create PixelMap List error, error=%{public}u", errorCode);
590         taiheContext->errMsg = "Create PixelMap List error";
591         taiheContext->status = (errorCode != OHOS::Media::SUCCESS) ? errorCode : OHOS::Media::ERROR;
592     }
593 }
594 
CreatePixelMapListSyncWithOptionsComplete(std::unique_ptr<ImageSourceTaiheContext> & taiheContext)595 static array<PixelMap> CreatePixelMapListSyncWithOptionsComplete(std::unique_ptr<ImageSourceTaiheContext> &taiheContext)
596 {
597     if (!CheckAsyncContext(taiheContext, false)) {
598         IMAGE_LOGE("check taiheContext fail");
599         return array<PixelMap>(nullptr, 0);
600     }
601 
602     std::vector<PixelMap> result;
603     if (taiheContext->status == OHOS::Media::SUCCESS && taiheContext->pixelMaps != nullptr) {
604         IMAGE_LOGD("CreatePixelMapListSyncWithOptionsComplete array");
605         for (auto &pixelMap : *taiheContext->pixelMaps.get()) {
606             result.emplace_back(PixelMapImpl::CreatePixelMap(std::move(pixelMap)));
607         }
608     }
609     return array<PixelMap>(result);
610 }
611 
CreatePixelMapListSyncWithOptions(DecodingOptions const & options)612 array<PixelMap> ImageSourceImpl::CreatePixelMapListSyncWithOptions(DecodingOptions const& options)
613 {
614     OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::CreatePixelMapListSyncWithOptions");
615     std::unique_ptr<ImageSourceTaiheContext> taiheContext = std::make_unique<ImageSourceTaiheContext>();
616     taiheContext->rImageSource = nativeImgSrc;
617     if (taiheContext->rImageSource == nullptr) {
618         ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "nativeImgSrc is nullptr");
619         return array<PixelMap>(nullptr, 0);
620     }
621 
622     taiheContext->thisPtr = this;
623     if (taiheContext->thisPtr == nullptr) {
624         ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "thisPtr is nullptr");
625         return array<PixelMap>(nullptr, 0);
626     }
627 
628     if (!ParseDecodeOptions(options, taiheContext->decodeOpts, taiheContext->index,
629         taiheContext->errMsg)) {
630         IMAGE_LOGE("DecodeOptions mismatch.");
631         ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "DecodeOptions mismatch.");
632         return array<PixelMap>(nullptr, 0);
633     }
634 
635     ImageTaiheUtils::HicheckerReport();
636     CreatePixelMapListSyncWithOptionsExecute(taiheContext);
637     return CreatePixelMapListSyncWithOptionsComplete(taiheContext);
638 }
639 
CreatePixelMapListSync()640 array<PixelMap> ImageSourceImpl::CreatePixelMapListSync()
641 {
642     return CreatePixelMapListSyncWithOptions({});
643 }
644 
CreatePixelMapListSyncWithOptionalOptions(optional_view<DecodingOptions> options)645 array<PixelMap> ImageSourceImpl::CreatePixelMapListSyncWithOptionalOptions(optional_view<DecodingOptions> options)
646 {
647     return CreatePixelMapListSyncWithOptions(options.value_or(DecodingOptions {}));
648 }
649 
GetDelayTimeListSync()650 array<int32_t> ImageSourceImpl::GetDelayTimeListSync()
651 {
652     OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::GetDelayTimeListSync");
653 
654     if (nativeImgSrc == nullptr) {
655         ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "nativeImgSrc is nullptr.");
656         return array<int32_t>(0);
657     }
658 
659     uint32_t errorCode = 0;
660     auto delayTimes = nativeImgSrc->GetDelayTime(errorCode);
661     if ((errorCode != OHOS::Media::SUCCESS) || (delayTimes == nullptr)) {
662         IMAGE_LOGE("Get DelayTime error, error=%{public}u", errorCode);
663         ImageTaiheUtils::ThrowExceptionError((errorCode != OHOS::Media::SUCCESS) ? errorCode : OHOS::Media::ERROR,
664             "Get DelayTime error");
665         return array<int32_t>(0);
666     } else {
667         return array<int32_t>(taihe::copy_data_t{}, delayTimes->data(), delayTimes->size());
668     }
669 }
670 
ParsePropertyOptions(std::unique_ptr<ImageSourceTaiheContext> & context,optional_view<ImagePropertyOptions> & options)671 static bool ParsePropertyOptions(std::unique_ptr<ImageSourceTaiheContext> &context,
672     optional_view<ImagePropertyOptions> &options)
673 {
674     if (!options->index.has_value()) {
675         IMAGE_LOGD("no index");
676         return false;
677     }
678     context->index = options->index.value();
679     if (!options->defaultValue.has_value()) {
680         IMAGE_LOGD("no defaultValue");
681     } else {
682         context->defaultValueStr = options->defaultValue.value();
683     }
684     return true;
685 }
686 
GenerateErrMsg(std::unique_ptr<ImageSourceTaiheContext> & context,std::string & errMsg)687 static void GenerateErrMsg(std::unique_ptr<ImageSourceTaiheContext> &context, std::string &errMsg)
688 {
689     if (context == nullptr) {
690         return;
691     }
692     switch (context->status) {
693         case OHOS::Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT:
694             errMsg = "The image does not support EXIF decoding.";
695             break;
696         case OHOS::Media::ERROR:
697             errMsg = "The operation failed.";
698             break;
699         case OHOS::Media::ERR_IMAGE_DATA_UNSUPPORT:
700             errMsg = "The image data is not supported.";
701             break;
702         case OHOS::Media::ERR_IMAGE_SOURCE_DATA:
703             errMsg = "The image source data is incorrect.";
704             break;
705         case OHOS::Media::ERR_IMAGE_SOURCE_DATA_INCOMPLETE:
706             errMsg = "The image source data is incomplete.";
707             break;
708         case OHOS::Media::ERR_IMAGE_MISMATCHED_FORMAT:
709             errMsg = "The image format does not mastch.";
710             break;
711         case OHOS::Media::ERR_IMAGE_UNKNOWN_FORMAT:
712             errMsg = "Unknown image format.";
713             break;
714         case OHOS::Media::ERR_IMAGE_INVALID_PARAMETER:
715             errMsg = "Invalid image parameter.";
716             break;
717         case OHOS::Media::ERR_IMAGE_DECODE_FAILED:
718             errMsg = "Failed to decode the image.";
719             break;
720         case OHOS::Media::ERR_IMAGE_PLUGIN_CREATE_FAILED:
721             errMsg = "Failed to create the image plugin.";
722             break;
723         case OHOS::Media::ERR_IMAGE_DECODE_HEAD_ABNORMAL:
724             errMsg = "Failed to decode the image header.";
725             break;
726         case OHOS::Media::ERR_MEDIA_VALUE_INVALID:
727             errMsg = "The EXIF value is invalid.";
728             break;
729         default:
730             errMsg = "There is unknown error happened.";
731     }
732 }
733 
GetImagePropertySync(PropertyKey key,optional_view<ImagePropertyOptions> options)734 string ImageSourceImpl::GetImagePropertySync(PropertyKey key, optional_view<ImagePropertyOptions> options)
735 {
736     OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::GetImagePropertySync");
737 
738     std::unique_ptr<ImageSourceTaiheContext> context = std::make_unique<ImageSourceTaiheContext>();
739     if (nativeImgSrc == nullptr) {
740         ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "empty native rImageSource");
741         return context->valueStr;
742     }
743 
744     if (options.has_value() && !ParsePropertyOptions(context, options)) {
745         ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PropertyOptions mismatch");
746         return context->valueStr;
747     }
748 
749     context->keyStr = std::string(key.get_value());
750     context->status = nativeImgSrc->GetImagePropertyString(context->index, context->keyStr, context->valueStr);
751     if (context->status != OHOS::Media::SUCCESS) {
752         if (!context->defaultValueStr.empty()) {
753             return context->defaultValueStr;
754         }
755         std::string errMsg;
756         GenerateErrMsg(context, errMsg);
757         ImageTaiheUtils::ThrowExceptionError(context->status, errMsg);
758     }
759     return context->valueStr;
760 }
761 
GetImagePropertiesExecute(std::unique_ptr<ImageSourceTaiheContext> & context)762 static void GetImagePropertiesExecute(std::unique_ptr<ImageSourceTaiheContext> &context)
763 {
764     if (context == nullptr) {
765         IMAGE_LOGE("empty context");
766         return;
767     }
768     uint32_t status = OHOS::Media::SUCCESS;
769     for (auto keyStrIt = context->keyStrArray.begin(); keyStrIt != context->keyStrArray.end(); ++keyStrIt) {
770         std::string valueStr = "";
771         status = context->rImageSource->GetImagePropertyString(0, *keyStrIt, valueStr);
772         if (status == OHOS::Media::SUCCESS) {
773             context->kVStrArray.emplace_back(std::make_pair(*keyStrIt, valueStr));
774         } else {
775             context->kVStrArray.emplace_back(std::make_pair(*keyStrIt, ""));
776             context->errMsgArray.insert(std::make_pair(status, *keyStrIt));
777             IMAGE_LOGE("errCode: %{public}u , exif key: %{public}s", status, keyStrIt->c_str());
778         }
779     }
780     context->status = context->kVStrArray.size() == context->errMsgArray.size() ?
781         OHOS::Media::ERROR : OHOS::Media::SUCCESS;
782 }
783 
CreatePropertyValue(const std::string & valueStr)784 static PropertyValue CreatePropertyValue(const std::string& valueStr)
785 {
786     if (!valueStr.empty()) {
787         return PropertyValue::make_type_string(valueStr);
788     } else {
789         return PropertyValue::make_type_null();
790     }
791 }
792 
CreatePropertiesRecord(std::vector<std::pair<std::string,std::string>> recordParameters)793 map<PropertyKey, PropertyValue> CreatePropertiesRecord(
794     std::vector<std::pair<std::string, std::string>> recordParameters)
795 {
796     map<PropertyKey, PropertyValue> result;
797     for (size_t index = 0; index < recordParameters.size(); ++index) {
798         PropertyKey::key_t key;
799         if (!ImageTaiheUtils::GetEnumKeyByValue<PropertyKey>(recordParameters[index].first, key)) {
800             IMAGE_LOGE("Get current record parameter failed");
801             continue;
802         }
803         PropertyValue value = CreatePropertyValue(recordParameters[index].second);
804         result.emplace(PropertyKey(key), value);
805     }
806 
807     IMAGE_LOGD("Get record parameters info success.");
808     return result;
809 }
810 
CreateObtainErrorArray(std::multimap<std::int32_t,std::string> errMsgArray)811 void CreateObtainErrorArray(std::multimap<std::int32_t, std::string> errMsgArray)
812 {
813     for (auto it = errMsgArray.begin(); it != errMsgArray.end(); ++it) {
814         std::string errMsg;
815         int32_t errCode = it->first;
816         if (errCode == OHOS::Media::ERR_IMAGE_DECODE_ABNORMAL) {
817             errMsg = "The image source data is incorrect! exif key: " + it->second;
818         } else if (errCode == OHOS::Media::ERR_IMAGE_UNKNOWN_FORMAT) {
819             errMsg = "Unknown image format! exif key: " + it->second;
820         } else if (errCode == OHOS::Media::ERR_IMAGE_DECODE_FAILED) {
821             errMsg = "Failed to decode the image! exif key: " + it->second;
822         } else {
823             errCode = OHOS::Media::ERROR;
824             errMsg = "There is generic taihe failure! exif key: " + it->second;
825         }
826         ImageTaiheUtils::ThrowExceptionError(errCode, errMsg);
827     }
828 
829     IMAGE_LOGD("Create obtain error array success.");
830 }
831 
GetStringArrayArgument(array_view<PropertyKey> key)832 std::vector<std::string> GetStringArrayArgument(array_view<PropertyKey> key)
833 {
834     std::vector<std::string> keyStrArray;
835 
836     for (uint32_t i = 0; i < key.size(); i++) {
837         keyStrArray.emplace_back(key[i].get_value());
838     }
839 
840     IMAGE_LOGD("Get string argument success.");
841     return keyStrArray;
842 }
843 
GetImagePropertiesSync(array_view<PropertyKey> key)844 map<PropertyKey, PropertyValue> ImageSourceImpl::GetImagePropertiesSync(array_view<PropertyKey> key)
845 {
846     OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::GetImagePropertiesSync");
847 
848     map<PropertyKey, PropertyValue> result;
849     std::unique_ptr<ImageSourceTaiheContext> context = std::make_unique<ImageSourceTaiheContext>();
850     if (nativeImgSrc == nullptr) {
851         ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "empty native rImageSource");
852         return result;
853     }
854     context->rImageSource = nativeImgSrc;
855     context->keyStrArray = GetStringArrayArgument(key);
856     if (context->keyStrArray.size() == 0) return result;
857 
858     GetImagePropertiesExecute(context);
859 
860     if (context->status == OHOS::Media::SUCCESS) {
861         result = CreatePropertiesRecord(context->kVStrArray);
862     } else {
863         CreateObtainErrorArray(context->errMsgArray);
864     }
865     return result;
866 }
867 
CreateModifyErrorArray(std::multimap<std::int32_t,std::string> errMsgArray)868 void CreateModifyErrorArray(std::multimap<std::int32_t, std::string> errMsgArray)
869 {
870     for (auto it = errMsgArray.begin(); it != errMsgArray.end(); ++it) {
871         if (it->first == OHOS::Media::ERR_MEDIA_WRITE_PARCEL_FAIL) {
872             ImageTaiheUtils::ThrowExceptionError(it->first,
873                 "Create Fd without write permission! exif key: " + it->second);
874         } else if (it->first == OHOS::Media::ERR_MEDIA_OUT_OF_RANGE) {
875             ImageTaiheUtils::ThrowExceptionError(it->first,
876                 "The given buffer size is too small to add new exif data! exif key: " + it->second);
877         } else if (it->first == OHOS::Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
878             ImageTaiheUtils::ThrowExceptionError(it->first,
879                 "The image does not support EXIF decoding. exif key: " + it->second);
880         } else if (it->first == OHOS::Media::ERR_MEDIA_VALUE_INVALID) {
881             ImageTaiheUtils::ThrowExceptionError(it->first, it->second);
882         } else {
883             ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERROR,
884                 "There is generic taihe failure! exif key: " + it->second);
885         }
886     }
887 
888     IMAGE_LOGD("Create modify error array success.");
889 }
890 
ModifyImagePropertyComplete(std::unique_ptr<ImageSourceTaiheContext> & context)891 static void ModifyImagePropertyComplete(std::unique_ptr<ImageSourceTaiheContext> &context)
892 {
893     if (context == nullptr) {
894         IMAGE_LOGE("context is nullptr");
895         return;
896     }
897 
898     if (context->status == OHOS::Media::SUCCESS) {
899         IMAGE_LOGI("ModifyImageProperty success.");
900         return;
901     }
902 
903     if (context->isBatch) {
904         CreateModifyErrorArray(context->errMsgArray);
905     } else {
906         if (context->status == OHOS::Media::ERR_MEDIA_WRITE_PARCEL_FAIL) {
907             if (context->fdIndex != INVALID_FD) {
908                 ImageTaiheUtils::ThrowExceptionError(context->status, "Create Fd without write permission!");
909             } else {
910                 ImageTaiheUtils::ThrowExceptionError(context->status,
911                     "The EXIF data failed to be written to the file.");
912             }
913         } else if (context->status == OHOS::Media::ERR_MEDIA_OUT_OF_RANGE) {
914             ImageTaiheUtils::ThrowExceptionError(context->status,
915                 "The given buffer size is too small to add new exif data!");
916         } else if (context->status == OHOS::Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
917             ImageTaiheUtils::ThrowExceptionError(context->status,
918                 "The exif data format is not standard, so modify it failed!");
919         } else if (context->status == OHOS::Media::ERR_MEDIA_VALUE_INVALID) {
920             ImageTaiheUtils::ThrowExceptionError(context->status, context->errMsg);
921         } else {
922             ImageTaiheUtils::ThrowExceptionError(context->status,
923                 "There is generic taihe failure!");
924         }
925     }
926 }
927 
CheckExifDataValue(const std::string & key,const std::string & value,std::string & errorInfo)928 static uint32_t CheckExifDataValue(const std::string &key, const std::string &value, std::string &errorInfo)
929 {
930     auto status = static_cast<uint32_t>(OHOS::Media::ExifMetadatFormatter::Validate(key, value));
931     if (status != OHOS::Media::SUCCESS) {
932         errorInfo = key + " has invalid exif value: ";
933         errorInfo.append(value);
934     }
935     return status;
936 }
937 
ModifyImagePropertyExecute(std::unique_ptr<ImageSourceTaiheContext> & context)938 static void ModifyImagePropertyExecute(std::unique_ptr<ImageSourceTaiheContext> &context)
939 {
940     if (context == nullptr) {
941         IMAGE_LOGE("empty context");
942         return;
943     }
944     IMAGE_LOGD("ModifyImagePropertyExecute CheckExifDataValue");
945     uint32_t status = CheckExifDataValue(context->keyStr, context->valueStr, context->errMsg);
946     IMAGE_LOGD("ModifyImagePropertyExecute Check ret status: %{public}d", status);
947     if (status != OHOS::Media::SUCCESS) {
948         IMAGE_LOGE("There is invalid exif data parameter");
949         context->status = status;
950         return;
951     }
952     context->status = context->rImageSource->ModifyImagePropertyEx(context->index, context->keyStr, context->valueStr);
953 }
954 
ModifyImagePropertySync(PropertyKey key,string_view value)955 void ImageSourceImpl::ModifyImagePropertySync(PropertyKey key, string_view value)
956 {
957     OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::ModifyImagePropertySync");
958 
959     std::unique_ptr<ImageSourceTaiheContext> context = std::make_unique<ImageSourceTaiheContext>();
960     if (nativeImgSrc == nullptr) {
961         ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "empty native rImageSource");
962         return;
963     }
964     context->rImageSource = nativeImgSrc;
965 
966     context->keyStr = std::string(key.get_value());
967     context->valueStr = std::string(value);
968 
969     context->pathName = ImageSourceImpl::filePath_;
970     context->fdIndex = ImageSourceImpl::fileDescriptor_;
971     context->sourceBuffer = ImageSourceImpl::fileBuffer_;
972     context->sourceBufferSize = ImageSourceImpl::fileBufferSize_;
973 
974     ModifyImagePropertyExecute(context);
975     ModifyImagePropertyComplete(context);
976 }
977 
ModifyImagePropertiesExecute(std::unique_ptr<ImageSourceTaiheContext> & context)978 static void ModifyImagePropertiesExecute(std::unique_ptr<ImageSourceTaiheContext> &context)
979 {
980     if (context == nullptr) {
981         IMAGE_LOGE("empty context");
982         return;
983     }
984     uint32_t status = OHOS::Media::SUCCESS;
985     for (auto recordIterator = context->kVStrArray.begin(); recordIterator != context->kVStrArray.end();
986         ++recordIterator) {
987         IMAGE_LOGD("CheckExifDataValue");
988         status = CheckExifDataValue(recordIterator->first, recordIterator->second, context->errMsg);
989         IMAGE_LOGD("Check ret status: %{public}d", status);
990         if (status != OHOS::Media::SUCCESS) {
991             IMAGE_LOGE("There is invalid exif data parameter");
992             context->errMsgArray.insert(std::make_pair(status, context->errMsg));
993             continue;
994         }
995         status = context->rImageSource->ModifyImagePropertyEx(0, recordIterator->first, recordIterator->second);
996         if (status != OHOS::Media::SUCCESS) {
997             context->errMsgArray.insert(std::make_pair(status, recordIterator->first));
998         }
999     }
1000     context->status = context->errMsgArray.size() > 0 ? OHOS::Media::ERROR : OHOS::Media::SUCCESS;
1001 }
1002 
GetRecordArgument(map_view<PropertyKey,PropertyValue> records)1003 std::vector<std::pair<std::string, std::string>> GetRecordArgument(map_view<PropertyKey, PropertyValue> records)
1004 {
1005     std::vector<std::pair<std::string, std::string>> kVStrArray;
1006 
1007     for (const auto& [key, value] : records) {
1008         std::string valueStr;
1009         if (value.holds_type_string()) {
1010             valueStr = std::string(value.get_type_string_ref());
1011         } else if (value.holds_type_null()) {
1012             valueStr = "";
1013         }
1014         kVStrArray.push_back(std::make_pair(std::string(key.get_value()), valueStr));
1015     }
1016 
1017     IMAGE_LOGD("Get record argument success.");
1018     return kVStrArray;
1019 }
1020 
ModifyImagePropertiesSync(map_view<PropertyKey,PropertyValue> records)1021 void ImageSourceImpl::ModifyImagePropertiesSync(map_view<PropertyKey, PropertyValue> records)
1022 {
1023     OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::ModifyImagePropertiesSync");
1024 
1025     std::unique_ptr<ImageSourceTaiheContext> context = std::make_unique<ImageSourceTaiheContext>();
1026     if (nativeImgSrc == nullptr) {
1027         ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "empty native rImageSource");
1028         return;
1029     }
1030     context->rImageSource = nativeImgSrc;
1031 
1032     context->kVStrArray = GetRecordArgument(records);
1033     if (context->kVStrArray.size() == 0) return;
1034     context->isBatch = true;
1035 
1036     context->pathName = ImageSourceImpl::filePath_;
1037     context->fdIndex = ImageSourceImpl::fileDescriptor_;
1038     context->sourceBuffer = ImageSourceImpl::fileBuffer_;
1039     context->sourceBufferSize = ImageSourceImpl::fileBufferSize_;
1040 
1041     ModifyImagePropertiesExecute(context);
1042     ModifyImagePropertyComplete(context);
1043 }
1044 
ReleaseSync()1045 void ImageSourceImpl::ReleaseSync()
1046 {
1047     if (!isRelease) {
1048         if (nativeImgSrc != nullptr) {
1049             nativeImgSrc = nullptr;
1050         }
1051         isRelease = true;
1052     }
1053 }
1054 
GetSupportedFormats()1055 array<string> ImageSourceImpl::GetSupportedFormats()
1056 {
1057     std::set<std::string> formats;
1058     nativeImgSrc->GetSupportedFormats(formats);
1059     std::vector<std::string> vec(formats.begin(), formats.end());
1060     return ImageTaiheUtils::ToTaiheArrayString(vec);
1061 }
1062 
FileUrlToRawPath(const std::string & path)1063 static std::string FileUrlToRawPath(const std::string &path)
1064 {
1065     if (path.size() > FILE_URL_PREFIX.size() &&
1066         (path.compare(0, FILE_URL_PREFIX.size(), FILE_URL_PREFIX) == 0)) {
1067         return path.substr(FILE_URL_PREFIX.size());
1068     }
1069     return path;
1070 }
1071 
CreateImageSourceByUriOption(string_view uri,SourceOptions const & options)1072 ImageSource CreateImageSourceByUriOption(string_view uri, SourceOptions const& options)
1073 {
1074     OHOS::Media::SourceOptions opts = ImageTaiheUtils::ParseSourceOptions(options);
1075     uint32_t errorCode = OHOS::Media::ERR_MEDIA_INVALID_VALUE;
1076     std::string rawPath = FileUrlToRawPath(std::string(uri));
1077 
1078     std::shared_ptr<OHOS::Media::ImageSource> imageSource =
1079         OHOS::Media::ImageSource::CreateImageSource(rawPath, opts, errorCode);
1080     if (imageSource == nullptr) {
1081         ImageTaiheUtils::ThrowExceptionError("CreateImageSourceByUriOption error");
1082         return make_holder<ImageSourceImpl, ImageSource>();
1083     }
1084     {
1085         std::lock_guard<std::mutex> lock(imageSourceCrossThreadMutex_);
1086         ImageSourceImpl::filePath_ = rawPath;
1087         ImageSourceImpl::fileDescriptor_ = INVALID_FD;
1088         ImageSourceImpl::fileBuffer_ = nullptr;
1089         ImageSourceImpl::fileBufferSize_ = NUM_0;
1090     }
1091     return make_holder<ImageSourceImpl, ImageSource>(imageSource);
1092 }
1093 
CreateImageSourceByUri(string_view uri)1094 ImageSource CreateImageSourceByUri(string_view uri)
1095 {
1096     SourceOptions opts {};
1097     return CreateImageSourceByUriOption(uri, opts);
1098 }
1099 
CreateImageSourceByFdOption(double fd,SourceOptions const & options)1100 ImageSource CreateImageSourceByFdOption(double fd, SourceOptions const& options)
1101 {
1102     int32_t fdInt = static_cast<int32_t>(fd);
1103     OHOS::Media::SourceOptions opts = ImageTaiheUtils::ParseSourceOptions(options);
1104     uint32_t errorCode = OHOS::Media::ERR_MEDIA_INVALID_VALUE;
1105     std::shared_ptr<OHOS::Media::ImageSource> imageSource =
1106         OHOS::Media::ImageSource::CreateImageSource(fdInt, opts, errorCode);
1107     if (imageSource == nullptr) {
1108         ImageTaiheUtils::ThrowExceptionError("CreateImageSourceByFdOption error");
1109         return make_holder<ImageSourceImpl, ImageSource>();
1110     }
1111     {
1112         std::lock_guard<std::mutex> lock(imageSourceCrossThreadMutex_);
1113         ImageSourceImpl::filePath_ = "";
1114         ImageSourceImpl::fileDescriptor_ = fdInt;
1115         ImageSourceImpl::fileBuffer_ = nullptr;
1116         ImageSourceImpl::fileBufferSize_ = NUM_0;
1117     }
1118     return make_holder<ImageSourceImpl, ImageSource>(imageSource);
1119 }
1120 
CreateImageSourceByFd(int32_t fd)1121 ImageSource CreateImageSourceByFd(int32_t fd)
1122 {
1123     SourceOptions opts {};
1124     return CreateImageSourceByFdOption(fd, opts);
1125 }
1126 
CreateImageSourceByArrayBufferOption(array_view<uint8_t> buf,SourceOptions const & options)1127 ImageSource CreateImageSourceByArrayBufferOption(array_view<uint8_t> buf, SourceOptions const& options)
1128 {
1129     OHOS::Media::SourceOptions opts = ImageTaiheUtils::ParseSourceOptions(options);
1130     uint32_t errorCode = OHOS::Media::ERR_MEDIA_INVALID_VALUE;
1131     uint8_t *bufPtr = const_cast<uint8_t *>(buf.data());
1132     std::shared_ptr<OHOS::Media::ImageSource> imageSource =
1133         OHOS::Media::ImageSource::CreateImageSource(bufPtr, buf.size(), opts, errorCode);
1134     if (imageSource == nullptr) {
1135         ImageTaiheUtils::ThrowExceptionError("CreateImageSourceByArrayBufferOption error");
1136         return make_holder<ImageSourceImpl, ImageSource>();
1137     }
1138     {
1139         std::lock_guard<std::mutex> lock(imageSourceCrossThreadMutex_);
1140         ImageSourceImpl::filePath_ = "";
1141         ImageSourceImpl::fileDescriptor_ = INVALID_FD;
1142         ImageSourceImpl::fileBuffer_ = bufPtr;
1143         ImageSourceImpl::fileBufferSize_ = buf.size();
1144     }
1145     return make_holder<ImageSourceImpl, ImageSource>(imageSource);
1146 }
1147 
CreateImageSourceByArrayBuffer(array_view<uint8_t> buf)1148 ImageSource CreateImageSourceByArrayBuffer(array_view<uint8_t> buf)
1149 {
1150     SourceOptions opts {};
1151     return CreateImageSourceByArrayBufferOption(buf, opts);
1152 }
1153 
CreateImageSourceByRawFileDescriptorOption(uintptr_t rawfile,optional_view<SourceOptions> options)1154 ImageSource CreateImageSourceByRawFileDescriptorOption(uintptr_t rawfile, optional_view<SourceOptions> options)
1155 {
1156     double fd;
1157     double offset;
1158     double length;
1159     ani_env *env = ::taihe::get_env();
1160     ani_object rawfileObj = reinterpret_cast<ani_object>(rawfile);
1161     if (!ImageTaiheUtils::GetPropertyDouble(env, rawfileObj, "fd", fd) ||
1162         !ImageTaiheUtils::GetPropertyDouble(env, rawfileObj, "offset", offset) ||
1163         !ImageTaiheUtils::GetPropertyDouble(env, rawfileObj, "length", length)) {
1164         ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "GetPropertyDouble failed");
1165         return make_holder<ImageSourceImpl, ImageSource>();
1166     }
1167     SourceOptions etsOpts = options.value_or(SourceOptions {});
1168     OHOS::Media::SourceOptions opts = ImageTaiheUtils::ParseSourceOptions(etsOpts);
1169 
1170     uint32_t errorCode = OHOS::Media::ERR_MEDIA_INVALID_VALUE;
1171     int32_t fileSize = static_cast<int32_t>(offset) + static_cast<int32_t>(length);
1172     std::shared_ptr<OHOS::Media::ImageSource> imageSource = OHOS::Media::ImageSource::CreateImageSource(
1173         static_cast<int32_t>(fd), static_cast<int32_t>(offset), fileSize, opts, errorCode);
1174     if (imageSource == nullptr) {
1175         ImageTaiheUtils::ThrowExceptionError("CreateImageSourceByRawFileDescriptorOption error");
1176         return make_holder<ImageSourceImpl, ImageSource>();
1177     }
1178     {
1179         std::lock_guard<std::mutex> lock(imageSourceCrossThreadMutex_);
1180         ImageSourceImpl::filePath_ = "";
1181         ImageSourceImpl::fileDescriptor_ = INVALID_FD;
1182         ImageSourceImpl::fileBuffer_ = nullptr;
1183         ImageSourceImpl::fileBufferSize_ = NUM_0;
1184     }
1185     return make_holder<ImageSourceImpl, ImageSource>(imageSource);
1186 }
1187 } // namespace ANI::Image
1188 
1189 TH_EXPORT_CPP_API_CreateImageSourceByUri(CreateImageSourceByUri);
1190 TH_EXPORT_CPP_API_CreateImageSourceByUriOption(CreateImageSourceByUriOption);
1191 TH_EXPORT_CPP_API_CreateImageSourceByFd(CreateImageSourceByFd);
1192 TH_EXPORT_CPP_API_CreateImageSourceByFdOption(CreateImageSourceByFdOption);
1193 TH_EXPORT_CPP_API_CreateImageSourceByArrayBuffer(CreateImageSourceByArrayBuffer);
1194 TH_EXPORT_CPP_API_CreateImageSourceByArrayBufferOption(CreateImageSourceByArrayBufferOption);
1195 TH_EXPORT_CPP_API_CreateImageSourceByRawFileDescriptorOption(CreateImageSourceByRawFileDescriptorOption);