1/*
2 * Copyright (C) 2024 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 <memory>
17#include "exif_metadata.h"
18#include "picture.h"
19#include "pixel_yuv.h"
20#include "pixel_yuv_ext.h"
21#include "image_utils.h"
22#include "image_log.h"
23#include "image_source.h"
24#include "media_errors.h"                                                // Operation success
25#ifdef IMAGE_COLORSPACE_FLAG
26#include "color_space.h"
27#endif
28#include "surface_buffer.h"
29#include "securec.h"
30#include "tiff_parser.h"
31#include "metadata_helper.h"
32#include "v1_0/cm_color_space.h"
33#include "vpe_utils.h"
34
35namespace OHOS {
36namespace Media {
37using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
38namespace {
39    static const std::map<int32_t, PixelFormat> PIXEL_FORMAT_MAP = {
40        { GRAPHIC_PIXEL_FMT_RGBA_8888, PixelFormat::RGBA_8888 },
41        { GRAPHIC_PIXEL_FMT_YCBCR_420_SP, PixelFormat::NV12 },
42        { GRAPHIC_PIXEL_FMT_YCRCB_420_SP, PixelFormat::NV21 },
43        { GRAPHIC_PIXEL_FMT_RGBA_1010102, PixelFormat::RGBA_1010102 },
44        { GRAPHIC_PIXEL_FMT_BGRA_8888, PixelFormat::BGRA_8888 },
45        { GRAPHIC_PIXEL_FMT_RGB_888, PixelFormat::RGB_888 },
46        { GRAPHIC_PIXEL_FMT_RGB_565, PixelFormat::RGB_565 },
47        { GRAPHIC_PIXEL_FMT_RGBA16_FLOAT, PixelFormat::RGBA_F16 },
48    };
49
50    static const std::map<CM_ColorSpaceType, ColorSpace> CM_COLORSPACE_MAP = {
51        { CM_COLORSPACE_NONE, ColorSpace::UNKNOWN },
52        { CM_BT709_FULL, ColorSpace::ITU_709 },
53        { CM_BT2020_HLG_FULL, ColorSpace::ITU_2020 },
54        { CM_BT2020_PQ_FULL, ColorSpace::ITU_2020 },
55        { CM_BT709_LIMIT, ColorSpace::ITU_709 },
56        { CM_BT2020_HLG_LIMIT, ColorSpace::ITU_2020 },
57        { CM_BT2020_PQ_LIMIT, ColorSpace::ITU_2020 },
58        { CM_SRGB_FULL, ColorSpace::SRGB },
59        { CM_P3_FULL, ColorSpace::DCI_P3 },
60        { CM_P3_HLG_FULL, ColorSpace::DCI_P3 },
61        { CM_P3_PQ_FULL, ColorSpace::DCI_P3 },
62        { CM_ADOBERGB_FULL, ColorSpace::ADOBE_RGB_1998 },
63        { CM_SRGB_LIMIT, ColorSpace::SRGB },
64        { CM_P3_LIMIT, ColorSpace::DCI_P3 },
65        { CM_P3_HLG_LIMIT, ColorSpace::DCI_P3 },
66        { CM_P3_PQ_LIMIT, ColorSpace::DCI_P3 },
67        { CM_ADOBERGB_LIMIT, ColorSpace::ADOBE_RGB_1998 },
68        { CM_LINEAR_SRGB, ColorSpace::LINEAR_SRGB },
69        { CM_LINEAR_BT709, ColorSpace::ITU_709 },
70        { CM_LINEAR_P3, ColorSpace::DISPLAY_P3 },
71        { CM_LINEAR_BT2020, ColorSpace::ITU_2020 },
72        { CM_DISPLAY_SRGB, ColorSpace::SRGB },
73        { CM_DISPLAY_P3_SRGB, ColorSpace::DISPLAY_P3 },
74        { CM_DISPLAY_P3_HLG, ColorSpace::DISPLAY_P3 },
75        { CM_DISPLAY_P3_PQ, ColorSpace::DISPLAY_P3 },
76        { CM_DISPLAY_BT2020_SRGB, ColorSpace::ITU_2020 },
77        { CM_DISPLAY_BT2020_HLG, ColorSpace::ITU_2020 },
78        { CM_DISPLAY_BT2020_PQ, ColorSpace::ITU_2020 },
79    };
80
81#ifdef IMAGE_COLORSPACE_FLAG
82    static const std::map<CM_ColorSpaceType, ColorManager::ColorSpaceName> CM_COLORSPACE_NAME_MAP = {
83        { CM_COLORSPACE_NONE, ColorManager::NONE },
84        { CM_BT601_EBU_FULL, ColorManager::BT601_EBU },
85        { CM_BT601_SMPTE_C_FULL, ColorManager::BT601_SMPTE_C },
86        { CM_BT709_FULL, ColorManager::BT709 },
87        { CM_BT2020_HLG_FULL, ColorManager::BT2020_HLG },
88        { CM_BT2020_PQ_FULL, ColorManager::BT2020_PQ },
89        { CM_BT601_EBU_LIMIT, ColorManager::BT601_EBU_LIMIT },
90        { CM_BT601_SMPTE_C_LIMIT, ColorManager::BT601_SMPTE_C_LIMIT },
91        { CM_BT709_LIMIT, ColorManager::BT709_LIMIT },
92        { CM_BT2020_HLG_LIMIT, ColorManager::BT2020_HLG_LIMIT },
93        { CM_BT2020_PQ_LIMIT, ColorManager::BT2020_PQ_LIMIT },
94        { CM_SRGB_FULL, ColorManager::SRGB },
95        { CM_P3_FULL, ColorManager::DCI_P3 },
96        { CM_P3_HLG_FULL, ColorManager::P3_HLG },
97        { CM_P3_PQ_FULL, ColorManager::P3_PQ },
98        { CM_ADOBERGB_FULL, ColorManager::ADOBE_RGB },
99        { CM_SRGB_LIMIT, ColorManager::SRGB_LIMIT },
100        { CM_P3_LIMIT, ColorManager::DISPLAY_P3_LIMIT },
101        { CM_P3_HLG_LIMIT, ColorManager::P3_HLG_LIMIT },
102        { CM_P3_PQ_LIMIT, ColorManager::P3_PQ_LIMIT },
103        { CM_ADOBERGB_LIMIT, ColorManager::ADOBE_RGB_LIMIT },
104        { CM_LINEAR_SRGB, ColorManager::LINEAR_SRGB },
105        { CM_LINEAR_BT709, ColorManager::LINEAR_BT709 },
106        { CM_LINEAR_P3, ColorManager::LINEAR_P3 },
107        { CM_LINEAR_BT2020, ColorManager::LINEAR_BT2020 },
108        { CM_DISPLAY_SRGB, ColorManager::DISPLAY_SRGB },
109        { CM_DISPLAY_P3_SRGB, ColorManager::DISPLAY_P3_SRGB },
110        { CM_DISPLAY_P3_HLG, ColorManager::DISPLAY_P3_HLG },
111        { CM_DISPLAY_P3_PQ, ColorManager::DISPLAY_P3_PQ },
112        { CM_DISPLAY_BT2020_SRGB, ColorManager::DISPLAY_BT2020_SRGB },
113        { CM_DISPLAY_BT2020_HLG, ColorManager::DISPLAY_BT2020_HLG },
114        { CM_DISPLAY_BT2020_PQ, ColorManager::DISPLAY_BT2020_PQ },
115    };
116#endif
117}
118const static uint64_t MAX_AUXILIARY_PICTURE_COUNT = 32;
119static const uint8_t NUM_0 = 0;
120static const uint8_t NUM_1 = 1;
121static const uint8_t NUM_2 = 2;
122static const std::string EXIF_DATA_SIZE_TAG = "exifDataSize";
123
124static bool IsYuvFormat(PixelFormat format)
125{
126    return format == PixelFormat::NV21 || format == PixelFormat::NV12;
127}
128
129static bool IsAlphaFormat(PixelFormat format)
130{
131    return format == PixelFormat::RGBA_8888 || format == PixelFormat::BGRA_8888 ||
132        format == PixelFormat::RGBA_1010102 || format == PixelFormat::RGBA_F16;
133}
134
135static PixelFormat SbFormat2PixelFormat(int32_t sbFormat)
136{
137    auto iter = PIXEL_FORMAT_MAP.find(sbFormat);
138    if (iter == PIXEL_FORMAT_MAP.end()) {
139        return PixelFormat::UNKNOWN;
140    }
141    return iter->second;
142}
143
144static CM_ColorSpaceType GetCMColorSpaceType(sptr<SurfaceBuffer> buffer)
145{
146    if (buffer == nullptr) {
147        return CM_ColorSpaceType::CM_COLORSPACE_NONE;
148    }
149    CM_ColorSpaceType type;
150    MetadataHelper::GetColorSpaceType(buffer, type);
151    return type;
152}
153
154static ColorSpace CMColorSpaceType2ColorSpace(CM_ColorSpaceType type)
155{
156    auto iter = CM_COLORSPACE_MAP.find(type);
157    if (iter == CM_COLORSPACE_MAP.end()) {
158        return ColorSpace::UNKNOWN;
159    }
160    return iter->second;
161}
162
163#ifdef IMAGE_COLORSPACE_FLAG
164static ColorManager::ColorSpaceName CMColorSpaceType2ColorSpaceName(CM_ColorSpaceType type)
165{
166    auto iter = CM_COLORSPACE_NAME_MAP.find(type);
167    if (iter == CM_COLORSPACE_NAME_MAP.end()) {
168        return ColorManager::NONE;
169    }
170    return iter->second;
171}
172#endif
173
174static ImageInfo MakeImageInfo(int width, int height, PixelFormat pf, AlphaType at, ColorSpace cs)
175{
176    ImageInfo info;
177    info.size.width = width;
178    info.size.height = height;
179    info.pixelFormat = pf;
180    info.alphaType = at;
181    info.colorSpace = cs;
182    return info;
183}
184
185static void SetYuvDataInfo(std::unique_ptr<PixelMap> &pixelMap, sptr<OHOS::SurfaceBuffer> &sBuffer)
186{
187    if (pixelMap == nullptr || sBuffer == nullptr) {
188        return;
189    }
190    int32_t width = sBuffer->GetWidth();
191    int32_t height = sBuffer->GetHeight();
192    OH_NativeBuffer_Planes *planes = nullptr;
193    GSError retVal = sBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
194    YUVDataInfo info;
195    info.imageSize = { width, height };
196    if (retVal != OHOS::GSERROR_OK || planes == nullptr || planes->planeCount <= NUM_1) {
197        IMAGE_LOGE("Get planesInfo failed, retVal:%{public}d", retVal);
198        return;
199    } else if (planes->planeCount >= NUM_2) {
200        info.yStride = planes->planes[NUM_0].columnStride;
201        info.uvStride = planes->planes[NUM_1].columnStride;
202        info.yOffset = planes->planes[NUM_0].offset;
203        info.uvOffset = planes->planes[NUM_1].offset - NUM_1;
204    }
205    pixelMap->SetImageYUVInfo(info);
206}
207
208static void SetImageInfoToHdr(std::shared_ptr<PixelMap> &mainPixelMap, std::unique_ptr<PixelMap> &hdrPixelMap)
209{
210    if (mainPixelMap != nullptr && hdrPixelMap != nullptr) {
211        ImageInfo mainInfo;
212        mainPixelMap->GetImageInfo(mainInfo);
213        ImageInfo hdrInfo;
214        hdrPixelMap->GetImageInfo(hdrInfo);
215        hdrInfo.size = mainInfo.size;
216        hdrInfo.encodedFormat = mainInfo.encodedFormat;
217        hdrPixelMap->SetImageInfo(hdrInfo, true);
218    }
219}
220
221Picture::~Picture() {}
222
223std::unique_ptr<Picture> Picture::Create(std::shared_ptr<PixelMap> &pixelMap)
224{
225    if (pixelMap == nullptr) {
226        return nullptr;
227    }
228    std::unique_ptr<Picture> dstPicture = std::make_unique<Picture>();
229    if (pixelMap->GetExifMetadata() != nullptr) {
230        dstPicture->SetExifMetadata(pixelMap->GetExifMetadata());
231    }
232    dstPicture->mainPixelMap_ = pixelMap;
233    return dstPicture;
234}
235
236std::unique_ptr<Picture> Picture::Create(sptr<SurfaceBuffer> &surfaceBuffer)
237{
238    std::shared_ptr<PixelMap> pixelmap = SurfaceBuffer2PixelMap(surfaceBuffer);
239    return Create(pixelmap);
240}
241
242std::unique_ptr<PixelMap> Picture::SurfaceBuffer2PixelMap(sptr<OHOS::SurfaceBuffer> &surfaceBuffer)
243{
244    if (surfaceBuffer == nullptr) {
245        return nullptr;
246    }
247    PixelFormat pixelFormat = SbFormat2PixelFormat(surfaceBuffer->GetFormat());
248    ColorSpace colorSpace = CMColorSpaceType2ColorSpace(GetCMColorSpaceType(surfaceBuffer));
249    AlphaType alphaType = IsAlphaFormat(pixelFormat) ?
250             AlphaType::IMAGE_ALPHA_TYPE_PREMUL : AlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
251    void* nativeBuffer = surfaceBuffer.GetRefPtr();
252    int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
253    if (err != OHOS::GSERROR_OK) {
254        IMAGE_LOGE("NativeBufferReference failed");
255        return nullptr;
256    }
257
258    std::unique_ptr<PixelMap> pixelMap;
259    if (IsYuvFormat(pixelFormat)) {
260#ifdef EXT_PIXEL
261        pixelMap = std::make_unique<PixelYuvExt>();
262#else
263        pixelMap = std::make_unique<PixelYuv>();
264#endif
265    } else {
266        pixelMap = std::make_unique<PixelMap>();
267    }
268    if (pixelMap == nullptr) {
269        return nullptr;
270    }
271
272    ImageInfo imageInfo = MakeImageInfo(surfaceBuffer->GetWidth(),
273                                        surfaceBuffer->GetHeight(), pixelFormat, alphaType, colorSpace);
274    pixelMap->SetImageInfo(imageInfo, true);
275    pixelMap->SetPixelsAddr(surfaceBuffer->GetVirAddr(),
276                            nativeBuffer, pixelMap->GetRowBytes() * pixelMap->GetHeight(),
277                            AllocatorType::DMA_ALLOC, nullptr);
278#ifdef IMAGE_COLORSPACE_FLAG
279    ColorManager::ColorSpaceName colorSpaceName =
280        CMColorSpaceType2ColorSpaceName(GetCMColorSpaceType(surfaceBuffer));
281    pixelMap->InnerSetColorSpace(ColorManager::ColorSpace(colorSpaceName));
282#endif
283    if (IsYuvFormat(pixelFormat)) {
284        SetYuvDataInfo(pixelMap, surfaceBuffer);
285    }
286    return pixelMap;
287}
288
289std::shared_ptr<PixelMap> Picture::GetMainPixel()
290{
291    return mainPixelMap_;
292}
293
294void Picture::SetMainPixel(std::shared_ptr<PixelMap> PixelMap)
295{
296    mainPixelMap_ = PixelMap;
297}
298
299static std::unique_ptr<PixelMap> ComposeHdrPixelMap(
300    ImageHdrType hdrType, CM_ColorSpaceType hdrCmColor,
301    std::shared_ptr<PixelMap> &mainPixelMap, sptr<SurfaceBuffer> &baseSptr, sptr<SurfaceBuffer> &gainmapSptr)
302{
303    sptr<SurfaceBuffer> hdrSptr = SurfaceBuffer::Create();
304    ImageInfo imageInfo;
305    mainPixelMap->GetImageInfo(imageInfo);
306    BufferRequestConfig requestConfig = {
307        .width = imageInfo.size.width,
308        .height = imageInfo.size.height,
309        .strideAlignment = imageInfo.size.width,
310        .format = GRAPHIC_PIXEL_FMT_RGBA_1010102,
311        .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
312        .timeout = 0,
313    };
314
315    GSError error = hdrSptr->Alloc(requestConfig);
316    if (error != GSERROR_OK) {
317        IMAGE_LOGE("HDR SurfaceBuffer Alloc failed, %{public}d", ERR_DMA_NOT_EXIST);
318        return nullptr;
319    }
320    CM_HDR_Metadata_Type type;
321    if (hdrType == ImageHdrType::HDR_VIVID_DUAL || hdrType == ImageHdrType::HDR_CUVA) {
322        type = CM_IMAGE_HDR_VIVID_SINGLE;
323    } else if (hdrType == ImageHdrType::HDR_ISO_DUAL) {
324        type = CM_IMAGE_HDR_ISO_SINGLE;
325    }
326    VpeUtils::SetSbMetadataType(hdrSptr, type);
327    VpeUtils::SetSbColorSpaceType(hdrSptr, hdrCmColor);
328
329    VpeSurfaceBuffers buffers = {
330        .sdr = baseSptr,
331        .gainmap = gainmapSptr,
332        .hdr = hdrSptr,
333    };
334    auto res = VpeUtils().ColorSpaceConverterComposeImage(buffers, (hdrType == ImageHdrType::HDR_CUVA));
335    if (res != VPE_ERROR_OK) {
336        IMAGE_LOGE("Compose HDR image failed");
337        return nullptr;
338    } else {
339        return Picture::SurfaceBuffer2PixelMap(hdrSptr);
340    }
341}
342
343std::unique_ptr<PixelMap> Picture::GetHdrComposedPixelMap()
344{
345    if (!HasAuxiliaryPicture(AuxiliaryPictureType::GAINMAP) ||
346        mainPixelMap_->GetAllocatorType() != AllocatorType::DMA_ALLOC) {
347        IMAGE_LOGE("Unsupport HDR compose.");
348        return nullptr;
349    }
350    std::shared_ptr<PixelMap> gainmap = Picture::GetAuxiliaryPicture(AuxiliaryPictureType::GAINMAP)->GetContentPixel();
351    ImageHdrType hdrType = gainmap->GetHdrType();
352    std::shared_ptr<HdrMetadata> metadata = gainmap->GetHdrMetadata();
353
354    CM_ColorSpaceType baseCmColor =
355        ImageSource::ConvertColorSpaceType(mainPixelMap_->InnerGetGrColorSpace().GetColorSpaceName(), true);
356    sptr<SurfaceBuffer> baseSptr(reinterpret_cast<SurfaceBuffer*>(mainPixelMap_->GetFd()));
357    VpeUtils::SetSurfaceBufferInfo(baseSptr, false, hdrType, baseCmColor, *metadata);
358
359    sptr<SurfaceBuffer> gainmapSptr(reinterpret_cast<SurfaceBuffer*>(gainmap->GetFd()));
360    CM_ColorSpaceType hdrCmColor = CM_BT2020_HLG_FULL;
361    CM_ColorSpaceType gainmapCmColor = metadata->extendMeta.metaISO.useBaseColorFlag == 0x01 ? baseCmColor : hdrCmColor;
362    IMAGE_LOGD("ComposeHdrImage color flag = %{public}d, gainmapChannelNum = %{public}d",
363        metadata->extendMeta.metaISO.useBaseColorFlag, metadata->extendMeta.metaISO.gainmapChannelNum);
364    ImageSource::SetVividMetaColor(*metadata, baseCmColor, gainmapCmColor, hdrCmColor);
365    VpeUtils::SetSurfaceBufferInfo(gainmapSptr, true, hdrType, gainmapCmColor, *metadata);
366
367    auto hdrPixelMap = ComposeHdrPixelMap(hdrType, hdrCmColor, mainPixelMap_, baseSptr, gainmapSptr);
368    SetImageInfoToHdr(mainPixelMap_, hdrPixelMap);
369    return hdrPixelMap;
370}
371
372std::shared_ptr<PixelMap> Picture::GetGainmapPixelMap()
373{
374    if (!HasAuxiliaryPicture(AuxiliaryPictureType::GAINMAP)) {
375        IMAGE_LOGE("Unsupport gain map.");
376        return nullptr;
377    } else {
378        return GetAuxiliaryPicture(AuxiliaryPictureType::GAINMAP)->GetContentPixel();
379    }
380}
381
382std::shared_ptr<AuxiliaryPicture> Picture::GetAuxiliaryPicture(AuxiliaryPictureType type)
383{
384    auto iter = auxiliaryPictures_.find(type);
385    if (iter == auxiliaryPictures_.end()) {
386        return nullptr;
387    }
388    return iter->second;
389}
390
391void Picture::SetAuxiliaryPicture(std::shared_ptr<AuxiliaryPicture> &picture)
392{
393    auxiliaryPictures_[picture->GetType()] = picture;
394    if (picture != nullptr && picture->GetType() == AuxiliaryPictureType::GAINMAP) {
395        std::shared_ptr<PixelMap> gainmapPixel = GetGainmapPixelMap();
396        if (gainmapPixel != nullptr && mainPixelMap_ != nullptr) {
397            mainPixelMap_->SetHdrMetadata(gainmapPixel->GetHdrMetadata());
398            mainPixelMap_->SetHdrType(gainmapPixel->GetHdrType());
399        }
400    }
401}
402
403bool Picture::HasAuxiliaryPicture(AuxiliaryPictureType type)
404{
405    return auxiliaryPictures_.find(type) != auxiliaryPictures_.end();
406}
407
408bool Picture::Marshalling(Parcel &data) const
409{
410    if (!mainPixelMap_) {
411        IMAGE_LOGE("Main PixelMap is null.");
412        return false;
413    }
414    if (!mainPixelMap_->Marshalling(data)) {
415        IMAGE_LOGE("Failed to marshal main PixelMap.");
416        return false;
417    }
418
419    size_t numAuxiliaryPictures = auxiliaryPictures_.size();
420    if (!data.WriteUint64(numAuxiliaryPictures)) {
421        IMAGE_LOGE("Failed to write number of auxiliary pictures.");
422        return false;
423    }
424
425    for (const auto &auxiliaryPicture : auxiliaryPictures_) {
426        AuxiliaryPictureType type =  auxiliaryPicture.first;
427
428        if (!data.WriteInt32(static_cast<int32_t>(type))) {
429            IMAGE_LOGE("Failed to write auxiliary picture type.");
430            return false;
431        }
432
433        if (!auxiliaryPicture.second || !auxiliaryPicture.second->Marshalling(data)) {
434            IMAGE_LOGE("Failed to marshal auxiliary picture of type %d.", static_cast<int>(type));
435            return false;
436        }
437    }
438
439    if (!data.WriteBool(maintenanceData_ != nullptr)) {
440        IMAGE_LOGE("Failed to write maintenance data existence value.");
441        return false;
442    }
443
444    if (maintenanceData_ != nullptr) {
445        if (maintenanceData_->WriteToMessageParcel(reinterpret_cast<MessageParcel&>(data)) != GSError::GSERROR_OK) {
446            IMAGE_LOGE("Failed to write maintenance data content.");
447            return false;
448        }
449    }
450
451    if (!data.WriteBool(exifMetadata_ != nullptr)) {
452        IMAGE_LOGE("Failed to write exif data existence value.");
453        return false;
454    }
455
456    if (exifMetadata_ != nullptr) {
457        if (!exifMetadata_->Marshalling(data)) {
458            IMAGE_LOGE("Failed to marshal exif metadata.");
459            return false;
460        }
461    }
462
463    return true;
464}
465
466Picture *Picture::Unmarshalling(Parcel &data)
467{
468    PICTURE_ERR error;
469    Picture* dstPicture = Picture::Unmarshalling(data, error);
470    if (dstPicture == nullptr || error.errorCode != SUCCESS) {
471        IMAGE_LOGE("unmarshalling failed errorCode:%{public}d, errorInfo:%{public}s",
472            error.errorCode, error.errorInfo.c_str());
473    }
474    return dstPicture;
475}
476
477Picture *Picture::Unmarshalling(Parcel &parcel, PICTURE_ERR &error)
478{
479    std::unique_ptr<Picture> picture = std::make_unique<Picture>();
480    std::shared_ptr<PixelMap> pixelmapPtr(PixelMap::Unmarshalling(parcel));
481
482    if (!pixelmapPtr) {
483        IMAGE_LOGE("Failed to unmarshal main PixelMap.");
484        return nullptr;
485    }
486    picture->SetMainPixel(pixelmapPtr);
487    uint64_t numAuxiliaryPictures = parcel.ReadUint64();
488    if (numAuxiliaryPictures > MAX_AUXILIARY_PICTURE_COUNT) {
489        return nullptr;
490    }
491
492    for (size_t i = NUM_0; i < numAuxiliaryPictures; ++i) {
493        int32_t type = parcel.ReadInt32();
494        std::shared_ptr<AuxiliaryPicture> auxPtr(AuxiliaryPicture::Unmarshalling(parcel));
495        if (!auxPtr) {
496            IMAGE_LOGE("Failed to unmarshal auxiliary picture of type %d.", type);
497            return nullptr;
498        }
499        picture->SetAuxiliaryPicture(auxPtr);
500    }
501
502    bool hasMaintenanceData = parcel.ReadBool();
503    if (hasMaintenanceData) {
504        sptr<SurfaceBuffer> surfaceBuffer = SurfaceBuffer::Create();
505        if (surfaceBuffer->ReadFromMessageParcel(reinterpret_cast<MessageParcel&>(parcel)) != GSError::GSERROR_OK) {
506            IMAGE_LOGE("Failed to unmarshal maintenance data");
507            return nullptr;
508        }
509        picture->maintenanceData_ = surfaceBuffer;
510    }
511
512    bool hasExifData = parcel.ReadBool();
513    if (hasExifData) {
514        picture->exifMetadata_ = std::shared_ptr<ExifMetadata>(ExifMetadata::Unmarshalling(parcel));
515    }
516
517    return picture.release();
518}
519
520int32_t Picture::SetExifMetadata(sptr<SurfaceBuffer> &surfaceBuffer)
521{
522    if (surfaceBuffer == nullptr) {
523        return ERR_IMAGE_INVALID_PARAMETER;
524    }
525
526    auto extraData = surfaceBuffer->GetExtraData();
527    if (extraData == nullptr) {
528        return ERR_IMAGE_INVALID_PARAMETER;
529    }
530
531    int32_t size = NUM_0;
532    extraData->ExtraGet(EXIF_DATA_SIZE_TAG, size);
533    if (size <= 0) {
534        IMAGE_LOGE("Invalid buffer size: %d.", size);
535        return ERR_IMAGE_INVALID_PARAMETER;
536    }
537
538    size_t tiffHeaderPos = TiffParser::FindTiffPos(reinterpret_cast<const byte *>(surfaceBuffer->GetVirAddr()), size);
539    if (tiffHeaderPos == std::numeric_limits<size_t>::max()) {
540        IMAGE_LOGE("Input image stream is not tiff type.");
541        return ERR_IMAGE_SOURCE_DATA;
542    }
543
544    ExifData *exifData;
545    TiffParser::Decode(static_cast<const unsigned char *>(surfaceBuffer->GetVirAddr()) + tiffHeaderPos,
546        size - tiffHeaderPos, &exifData);
547    if (exifData == nullptr) {
548        IMAGE_LOGE("Failed to decode EXIF data from image stream.");
549        return ERR_EXIF_DECODE_FAILED;
550    }
551
552    exifMetadata_ = std::make_shared<OHOS::Media::ExifMetadata>(exifData);
553    return SUCCESS;
554}
555
556int32_t Picture::SetExifMetadata(std::shared_ptr<ExifMetadata> exifMetadata)
557{
558    if (exifMetadata == nullptr) {
559        return ERR_IMAGE_INVALID_PARAMETER;
560    }
561    exifMetadata_ = exifMetadata;
562    return SUCCESS;
563}
564
565std::shared_ptr<ExifMetadata> Picture::GetExifMetadata()
566{
567    return exifMetadata_;
568}
569
570bool Picture::SetMaintenanceData(sptr<SurfaceBuffer> &surfaceBuffer)
571{
572    if (surfaceBuffer == nullptr) {
573        return false;
574    }
575    maintenanceData_ = surfaceBuffer;
576    return true;
577}
578
579sptr<SurfaceBuffer> Picture::GetMaintenanceData() const
580{
581    return maintenanceData_;
582}
583
584} // namespace Media
585} // namespace OHOS
586