• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 "ext_decoder.h"
17 
18 #include <algorithm>
19 #include <map>
20 
21 #include "ext_pixel_convert.h"
22 #include "image_log.h"
23 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
24 #include "hisysevent.h"
25 #endif
26 #include "image_system_properties.h"
27 #include "image_utils.h"
28 #include "media_errors.h"
29 #include "securec.h"
30 #include "string_ex.h"
31 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
32 #include "surface_buffer.h"
33 #endif
34 
35 #undef LOG_DOMAIN
36 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
37 
38 #undef LOG_TAG
39 #define LOG_TAG "ExtDecoder"
40 
41 namespace {
42     constexpr static int32_t ZERO = 0;
43     constexpr static int32_t NUM_3 = 3;
44     constexpr static int32_t NUM_4 = 4;
45     constexpr static int32_t OFFSET = 1;
46     constexpr static size_t SIZE_ZERO = 0;
47     constexpr static uint32_t DEFAULT_SAMPLE_SIZE = 1;
48     constexpr static uint32_t NO_EXIF_TAG = 1;
49     constexpr static uint32_t OFFSET_0 = 0;
50     constexpr static uint32_t OFFSET_1 = 1;
51     constexpr static uint32_t OFFSET_2 = 2;
52     constexpr static uint32_t OFFSET_3 = 3;
53     constexpr static uint32_t OFFSET_5 = 5;
54     constexpr static uint32_t SHIFT_BITS_8 = 8;
55     constexpr static uint32_t SHIFT_BITS_16 = 16;
56     constexpr static uint32_t SHIFT_BITS_24 = 24;
57     constexpr static uint32_t DESC_SIGNATURE = 0x64657363;
58     constexpr static size_t SIZE_1 = 1;
59     constexpr static size_t SIZE_4 = 4;
60     constexpr static int HARDWARE_MIN_DIM = 1024;
61     constexpr static int HARDWARE_MAX_DIM = 8192;
62     constexpr static float HALF = 0.5;
63     constexpr static float QUARTER = 0.25;
64     constexpr static float ONE_EIGHTH = 0.125;
65     constexpr static uint64_t ICC_HEADER_SIZE = 132;
66 }
67 
68 namespace OHOS {
69 namespace ImagePlugin {
70 using namespace Media;
71 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
72 using namespace OHOS::HDI::Base;
73 #endif
74 using namespace std;
75 const static string DEFAULT_EXIF_VALUE = "default_exif_value";
76 const static string CODEC_INITED_KEY = "CodecInited";
77 const static string ENCODED_FORMAT_KEY = "EncodedFormat";
78 const static string SUPPORT_SCALE_KEY = "SupportScale";
79 const static string SUPPORT_CROP_KEY = "SupportCrop";
80 const static string EXT_SHAREMEM_NAME = "EXT RawData";
81 const static string TAG_ORIENTATION_STRING = "Orientation";
82 const static string TAG_ORIENTATION_INT = "OrientationInt";
83 const static string GIF_IMAGE_DELAY_TIME = "GIFDelayTime";
84 const static std::string HW_MNOTE_TAG_HEADER = "HwMnote";
85 const static std::string HW_MNOTE_CAPTURE_MODE = "HwMnoteCaptureMode";
86 const static std::string HW_MNOTE_PHYSICAL_APERTURE = "HwMnotePhysicalAperture";
87 const static std::string HW_MNOTE_TAG_ROLL_ANGLE = "HwMnoteRollAngle";
88 const static std::string HW_MNOTE_TAG_PITCH_ANGLE = "HwMnotePitchAngle";
89 const static std::string HW_MNOTE_TAG_SCENE_FOOD_CONF = "HwMnoteSceneFoodConf";
90 const static std::string HW_MNOTE_TAG_SCENE_STAGE_CONF = "HwMnoteSceneStageConf";
91 const static std::string HW_MNOTE_TAG_SCENE_BLUE_SKY_CONF = "HwMnoteSceneBlueSkyConf";
92 const static std::string HW_MNOTE_TAG_SCENE_GREEN_PLANT_CONF = "HwMnoteSceneGreenPlantConf";
93 const static std::string HW_MNOTE_TAG_SCENE_BEACH_CONF = "HwMnoteSceneBeachConf";
94 const static std::string HW_MNOTE_TAG_SCENE_SNOW_CONF = "HwMnoteSceneSnowConf";
95 const static std::string HW_MNOTE_TAG_SCENE_SUNSET_CONF = "HwMnoteSceneSunsetConf";
96 const static std::string HW_MNOTE_TAG_SCENE_FLOWERS_CONF = "HwMnoteSceneFlowersConf";
97 const static std::string HW_MNOTE_TAG_SCENE_NIGHT_CONF = "HwMnoteSceneNightConf";
98 const static std::string HW_MNOTE_TAG_SCENE_TEXT_CONF = "HwMnoteSceneTextConf";
99 const static std::string HW_MNOTE_TAG_FACE_COUNT = "HwMnoteFaceCount";
100 const static std::string HW_MNOTE_TAG_FOCUS_MODE = "HwMnoteFocusMode";
101 // SUCCESS is existed in both OHOS::HiviewDFX and OHOS::Media
102 #define SUCCESS OHOS::Media::SUCCESS
103 const static std::string DEFAULT_PACKAGE_NAME = "entry";
104 const static std::string DEFAULT_VERSION_ID = "1";
105 const static std::string UNKNOWN_IMAGE = "unknown";
106 
107 struct ColorTypeOutput {
108     PlPixelFormat outFormat;
109     SkColorType skFormat;
110 };
111 
112 static const map<PlPixelFormat, ColorTypeOutput> COLOR_TYPE_MAP = {
113     { PlPixelFormat::UNKNOWN, { PlPixelFormat::RGBA_8888, kRGBA_8888_SkColorType } },
114     { PlPixelFormat::RGBA_8888, { PlPixelFormat::RGBA_8888, kRGBA_8888_SkColorType } },
115     { PlPixelFormat::BGRA_8888, { PlPixelFormat::BGRA_8888, kBGRA_8888_SkColorType } },
116     { PlPixelFormat::ALPHA_8, { PlPixelFormat::ALPHA_8, kAlpha_8_SkColorType } },
117     { PlPixelFormat::RGB_565, { PlPixelFormat::RGB_565, kRGB_565_SkColorType } },
118     { PlPixelFormat::RGB_888, { PlPixelFormat::RGB_888, kRGB_888x_SkColorType } },
119 };
120 
121 static const map<PlAlphaType, SkAlphaType> ALPHA_TYPE_MAP = {
122     { PlAlphaType::IMAGE_ALPHA_TYPE_OPAQUE, kOpaque_SkAlphaType },
123     { PlAlphaType::IMAGE_ALPHA_TYPE_PREMUL, kPremul_SkAlphaType },
124     { PlAlphaType::IMAGE_ALPHA_TYPE_UNPREMUL, kUnpremul_SkAlphaType },
125 };
126 
127 static const map<SkEncodedImageFormat, string> FORMAT_NAME = {
128     { SkEncodedImageFormat::kBMP, "image/bmp" },
129     { SkEncodedImageFormat::kGIF, "image/gif" },
130     { SkEncodedImageFormat::kICO, "image/png" },
131     { SkEncodedImageFormat::kJPEG, "image/jpeg" },
132     { SkEncodedImageFormat::kPNG, "image/png" },
133     { SkEncodedImageFormat::kWBMP, "image/bmp" },
134     { SkEncodedImageFormat::kWEBP, "image/webp" },
135     { SkEncodedImageFormat::kPKM, "" },
136     { SkEncodedImageFormat::kKTX, "" },
137     { SkEncodedImageFormat::kASTC, "" },
138     { SkEncodedImageFormat::kDNG, "" },
139     { SkEncodedImageFormat::kHEIF, "image/heif" },
140 };
141 
SetDecodeContextBuffer(DecodeContext & context,AllocatorType type,uint8_t * ptr,uint64_t count,void * fd)142 static void SetDecodeContextBuffer(DecodeContext &context,
143     AllocatorType type, uint8_t* ptr, uint64_t count, void* fd)
144 {
145     context.allocatorType = type;
146     context.freeFunc = nullptr;
147     context.pixelsBuffer.buffer = ptr;
148     context.pixelsBuffer.bufferSize = count;
149     context.pixelsBuffer.context = fd;
150 }
151 
ShareMemAlloc(DecodeContext & context,uint64_t count)152 static uint32_t ShareMemAlloc(DecodeContext &context, uint64_t count)
153 {
154 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
155     IMAGE_LOGE("Unsupport share mem alloc");
156     return ERR_IMAGE_DATA_UNSUPPORT;
157 #else
158     auto fd = make_unique<int32_t>();
159     *fd = AshmemCreate(EXT_SHAREMEM_NAME.c_str(), count);
160     if (*fd < 0) {
161         IMAGE_LOGE("AshmemCreate failed");
162         return ERR_SHAMEM_DATA_ABNORMAL;
163     }
164     int result = AshmemSetProt(*fd, PROT_READ | PROT_WRITE);
165     if (result < 0) {
166         ::close(*fd);
167         IMAGE_LOGE("AshmemSetProt failed");
168         return ERR_SHAMEM_DATA_ABNORMAL;
169     }
170     void* ptr = ::mmap(nullptr, count, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, ZERO);
171     if (ptr == MAP_FAILED) {
172         ::close(*fd);
173         IMAGE_LOGE("::mmap failed");
174         return ERR_SHAMEM_DATA_ABNORMAL;
175     }
176     SetDecodeContextBuffer(context,
177         AllocatorType::SHARE_MEM_ALLOC, static_cast<uint8_t*>(ptr), count, fd.release());
178     return SUCCESS;
179 #endif
180 }
181 
DmaMemAlloc(DecodeContext & context,uint64_t count,SkImageInfo & dstInfo)182 static uint32_t DmaMemAlloc(DecodeContext &context, uint64_t count, SkImageInfo &dstInfo)
183 {
184 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
185     IMAGE_LOGE("Unsupport dma mem alloc");
186     return ERR_IMAGE_DATA_UNSUPPORT;
187 #else
188     sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
189     BufferRequestConfig requestConfig = {
190         .width = dstInfo.width(),
191         .height = dstInfo.height(),
192         .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
193         .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // hardware decode only support rgba8888
194         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
195         .timeout = 0,
196         .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
197         .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
198     };
199     GSError ret = sb->Alloc(requestConfig);
200     if (ret != GSERROR_OK) {
201         IMAGE_LOGE("SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
202         return ERR_DMA_NOT_EXIST;
203     }
204     void* nativeBuffer = sb.GetRefPtr();
205     int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
206     if (err != OHOS::GSERROR_OK) {
207         IMAGE_LOGE("NativeBufferReference failed");
208         return ERR_DMA_DATA_ABNORMAL;
209     }
210 
211     SetDecodeContextBuffer(context,
212         AllocatorType::DMA_ALLOC, static_cast<uint8_t*>(sb->GetVirAddr()), count, nativeBuffer);
213     return SUCCESS;
214 #endif
215 }
216 
HeapMemAlloc(DecodeContext & context,uint64_t count)217 static uint32_t HeapMemAlloc(DecodeContext &context, uint64_t count)
218 {
219     if (count == 0 || count > PIXEL_MAP_MAX_RAM_SIZE) {
220         IMAGE_LOGE("HeapMemAlloc Invalid value of bufferSize");
221         return ERR_IMAGE_DATA_ABNORMAL;
222     }
223     auto out = static_cast<uint8_t *>(malloc(count));
224 #ifdef _WIN32
225     if (memset_s(out, ZERO, count) != EOK) {
226 #else
227     if (memset_s(out, count, ZERO, count) != EOK) {
228 #endif
229         IMAGE_LOGE("Decode failed, memset buffer failed");
230         free(out);
231         return ERR_IMAGE_DECODE_FAILED;
232     }
233     SetDecodeContextBuffer(context, AllocatorType::HEAP_ALLOC, out, count, nullptr);
234     return SUCCESS;
235 }
236 
237 ExtDecoder::ExtDecoder() : codec_(nullptr), frameCount_(ZERO)
238 {
239 }
240 
241 ExtDecoder::~ExtDecoder()
242 {
243     if (gifCache_ != nullptr) {
244         free(gifCache_);
245         gifCache_ = nullptr;
246     }
247 }
248 
249 void ExtDecoder::SetSource(InputDataStream &sourceStream)
250 {
251     stream_ = &sourceStream;
252     streamOff_ = sourceStream.Tell();
253     if (streamOff_ >= sourceStream.GetStreamSize()) {
254         streamOff_ = ZERO;
255     }
256 }
257 
258 void ExtDecoder::Reset()
259 {
260     stream_ = nullptr;
261     codec_ = nullptr;
262     dstInfo_.reset();
263     dstSubset_ = SkIRect::MakeEmpty();
264     info_.reset();
265 }
266 
267 static inline float Max(float a, float b)
268 {
269     return (a > b) ? a : b;
270 }
271 
272 bool ExtDecoder::GetScaledSize(int &dWidth, int &dHeight, float &scale)
273 {
274     if (info_.isEmpty() && !DecodeHeader()) {
275         IMAGE_LOGE("DecodeHeader failed in GetScaledSize!");
276         return false;
277     }
278     if (info_.isEmpty()) {
279         IMAGE_LOGE("empty image info in GetScaledSize!");
280         return false;
281     }
282     float finalScale = scale;
283     if (scale == ZERO) {
284         finalScale = Max(static_cast<float>(dWidth) / info_.width(),
285             static_cast<float>(dHeight) / info_.height());
286     }
287     auto scaledDimension = codec_->getScaledDimensions(finalScale);
288     dWidth = scaledDimension.width();
289     dHeight = scaledDimension.height();
290     scale = finalScale;
291     IMAGE_LOGD("IsSupportScaleOnDecode info [%{public}d x %{public}d]", info_.width(), info_.height());
292     IMAGE_LOGD("IsSupportScaleOnDecode [%{public}d x %{public}d]", dWidth, dHeight);
293     IMAGE_LOGD("IsSupportScaleOnDecode [%{public}f]", scale);
294     return true;
295 }
296 
297 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
298 bool ExtDecoder::GetHardwareScaledSize(int &dWidth, int &dHeight, float &scale) {
299     if (info_.isEmpty() && !DecodeHeader()) {
300         IMAGE_LOGE("DecodeHeader failed in GetHardwareScaledSize!");
301         return false;
302     }
303     if (info_.isEmpty()) {
304         IMAGE_LOGE("empty image info in GetHardwareScaledSize!");
305         return false;
306     }
307     float finalScale = scale;
308     int oriWidth = info_.width();
309     int oriHeight = info_.height();
310     if (scale == ZERO) {
311         finalScale = Max(static_cast<float>(dWidth) / oriWidth,
312                          static_cast<float>(dHeight) / oriHeight);
313     }
314     // calculate sample size and dst size for hardware decode
315     if (finalScale > HALF) {
316         sampleSize_ = 1;
317         dWidth = oriWidth;
318         dHeight = oriHeight;
319     } else if (finalScale > QUARTER) {
320         sampleSize_ = 2;
321         dWidth = oriWidth * HALF;
322         dHeight = oriHeight * HALF;
323     } else if (finalScale > ONE_EIGHTH) {
324         sampleSize_ = 4;
325         dWidth = oriWidth * QUARTER;
326         dHeight = oriHeight * QUARTER;
327     } else {
328         sampleSize_ = 8;
329         dWidth = oriWidth * ONE_EIGHTH;
330         dHeight = oriHeight * ONE_EIGHTH;
331     }
332     return true;
333 }
334 #endif
335 
336 bool ExtDecoder::IsSupportScaleOnDecode()
337 {
338     constexpr float HALF_SCALE = 0.5f;
339     int w = ZERO;
340     int h = ZERO;
341     float scale = HALF_SCALE;
342     return GetScaledSize(w, h, scale);
343 }
344 
345 bool ExtDecoder::IsSupportCropOnDecode()
346 {
347     if (info_.isEmpty() && !DecodeHeader()) {
348         return false;
349     }
350     SkIRect innerRect = info_.bounds().makeInset(OFFSET, OFFSET);
351     return IsSupportCropOnDecode(innerRect);
352 }
353 
354 bool ExtDecoder::IsSupportCropOnDecode(SkIRect &target)
355 {
356     if (info_.isEmpty() && !DecodeHeader()) {
357         return false;
358     }
359     SkIRect orgbounds = info_.bounds();
360     SkIRect source = target;
361     if (orgbounds.contains(target) && codec_->getValidSubset(&target)) {
362         return source == target;
363     }
364     return false;
365 }
366 
367 bool ExtDecoder::HasProperty(string key)
368 {
369     if (CODEC_INITED_KEY.compare(key) == ZERO) {
370         return CheckCodec();
371     } else if (ENCODED_FORMAT_KEY.compare(key) == ZERO) {
372         return true;
373     } else if (SUPPORT_SCALE_KEY.compare(key) == ZERO) {
374         return IsSupportScaleOnDecode();
375     } else if (SUPPORT_CROP_KEY.compare(key) == ZERO) {
376         return IsSupportCropOnDecode();
377     }
378     return false;
379 }
380 
381 uint32_t ExtDecoder::GetImageSize(uint32_t index, PlSize &size)
382 {
383     IMAGE_LOGD("GetImageSize index:%{public}u", index);
384     if (!CheckIndexValied(index)) {
385         IMAGE_LOGE("Invalid index:%{public}u, range:%{public}d", index, frameCount_);
386         return ERR_IMAGE_INVALID_PARAMETER;
387     }
388     IMAGE_LOGD("GetImageSize index:%{public}u, range:%{public}d", index, frameCount_);
389     // Info has been get in check process, or empty on get failed.
390     if (info_.isEmpty()) {
391         IMAGE_LOGE("GetImageSize failed, decode header failed.");
392         return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
393     }
394     size.width = info_.width();
395     size.height = info_.height();
396     return SUCCESS;
397 }
398 
399 static inline bool IsLowDownScale(const PlSize &size, SkImageInfo &info)
400 {
401     return size.width < static_cast<uint32_t>(info.width()) &&
402         size.height < static_cast<uint32_t>(info.height());
403 }
404 
405 static inline bool IsValidCrop(const PlRect &crop, SkImageInfo &info, SkIRect &out)
406 {
407     out = SkIRect::MakeXYWH(crop.left, crop.top, crop.width, crop.height);
408     if (out.fLeft < ZERO || out.fTop < ZERO) {
409         return false;
410     }
411     if (out.fRight > info.width()) {
412         out.fRight = info.width();
413     }
414     if (out.fBottom > info.height()) {
415         out.fBottom = info.height();
416     }
417     return true;
418 }
419 
420 static sk_sp<SkColorSpace> getDesiredColorSpace(SkImageInfo &srcInfo, const PixelDecodeOptions &opts)
421 {
422     if (opts.plDesiredColorSpace == nullptr) {
423         return srcInfo.refColorSpace();
424     }
425     return opts.plDesiredColorSpace->ToSkColorSpace();
426 }
427 
428 uint32_t ExtDecoder::CheckDecodeOptions(uint32_t index, const PixelDecodeOptions &opts)
429 {
430     if (ImageUtils::CheckMulOverflow(dstInfo_.width(), dstInfo_.height(), dstInfo_.bytesPerPixel())) {
431         IMAGE_LOGE("SetDecodeOptions failed, width:%{public}d, height:%{public}d is too large",
432                      dstInfo_.width(), dstInfo_.height());
433         return ERR_IMAGE_INVALID_PARAMETER;
434     }
435     if (!IsValidCrop(opts.CropRect, info_, dstSubset_)) {
436         IMAGE_LOGE("Invalid crop rect xy [%{public}d x %{public}d], wh [%{public}d x %{public}d]",
437             dstSubset_.left(), dstSubset_.top(), dstSubset_.width(), dstSubset_.height());
438         return ERR_IMAGE_INVALID_PARAMETER;
439     }
440 
441     dstOptions_.fFrameIndex = index;
442 #ifdef IMAGE_COLORSPACE_FLAG
443     dstColorSpace_ = opts.plDesiredColorSpace;
444 #endif
445     if (IsSupportCropOnDecode(dstSubset_)) {
446         dstOptions_.fSubset = &dstSubset_;
447     }
448     return SUCCESS;
449 }
450 
451 uint32_t ExtDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
452 {
453     if (!CheckIndexValied(index)) {
454         IMAGE_LOGE("Invalid index:%{public}u, range:%{public}d", index, frameCount_);
455         return ERR_IMAGE_INVALID_PARAMETER;
456     }
457     if (opts.sampleSize != DEFAULT_SAMPLE_SIZE) {
458         IMAGE_LOGE("Do not support sample size now!");
459         return ERR_IMAGE_INVALID_PARAMETER;
460     }
461     auto desireColor = ConvertToColorType(opts.desiredPixelFormat, info.pixelFormat);
462     auto desireAlpha = ConvertToAlphaType(opts.desireAlphaType, info.alphaType);
463     // SK only support low down scale
464     int dstWidth = opts.desiredSize.width;
465     int dstHeight = opts.desiredSize.height;
466     float scale = ZERO;
467 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
468     if (IsSupportHardwareDecode()) {
469         // get dstInfo for hardware decode
470         if (IsLowDownScale(opts.desiredSize, info_) && GetHardwareScaledSize(dstWidth, dstHeight, scale)) {
471             hwDstInfo_ = SkImageInfo::Make(dstWidth, dstHeight, desireColor, desireAlpha, info_.refColorSpace());
472         } else {
473             hwDstInfo_ = SkImageInfo::Make(info_.width(), info_.height(),
474                                            desireColor, desireAlpha, info_.refColorSpace());
475         }
476         // restore dstWidth and dstHeight
477         dstWidth = opts.desiredSize.width;
478         dstHeight = opts.desiredSize.height;
479     }
480 #endif
481     if (IsLowDownScale(opts.desiredSize, info_) && GetScaledSize(dstWidth, dstHeight, scale)) {
482         dstInfo_ = SkImageInfo::Make(dstWidth, dstHeight, desireColor, desireAlpha,
483             getDesiredColorSpace(info_, opts));
484     } else {
485         dstInfo_ = SkImageInfo::Make(info_.width(), info_.height(),
486             desireColor, desireAlpha, getDesiredColorSpace(info_, opts));
487     }
488     auto resCode = CheckDecodeOptions(index, opts);
489     if (resCode != SUCCESS) {
490         return resCode;
491     }
492 
493     info.size.width = dstInfo_.width();
494     info.size.height = dstInfo_.height();
495     return SUCCESS;
496 }
497 
498 uint32_t ExtDecoder::SetContextPixelsBuffer(uint64_t byteCount, DecodeContext &context)
499 {
500     if (byteCount == ZERO) {
501         return ERR_IMAGE_INVALID_PARAMETER;
502     }
503     if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
504         return ShareMemAlloc(context, byteCount);
505     } else if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
506         return DmaMemAlloc(context, byteCount, dstInfo_);
507     }
508     return HeapMemAlloc(context, byteCount);
509 }
510 
511 static void DebugInfo(SkImageInfo &info, SkImageInfo &dstInfo, SkCodec::Options &opts)
512 {
513     IMAGE_LOGD("Decode source info: WH[%{public}d x %{public}d], A %{public}d, C %{public}d.",
514         info.width(), info.height(),
515         info.alphaType(), info.colorType());
516     IMAGE_LOGD("Decode dst info: WH[%{public}d x %{public}d], A %{public}d, C %{public}d.",
517         dstInfo.width(), dstInfo.height(), dstInfo.alphaType(), dstInfo.colorType());
518     if (opts.fSubset != nullptr) {
519         IMAGE_LOGD("Decode dstOpts sub: (%{public}d, %{public}d), WH[%{public}d x %{public}d]",
520             opts.fSubset->fLeft, opts.fSubset->fTop,
521             opts.fSubset->width(), opts.fSubset->height());
522     }
523 }
524 
525 static uint32_t RGBxToRGB(uint8_t* srcBuffer, size_t srsSize,
526     uint8_t* dstBuffer, size_t dstSize, size_t pixelCount)
527 {
528     ExtPixels src = {srcBuffer, srsSize, pixelCount};
529     ExtPixels dst = {dstBuffer, dstSize, pixelCount};
530     auto res = ExtPixelConvert::RGBxToRGB(src, dst);
531     if (res != SUCCESS) {
532         IMAGE_LOGE("RGBxToRGB failed %{public}d", res);
533     }
534     return res;
535 }
536 
537 uint32_t ExtDecoder::PreDecodeCheck(uint32_t index)
538 {
539     if (!CheckIndexValied(index)) {
540         IMAGE_LOGE("Decode failed, invalid index:%{public}u, range:%{public}d", index, frameCount_);
541         return ERR_IMAGE_INVALID_PARAMETER;
542     }
543     if (codec_ == nullptr) {
544         IMAGE_LOGE("Decode failed, codec is null");
545         return ERR_IMAGE_DECODE_FAILED;
546     }
547     if (dstInfo_.isEmpty()) {
548         IMAGE_LOGE("Decode failed, dst info is empty");
549         return ERR_IMAGE_DECODE_FAILED;
550     }
551         return SUCCESS;
552 }
553 
554 bool ExtDecoder::ResetCodec()
555 {
556     codec_ = nullptr;
557     stream_->Seek(streamOff_);
558     return ExtDecoder::CheckCodec();
559 }
560 
561 #ifdef JPEG_HW_DECODE_ENABLE
562 uint32_t ExtDecoder::DoHardWareDecode(DecodeContext &context)
563 {
564     if (HardWareDecode(context) == SUCCESS) {
565         return SUCCESS;
566     }
567     return ERROR;
568 }
569 #endif
570 
571 uint32_t ExtDecoder::Decode(uint32_t index, DecodeContext &context)
572 {
573 #ifdef JPEG_HW_DECODE_ENABLE
574     if (IsSupportHardwareDecode() && DoHardWareDecode(context) == SUCCESS) {
575         return SUCCESS;
576     }
577 #endif
578     uint32_t res = PreDecodeCheck(index);
579     if (res != SUCCESS) {
580         return res;
581     }
582     uint64_t byteCount = static_cast<uint64_t>(dstInfo_.computeMinByteSize());
583     uint8_t *dstBuffer = nullptr;
584     if (dstInfo_.colorType() == SkColorType::kRGB_888x_SkColorType) {
585         auto tmpBuffer = make_unique<uint8_t[]>(byteCount);
586         dstBuffer = tmpBuffer.get();
587         byteCount = byteCount / NUM_4 * NUM_3;
588     }
589     if (context.pixelsBuffer.buffer == nullptr) {
590         res = SetContextPixelsBuffer(byteCount, context);
591         if (res != SUCCESS) {
592             return res;
593         }
594         if (dstBuffer == nullptr) {
595             dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
596         }
597     }
598     dstOptions_.fFrameIndex = index;
599     DebugInfo(info_, dstInfo_, dstOptions_);
600     uint64_t rowStride = dstInfo_.minRowBytes64();
601 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
602     if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
603         SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*> (context.pixelsBuffer.context);
604         rowStride = sbBuffer->GetStride();
605     }
606 #endif
607     SkEncodedImageFormat skEncodeFormat = codec_->getEncodedFormat();
608     ReportImageType(skEncodeFormat);
609     IMAGE_LOGD("decode format %{public}d", skEncodeFormat);
610     if (skEncodeFormat == SkEncodedImageFormat::kGIF || skEncodeFormat == SkEncodedImageFormat::kWEBP) {
611         return GifDecode(index, context, rowStride);
612     }
613     SkCodec::Result ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_);
614     if (ret != SkCodec::kSuccess && ResetCodec()) {
615         // Try again
616         ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_);
617     }
618     if (ret != SkCodec::kSuccess) {
619         IMAGE_LOGE("Decode failed, get pixels failed, ret=%{public}d", ret);
620         return ERR_IMAGE_DECODE_ABNORMAL;
621     }
622     if (dstInfo_.colorType() == SkColorType::kRGB_888x_SkColorType) {
623         return RGBxToRGB(dstBuffer, dstInfo_.computeMinByteSize(), static_cast<uint8_t*>(context.pixelsBuffer.buffer),
624             byteCount, dstInfo_.width() * dstInfo_.height());
625     }
626     return SUCCESS;
627 }
628 
629 static std::string GetFormatStr(SkEncodedImageFormat format)
630 {
631     switch (format) {
632         case SkEncodedImageFormat::kBMP:
633             return "bmp";
634         case SkEncodedImageFormat::kGIF:
635             return "gif";
636         case SkEncodedImageFormat::kICO:
637             return "ico";
638         case SkEncodedImageFormat::kJPEG:
639             return "jpeg";
640         case SkEncodedImageFormat::kPNG:
641             return "png";
642         case SkEncodedImageFormat::kWBMP:
643             return "wbmp";
644         case SkEncodedImageFormat::kWEBP:
645             return "webp";
646         case SkEncodedImageFormat::kPKM:
647             return "pkm";
648         case SkEncodedImageFormat::kKTX:
649             return "ktx";
650         case SkEncodedImageFormat::kASTC:
651             return "astc";
652         case SkEncodedImageFormat::kDNG:
653             return "dng";
654         case SkEncodedImageFormat::kHEIF:
655             return "heif";
656         case SkEncodedImageFormat::kAVIF:
657             return "avif";
658         default:
659             return UNKNOWN_IMAGE;
660     }
661 }
662 
663 void ExtDecoder::ReportImageType(SkEncodedImageFormat skEncodeFormat)
664 {
665     IMAGE_LOGD("ExtDecoder::ReportImageType format %{public}d start", skEncodeFormat);
666     static constexpr char IMAGE_FWK_UE[] = "IMAGE_FWK_UE";
667 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
668     int32_t ret = HiSysEventWrite(
669             IMAGE_FWK_UE,
670             "DECODED_IMAGE_TYPE_STATISTICS",
671             HiviewDFX::HiSysEvent::EventType::STATISTIC,
672             "PNAMEID", DEFAULT_PACKAGE_NAME,
673             "PVERSIONID", DEFAULT_VERSION_ID,
674             "IMAGE_TYPE", GetFormatStr(skEncodeFormat)
675     );
676     if (SUCCESS != ret) {
677         IMAGE_LOGD("ExtDecoder::ReportImageType failed, ret = %{public}d", ret);
678         return;
679     }
680 #endif
681     IMAGE_LOGD("ExtDecoder::ReportImageType format %{public}d success", skEncodeFormat);
682 }
683 #ifdef JPEG_HW_DECODE_ENABLE
684 uint32_t ExtDecoder::AllocOutputBuffer(DecodeContext &context)
685 {
686     uint64_t byteCount = static_cast<uint64_t>(dstInfo_.height()) * dstInfo_.width() * dstInfo_.bytesPerPixel();
687     uint32_t ret = DmaMemAlloc(context, byteCount, info_);
688     if (ret != SUCCESS) {
689         IMAGE_LOGE("Alloc OutputBuffer failed, ret=%{public}d", ret);
690         return ERR_IMAGE_DECODE_ABNORMAL;
691     }
692     BufferHandle *handle = (static_cast<SurfaceBuffer*>(context.pixelsBuffer.context))->GetBufferHandle();
693     if (outputColorFmt_ == PIXEL_FMT_RGBA_8888) {
694         outputBufferSize_.width = static_cast<uint32_t>(handle->stride) / NUM_4;
695     } else {
696         outputBufferSize_.width = static_cast<uint32_t>(handle->stride);
697     }
698     outputBufferSize_.height = static_cast<uint32_t>(handle->height);
699     outputBuffer_.buffer = new NativeBuffer(handle);
700     outputBuffer_.fenceFd = -1;
701     return SUCCESS;
702 }
703 
704 bool CheckContext(const SkImageInfo &dstInfo)
705 {
706     if (dstInfo.colorType() != kRGBA_8888_SkColorType) {
707         IMAGE_LOGE("hardware decode only support rgba_8888 format");
708         return false;
709     }
710     return true;
711 }
712 
713 void ExtDecoder::ReleaseOutputBuffer(DecodeContext &context, Media::AllocatorType allocatorType)
714 {
715     ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer*>(context.pixelsBuffer.context));
716     context.pixelsBuffer.buffer = nullptr;
717     context.allocatorType = allocatorType;
718     context.freeFunc = nullptr;
719     context.pixelsBuffer.bufferSize = 0;
720     context.pixelsBuffer.context = nullptr;
721     outputBuffer_.buffer = nullptr;
722 }
723 
724 uint32_t ExtDecoder::HardWareDecode(DecodeContext &context)
725 {
726     // check if the hwDstInfo is equal to the dstInfo
727     if (hwDstInfo_.width() != dstInfo_.width() || hwDstInfo_.height() != dstInfo_.height()) {
728         IMAGE_LOGI("hwDstInfo(%{public}d, %{public}d) != dstInfo(%{public}d, %{public}d)",
729             hwDstInfo_.width(), hwDstInfo_.height(), dstInfo_.width(), dstInfo_.height());
730         return ERROR;
731     }
732     JpegHardwareDecoder hwDecoder;
733     orgImgSize_.width = info_.width();
734     orgImgSize_.height = info_.height();
735 
736     if (!CheckContext(dstInfo_)) {
737         return ERROR;
738     }
739 
740     Media::AllocatorType tmpAllocatorType = context.allocatorType;
741     uint32_t ret = AllocOutputBuffer(context);
742     if (ret != SUCCESS) {
743         IMAGE_LOGE("Decode failed, Alloc OutputBuffer failed, ret=%{public}d", ret);
744         return ERR_IMAGE_DECODE_ABNORMAL;
745     }
746     ret = hwDecoder.Decode(codec_.get(), stream_, orgImgSize_, sampleSize_, outputBuffer_);
747     if (ret != SUCCESS) {
748         IMAGE_LOGE("failed to do jpeg hardware decode, err=%{public}d", ret);
749         ReleaseOutputBuffer(context, tmpAllocatorType);
750         return ERR_IMAGE_DECODE_ABNORMAL;
751     }
752     return SUCCESS;
753 }
754 #endif
755 
756 static uint32_t handleGifCache(uint8_t* src, uint8_t* dst, SkImageInfo& info, const uint64_t rowStride) {
757     if (src == nullptr || dst == nullptr) {
758         return ERR_IMAGE_DECODE_ABNORMAL;
759     }
760     int dstHeight = info.height();
761     uint8_t* srcRow = src;
762     uint8_t* dstRow = dst;
763     for (int i = 0; i < dstHeight; i++) {
764         errno_t err = memcpy_s(dstRow, rowStride, srcRow, rowStride);
765         if (err != EOK) {
766             IMAGE_LOGE("handle gif memcpy failed. errno:%{public}d", err);
767             return ERR_IMAGE_DECODE_ABNORMAL;
768         }
769         srcRow += rowStride;
770         dstRow += rowStride;
771     }
772     return SUCCESS;
773 }
774 
775 uint32_t ExtDecoder::GifDecode(uint32_t index, DecodeContext &context, const uint64_t rowStride)
776 {
777     SkCodec::FrameInfo curInfo {};
778     codec_->getFrameInfo(index, &curInfo);
779     if (index == 0 || gifCache_ == nullptr) {
780         dstOptions_.fPriorFrame = SkCodec::kNoFrame;
781     } else {
782         int preIndex = index - 1;
783         SkCodec::FrameInfo preInfo {};
784         codec_->getFrameInfo(preIndex, &preInfo);
785         if (preInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
786             dstOptions_.fPriorFrame = gifCacheIndex_;
787         } else {
788             dstOptions_.fPriorFrame = gifCacheIndex_ == preIndex ? preIndex : SkCodec::kNoFrame;
789         }
790     }
791     uint8_t* dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
792     if (curInfo.fDisposalMethod != SkCodecAnimation::DisposalMethod::kRestorePrevious) {
793         if (gifCache_ == nullptr) {
794             int dstHeight = dstInfo_.height();
795             uint64_t byteCount = rowStride * dstHeight;
796             gifCache_ = static_cast<uint8_t *>(calloc(byteCount, 1));
797         }
798         dstBuffer = gifCache_;
799     } else if (gifCache_ != nullptr) {
800         handleGifCache(gifCache_, dstBuffer, dstInfo_, rowStride);
801     }
802     SkCodec::Result ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_);
803     if (ret != SkCodec::kSuccess && ResetCodec()) {
804         // Try again
805         ret = codec_->getPixels(dstInfo_, dstBuffer, rowStride, &dstOptions_);
806     }
807     if (ret != SkCodec::kSuccess) {
808         IMAGE_LOGE("Gif decode failed, get pixels failed, ret=%{public}d", ret);
809         return ERR_IMAGE_DECODE_ABNORMAL;
810     }
811     if (curInfo.fDisposalMethod != SkCodecAnimation::DisposalMethod::kRestorePrevious) {
812         gifCacheIndex_ = index;
813         uint8_t* dst = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
814         return handleGifCache(dstBuffer, dst, dstInfo_, rowStride);
815     }
816     return SUCCESS;
817 }
818 
819 uint32_t ExtDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context)
820 {
821     // currently not support increment decode
822     return ERR_IMAGE_DATA_UNSUPPORT;
823 }
824 
825 bool ExtDecoder::CheckCodec()
826 {
827     if (codec_ != nullptr) {
828         return true;
829     } else if (stream_ == nullptr) {
830         IMAGE_LOGE("create codec: input stream is nullptr.");
831         return false;
832     } else if (stream_->GetStreamSize() == SIZE_ZERO) {
833         IMAGE_LOGE("create codec: input stream size is zero.");
834         return false;
835     }
836     codec_ = SkCodec::MakeFromStream(make_unique<ExtStream>(stream_));
837     if (codec_ == nullptr) {
838         IMAGE_LOGE("create codec from stream failed");
839         return false;
840     }
841     return codec_ != nullptr;
842 }
843 
844 bool ExtDecoder::DecodeHeader()
845 {
846     if (!CheckCodec()) {
847         IMAGE_LOGE("Check codec failed");
848         return false;
849     }
850     info_ = codec_->getInfo();
851     frameCount_ = codec_->getFrameCount();
852     IMAGE_LOGD("DecodeHeader: get frame count %{public}d.", frameCount_);
853     return true;
854 }
855 
856 bool ExtDecoder::CheckIndexValied(uint32_t index)
857 {
858     if (frameCount_ == ZERO && !DecodeHeader()) {
859         return false;
860     }
861     return static_cast<int32_t>(index) >= ZERO && static_cast<int32_t>(index) < frameCount_;
862 }
863 
864 static uint32_t GetFormatName(SkEncodedImageFormat format, std::string &name)
865 {
866     auto formatNameIter = FORMAT_NAME.find(format);
867     if (formatNameIter != FORMAT_NAME.end() && !formatNameIter->second.empty()) {
868         name = formatNameIter->second;
869         IMAGE_LOGD("GetFormatName: get encoded format name (%{public}d)=>[%{public}s].",
870             format, name.c_str());
871         return SUCCESS;
872     }
873     IMAGE_LOGE("GetFormatName: get encoded format name failed %{public}d.", format);
874     return ERR_IMAGE_DATA_UNSUPPORT;
875 }
876 
877 bool ExtDecoder::ConvertInfoToAlphaType(SkAlphaType &alphaType, PlAlphaType &outputType)
878 {
879     if (info_.isEmpty()) {
880         return false;
881     }
882     alphaType = info_.alphaType();
883     auto findItem = std::find_if(ALPHA_TYPE_MAP.begin(), ALPHA_TYPE_MAP.end(),
884         [alphaType](const map<PlAlphaType, SkAlphaType>::value_type item) {
885         return item.second == alphaType;
886     });
887     if (findItem == ALPHA_TYPE_MAP.end()) {
888         return false;
889     }
890     outputType = findItem->first;
891     alphaType = findItem->second;
892     return true;
893 }
894 
895 bool ExtDecoder::ConvertInfoToColorType(SkColorType &format, PlPixelFormat &outputFormat)
896 {
897     if (info_.isEmpty()) {
898         return false;
899     }
900     auto colorType = info_.colorType();
901     auto findItem = std::find_if(COLOR_TYPE_MAP.begin(), COLOR_TYPE_MAP.end(),
902         [colorType](const map<PlPixelFormat, ColorTypeOutput>::value_type item) {
903         return item.second.skFormat == colorType;
904     });
905     if (findItem == COLOR_TYPE_MAP.end()) {
906         return false;
907     }
908     format = findItem->second.skFormat;
909     outputFormat = findItem->second.outFormat;
910     return true;
911 }
912 
913 SkAlphaType ExtDecoder::ConvertToAlphaType(PlAlphaType desiredType, PlAlphaType &outputType)
914 {
915     if (desiredType != PlAlphaType::IMAGE_ALPHA_TYPE_UNKNOWN) {
916         auto alphaType = ALPHA_TYPE_MAP.find(desiredType);
917         if (alphaType != ALPHA_TYPE_MAP.end()) {
918             outputType = alphaType->first;
919             return alphaType->second;
920         }
921     }
922     IMAGE_LOGD("Unknown alpha type:%{public}d", desiredType);
923     SkAlphaType res;
924     if (ConvertInfoToAlphaType(res, outputType)) {
925         IMAGE_LOGD("Using alpha type:%{public}d", outputType);
926         return res;
927     }
928     IMAGE_LOGD("Using default alpha type:%{public}d", PlAlphaType::IMAGE_ALPHA_TYPE_PREMUL);
929     outputType = PlAlphaType::IMAGE_ALPHA_TYPE_PREMUL;
930     return SkAlphaType::kPremul_SkAlphaType;
931 }
932 
933 SkColorType ExtDecoder::ConvertToColorType(PlPixelFormat format, PlPixelFormat &outputFormat)
934 {
935     if (format != PlPixelFormat::UNKNOWN) {
936         auto colorType = COLOR_TYPE_MAP.find(format);
937         if (colorType != COLOR_TYPE_MAP.end()) {
938             outputFormat = colorType->second.outFormat;
939             return colorType->second.skFormat;
940         }
941     }
942     IMAGE_LOGD("Unknown pixel format:%{public}d", format);
943     SkColorType res;
944     if (ConvertInfoToColorType(res, outputFormat)) {
945         IMAGE_LOGD("Using pixel format:%{public}d", outputFormat);
946         return res;
947     }
948     IMAGE_LOGD("Using default pixel format:%{public}d", PlPixelFormat::RGBA_8888);
949     outputFormat = PlPixelFormat::RGBA_8888;
950     return kRGBA_8888_SkColorType;
951 }
952 
953 #ifdef IMAGE_COLORSPACE_FLAG
954 static uint32_t u8ToU32(const uint8_t* p)
955 {
956     return (p[OFFSET_0] << SHIFT_BITS_24) | (p[OFFSET_1] << SHIFT_BITS_16) |
957         (p[OFFSET_2] << SHIFT_BITS_8) | p[OFFSET_3];
958 }
959 
960 struct ICCTag {
961     uint8_t signature[SIZE_4];
962     uint8_t offset[SIZE_4];
963     uint8_t size[SIZE_4];
964 };
965 
966 struct ColorSpaceNameEnum {
967     std::string desc;
968     OHOS::ColorManager::ColorSpaceName name;
969 };
970 
971 static std::vector<ColorSpaceNameEnum> sColorSpaceNamedMap = {
972     {"Display P3", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
973     {"sRGB EOTF with DCI-P3 Color Gamut", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
974     {"DCI-P3 D65 Gamut with sRGB Transfer", OHOS::ColorManager::ColorSpaceName::DISPLAY_P3},
975     {"Adobe RGB (1998)", OHOS::ColorManager::ColorSpaceName::ADOBE_RGB},
976     {"DCI P3", OHOS::ColorManager::ColorSpaceName::DCI_P3},
977     {"sRGB", OHOS::ColorManager::ColorSpaceName::SRGB}
978     /*{"BT.2020", OHOS::ColorManager::ColorSpaceName::BT2020}*/
979 };
980 
981 static bool MatchColorSpaceName(const uint8_t* buf, uint32_t size, OHOS::ColorManager::ColorSpaceName &name)
982 {
983     if (buf == nullptr || size <= OFFSET_5) {
984         return false;
985     }
986     std::vector<char> desc;
987     // We need skip desc type
988     for (uint32_t i = OFFSET_5; i < size; i++) {
989         if (buf[i] != '\0') {
990             desc.push_back(buf[i]);
991         }
992     }
993     if (desc.size() <= SIZE_1) {
994         IMAGE_LOGI("empty buffer");
995         return false;
996     }
997     std::string descText(desc.begin() + OFFSET_1, desc.end());
998     for (auto nameEnum : sColorSpaceNamedMap) {
999         if (descText.find(nameEnum.desc) == std::string::npos) {
1000             continue;
1001         }
1002         name = nameEnum.name;
1003         return true;
1004     }
1005     IMAGE_LOGE("Failed to match desc [%{public}s]", descText.c_str());
1006     return false;
1007 }
1008 
1009 static bool GetColorSpaceName(const skcms_ICCProfile* profile, OHOS::ColorManager::ColorSpaceName &name)
1010 {
1011     if (profile == nullptr || profile->buffer == nullptr) {
1012         IMAGE_LOGD("profile is nullptr");
1013         return false;
1014     }
1015     auto tags = reinterpret_cast<const ICCTag*>(profile->buffer + ICC_HEADER_SIZE);
1016     for (uint32_t i = SIZE_ZERO; i < profile->tag_count; i++) {
1017         auto signature = u8ToU32(tags[i].signature);
1018         if (signature != DESC_SIGNATURE) {
1019             continue;
1020         }
1021         auto size = u8ToU32(tags[i].size);
1022         auto offset = u8ToU32(tags[i].offset);
1023         if (size == SIZE_ZERO || offset >= profile->size) {
1024             continue;
1025         }
1026         auto buffer = u8ToU32(tags[i].offset) + profile->buffer;
1027         if (MatchColorSpaceName(buffer, size, name)) {
1028             return true;
1029         }
1030     }
1031     return false;
1032 }
1033 
1034 OHOS::ColorManager::ColorSpace ExtDecoder::getGrColorSpace()
1035 {
1036     if (dstColorSpace_ != nullptr) {
1037         return *dstColorSpace_;
1038     }
1039     auto skColorSpace = dstInfo_.isEmpty() ? info_.refColorSpace() : dstInfo_.refColorSpace();
1040     OHOS::ColorManager::ColorSpaceName name = OHOS::ColorManager::ColorSpaceName::CUSTOM;
1041     if (codec_ != nullptr) {
1042         auto profile = codec_->getICCProfile();
1043         if (profile != nullptr) {
1044             IMAGE_LOGD("profile got !!!!");
1045             GetColorSpaceName(profile, name);
1046         }
1047     }
1048     return OHOS::ColorManager::ColorSpace(skColorSpace, name);
1049 }
1050 
1051 bool ExtDecoder::IsSupportICCProfile()
1052 {
1053     if (dstColorSpace_ != nullptr) {
1054         return true;
1055     }
1056     if (info_.isEmpty()) {
1057         return false;
1058     }
1059     return info_.refColorSpace() != nullptr;
1060 }
1061 #endif
1062 
1063 static uint32_t ProcessWithStreamData(InputDataStream *input,
1064     std::function<uint32_t(uint8_t*, size_t)> process)
1065 {
1066     size_t inputSize = input->GetStreamSize();
1067     if (inputSize == SIZE_ZERO) {
1068         return Media::ERR_MEDIA_INVALID_VALUE;
1069     }
1070 
1071     auto tmpBuffer = std::make_unique<uint8_t[]>(inputSize);
1072     auto savePos = input->Tell();
1073     input->Seek(SIZE_ZERO);
1074     uint32_t readSize = 0;
1075     bool ret = input->Read(inputSize, tmpBuffer.get(), inputSize, readSize);
1076     input->Seek(savePos);
1077     if (!ret) {
1078         IMAGE_LOGE("InputDataStream read failed.");
1079         return Media::ERR_IMAGE_DATA_ABNORMAL;
1080     }
1081     return process(tmpBuffer.get(), inputSize);
1082 }
1083 
1084 static bool ParseExifData(InputDataStream *input, EXIFInfo &info)
1085 {
1086     if (info.IsExifDataParsed()) {
1087         return true;
1088     }
1089     IMAGE_LOGD("ParseExifData enter");
1090     auto code = ProcessWithStreamData(input, [&info](uint8_t* buffer, size_t size) {
1091         return info.ParseExifData(buffer, size);
1092     });
1093     if (code != SUCCESS) {
1094         IMAGE_LOGE("Error parsing EXIF: code %{public}d", code);
1095     }
1096     return code == SUCCESS;
1097 }
1098 
1099 bool ExtDecoder::GetPropertyCheck(uint32_t index, const std::string &key, uint32_t &res)
1100 {
1101     if (IsSameTextStr(key, ACTUAL_IMAGE_ENCODED_FORMAT)) {
1102         res = Media::ERR_MEDIA_VALUE_INVALID;
1103         return false;
1104     }
1105     if (!CheckIndexValied(index)) {
1106         res = Media::ERR_IMAGE_DECODE_HEAD_ABNORMAL;
1107         return false;
1108     }
1109     SkEncodedImageFormat format = codec_->getEncodedFormat();
1110     if (format != SkEncodedImageFormat::kJPEG) {
1111         res = Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1112         return true;
1113     }
1114     auto result = ParseExifData(stream_, exifInfo_);
1115     if (!result) {
1116         res = Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1117     }
1118     return result;
1119 }
1120 
1121 static uint32_t GetDelayTime(SkCodec * codec, uint32_t index, int32_t &value)
1122 {
1123     if (codec->getEncodedFormat() != SkEncodedImageFormat::kGIF) {
1124         IMAGE_LOGE("[GetDelayTime] Should not get delay time in %{public}d", codec->getEncodedFormat());
1125         return ERR_MEDIA_INVALID_PARAM;
1126     }
1127     auto frameInfos = codec->getFrameInfo();
1128     if (index > frameInfos.size() - 1) {
1129         IMAGE_LOGE("[GetDelayTime] frame size %{public}zu, index:%{public}d", frameInfos.size(), index);
1130         return ERR_MEDIA_INVALID_PARAM;
1131     }
1132     value = frameInfos[index].fDuration;
1133     IMAGE_LOGD("[GetDelayTime] index[%{public}d]:%{public}d", index, value);
1134     return SUCCESS;
1135 }
1136 
1137 uint32_t ExtDecoder::GetImagePropertyInt(uint32_t index, const std::string &key, int32_t &value)
1138 {
1139     IMAGE_LOGD("[GetImagePropertyInt] enter ExtDecoder plugin, key:%{public}s", key.c_str());
1140     uint32_t res = Media::ERR_IMAGE_DATA_ABNORMAL;
1141     if (!GetPropertyCheck(index, key, res)) {
1142         return res;
1143     }
1144     if (GIF_IMAGE_DELAY_TIME.compare(key) == ZERO) {
1145         return GetDelayTime(codec_.get(), index, value);
1146     }
1147     // There can add some not need exif property
1148     if (res == Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
1149         return res;
1150     }
1151     // Need exif property following
1152     if (IsSameTextStr(key, TAG_ORIENTATION_STRING)) {
1153         std::string strValue;
1154         res = exifInfo_.GetExifData(TAG_ORIENTATION_INT, strValue);
1155         if (res != SUCCESS) {
1156             return res;
1157         }
1158         value = atoi(strValue.c_str());
1159         return res;
1160     }
1161     IMAGE_LOGE("[GetImagePropertyInt] The key:%{public}s is not supported int32_t", key.c_str());
1162     return Media::ERR_MEDIA_VALUE_INVALID;
1163 }
1164 
1165 uint32_t ExtDecoder::GetImagePropertyString(uint32_t index, const std::string &key, std::string &value)
1166 {
1167     IMAGE_LOGD("[GetImagePropertyString] enter jpeg plugin, key:%{public}s", key.c_str());
1168     uint32_t res = Media::ERR_IMAGE_DATA_ABNORMAL;
1169     if (!GetPropertyCheck(index, key, res)) {
1170         return res;
1171     }
1172     // There can add some not need exif property
1173     if (ENCODED_FORMAT_KEY.compare(key) == ZERO) {
1174         SkEncodedImageFormat format = codec_->getEncodedFormat();
1175         return GetFormatName(format, value);
1176     } else if (GIF_IMAGE_DELAY_TIME.compare(key) == ZERO) {
1177         int delayTime = ZERO;
1178         res = GetDelayTime(codec_.get(), index, delayTime);
1179         value = std::to_string(delayTime);
1180         return res;
1181     }
1182     if (res == Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) {
1183         return res;
1184     }
1185     // Need exif property following
1186     if (key.find(HW_MNOTE_TAG_HEADER) != std::string::npos) {
1187         res = GetMakerImagePropertyString(key, value);
1188         if (value.length() == 0) {
1189             value = DEFAULT_EXIF_VALUE;
1190             IMAGE_LOGE("[GetImagePropertyString]The image does not contain the %{public}s  tag ", key.c_str());
1191         }
1192         return res;
1193     }
1194     res = exifInfo_.GetExifData(key, value);
1195     IMAGE_LOGD("[GetImagePropertyString] enter jpeg plugin, value:%{public}s", value.c_str());
1196     return res;
1197 }
1198 
1199 uint32_t ExtDecoder::GetMakerImagePropertyString(const std::string &key, std::string &value)
1200 {
1201     if (exifInfo_.makerInfoTagValueMap.find(key) != exifInfo_.makerInfoTagValueMap.end()) {
1202         value = exifInfo_.makerInfoTagValueMap[key];
1203         return SUCCESS;
1204     }
1205     return Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT;
1206 }
1207 
1208 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
1209     const std::string &value, const std::string &path)
1210 {
1211     IMAGE_LOGD("[ModifyImageProperty] with path:%{public}s, key:%{public}s, value:%{public}s",
1212         path.c_str(), key.c_str(), value.c_str());
1213     return exifInfo_.ModifyExifData(key, value, path);
1214 }
1215 
1216 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
1217     const std::string &value, const int fd)
1218 {
1219     IMAGE_LOGD("[ModifyImageProperty] with fd:%{public}d, key:%{public}s, value:%{public}s",
1220         fd, key.c_str(), value.c_str());
1221     return exifInfo_.ModifyExifData(key, value, fd);
1222 }
1223 
1224 uint32_t ExtDecoder::ModifyImageProperty(uint32_t index, const std::string &key,
1225     const std::string &value, uint8_t *data, uint32_t size)
1226 {
1227     IMAGE_LOGD("[ModifyImageProperty] with key:%{public}s, value:%{public}s",
1228         key.c_str(), value.c_str());
1229     return exifInfo_.ModifyExifData(key, value, data, size);
1230 }
1231 
1232 uint32_t ExtDecoder::GetFilterArea(const int &privacyType, std::vector<std::pair<uint32_t, uint32_t>> &ranges)
1233 {
1234     IMAGE_LOGD("[GetFilterArea] with privacyType:%{public}d ", privacyType);
1235     if (!CheckCodec()) {
1236         IMAGE_LOGE("Check codec failed");
1237         return NO_EXIF_TAG;
1238     }
1239     SkEncodedImageFormat format = codec_->getEncodedFormat();
1240     if (format != SkEncodedImageFormat::kJPEG) {
1241         return NO_EXIF_TAG;
1242     }
1243     constexpr size_t APP1_SIZE_H_OFF = 4;
1244     constexpr size_t APP1_SIZE_L_OFF = 5;
1245     constexpr size_t U8_SHIFT = 8;
1246     return ProcessWithStreamData(stream_, [this, &privacyType, &ranges](uint8_t* buffer, size_t size) {
1247         size_t appSize = (static_cast<size_t>(buffer[APP1_SIZE_H_OFF]) << U8_SHIFT) | buffer[APP1_SIZE_L_OFF];
1248         IMAGE_LOGD("[GetFilterArea]: get app1 area size");
1249         appSize += APP1_SIZE_H_OFF;
1250         auto ret = exifInfo_.GetFilterArea(buffer, (appSize < size) ? appSize : size, privacyType, ranges);
1251         if (ret != SUCCESS) {
1252             IMAGE_LOGE("[GetFilterArea]: failed to get area %{public}d", ret);
1253         }
1254         return ret;
1255     });
1256 }
1257 
1258 uint32_t ExtDecoder::GetTopLevelImageNum(uint32_t &num)
1259 {
1260     if (!CheckIndexValied(SIZE_ZERO) && frameCount_ <= ZERO) {
1261         return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
1262     }
1263     num = frameCount_;
1264     return SUCCESS;
1265 }
1266 
1267 bool ExtDecoder::IsSupportHardwareDecode() {
1268     if (info_.isEmpty() && !DecodeHeader()) {
1269         return false;
1270     }
1271     if (!(ImageSystemProperties::GetHardWareDecodeEnabled()
1272         && codec_->getEncodedFormat() == SkEncodedImageFormat::kJPEG)) {
1273         return false;
1274     }
1275     int width = info_.width();
1276     int height = info_.height();
1277     return width >= HARDWARE_MIN_DIM && width <= HARDWARE_MAX_DIM
1278         && height >= HARDWARE_MIN_DIM && height <= HARDWARE_MAX_DIM;
1279 }
1280 } // namespace ImagePlugin
1281 } // namespace OHOS
1282