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