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 ®ion = 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);