From 23a3bc5a836c151ed399bd5c67bd64f10af2ce3e Mon Sep 17 00:00:00 2001 From: huchao Date: Sun, 31 Aug 2025 21:18:32 +0800 Subject: [PATCH] xtstyle and rfdatab Signed-off-by: huchao --- .../accessor/src/blob_metadata.cpp | 434 ++++++++++++++++++ .../accessor/src/exif_metadata_formatter.cpp | 10 + .../innerkitsimpl/accessor/src/metadata.cpp | 51 ++ .../innerkitsimpl/codec/src/image_source.cpp | 40 ++ frameworks/innerkitsimpl/picture/picture.cpp | 70 ++- .../test/unittest/image_common_ndk_test.cpp | 89 +++- .../innerkitsimpl/utils/include/image_utils.h | 1 + .../innerkitsimpl/utils/src/image_utils.cpp | 15 +- .../kits/js/common/image_source_napi.cpp | 5 + frameworks/kits/js/common/metadata_napi.cpp | 134 ++++++ frameworks/kits/js/common/picture_napi.cpp | 2 + .../js/common/picture_ndk/image_common.cpp | 57 ++- .../js/common/picture_ndk/picture_native.cpp | 2 - interfaces/innerkits/BUILD.gn | 4 + interfaces/innerkits/include/blob_metadata.h | 65 +++ interfaces/innerkits/include/image_source.h | 2 + interfaces/innerkits/include/image_type.h | 21 +- interfaces/innerkits/include/metadata.h | 4 + interfaces/innerkits/include/picture.h | 13 +- .../innerkits/include/rfdatab_metadata.h | 31 ++ .../innerkits/include/xtstyle_metadata.h | 32 ++ .../innerkits/libimage_native.versionscript | 4 + .../kits/js/common/include/metadata_napi.h | 4 +- .../kits/native/include/image/image_common.h | 69 ++- .../image/libextplugin/include/ext_decoder.h | 2 + .../image/libextplugin/include/ext_encoder.h | 7 +- .../include/hdr/jpeg_mpf_parser.h | 2 + .../include/heif_impl/HeifDecoderImpl.h | 2 + .../heif_impl/heif_parser/box/item_info_box.h | 2 + .../heif_impl/heif_parser/heif_image.h | 9 + .../heif_impl/heif_parser/heif_parser.h | 6 + .../image/libextplugin/src/ext_decoder.cpp | 19 + .../image/libextplugin/src/ext_encoder.cpp | 162 ++++++- .../libextplugin/src/hdr/jpeg_mpf_parser.cpp | 37 ++ .../src/heif_impl/HeifDecoderImpl.cpp | 11 + .../src/heif_impl/heif_parser/heif_image.cpp | 29 ++ .../src/heif_impl/heif_parser/heif_parser.cpp | 66 +++ .../manager/include/image/abs_image_decoder.h | 5 + 38 files changed, 1464 insertions(+), 54 deletions(-) create mode 100644 frameworks/innerkitsimpl/accessor/src/blob_metadata.cpp create mode 100644 frameworks/innerkitsimpl/accessor/src/metadata.cpp create mode 100644 interfaces/innerkits/include/blob_metadata.h create mode 100644 interfaces/innerkits/include/rfdatab_metadata.h create mode 100644 interfaces/innerkits/include/xtstyle_metadata.h diff --git a/frameworks/innerkitsimpl/accessor/src/blob_metadata.cpp b/frameworks/innerkitsimpl/accessor/src/blob_metadata.cpp new file mode 100644 index 000000000..534b04a47 --- /dev/null +++ b/frameworks/innerkitsimpl/accessor/src/blob_metadata.cpp @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "blob_metadata.h" + +#include +#include +#include +#include "ashmem.h" +#include "buffer_handle_parcel.h" +#include "image_log.h" +#include "image_utils.h" +#include "ipc_file_descriptor.h" +#include "media_errors.h" +#include "securec.h" + +#undef LOG_DOMAIN +#define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE + +#undef LOG_TAG +#define LOG_TAG "BlobMetadata" + +namespace OHOS { +namespace Media { +const static uint64_t MAX_BLOB_METADATA_LENGTH = 20 * 1024 * 1024; +const static uint32_t MAX_MARSHAL_BLOB_DATA_SIZE = 32 * 1024; +std::atomic BlobMetadata::currentId = 0; + +BlobMetadata::BlobMetadata() +{ + uniqueId_ = currentId.fetch_add(1, std::memory_order_relaxed); +}; + +BlobMetadata::BlobMetadata(MetadataType type) +{ + uniqueId_ = currentId.fetch_add(1, std::memory_order_relaxed); + type_ = type; +}; + +BlobMetadata::BlobMetadata(const BlobMetadata& blobMetadata) +{ + if (blobMetadata.data_ == nullptr || blobMetadata.dataSize_ <= 0) { + return; + } + uniqueId_ = currentId.fetch_add(1, std::memory_order_relaxed); + data_ = new uint8_t[blobMetadata.dataSize_]; + if (memcpy_s(data_, blobMetadata.dataSize_, blobMetadata.data_, blobMetadata.dataSize_) != EOK) { + delete[] data_; + data_ = nullptr; + type_ = MetadataType::UNKNOWN; + dataSize_ = 0; + } else { + type_ = blobMetadata.type_; + dataSize_ = blobMetadata.dataSize_; + } +} + +BlobMetadata& BlobMetadata::operator=(const BlobMetadata &blobMetadata) +{ + if (this == &blobMetadata) { + return *this; + } + if (data_ != nullptr) { + delete[] data_; + data_ = nullptr; + } + uniqueId_ = currentId.fetch_add(1, std::memory_order_relaxed); + if (blobMetadata.data_ == nullptr || blobMetadata.dataSize_ <= 0) { + dataSize_ = 0; + return *this; + } + data_ = new uint8_t[blobMetadata.dataSize_]; + if (memcpy_s(data_, blobMetadata.dataSize_, blobMetadata.data_, blobMetadata.dataSize_) != EOK) { + delete[] data_; + data_ = nullptr; + type_ = MetadataType::UNKNOWN; + dataSize_ = 0; + return *this; + } + type_ = blobMetadata.type_; + dataSize_ = blobMetadata.dataSize_; + return *this; +} + +BlobMetadata::~BlobMetadata() +{ + if (data_ != nullptr) { + delete[] data_; + data_ = nullptr; + } +} + +int BlobMetadata::GetValue(const std::string &key, std::string &value) const +{ + IMAGE_LOGE("Unsupported operation"); + return ERR_MEDIA_INVALID_OPERATION; +} + +bool BlobMetadata::SetValue(const std::string &key, const std::string &value) +{ + IMAGE_LOGE("Unsupported operation"); + return false; +} + +bool BlobMetadata::RemoveEntry(const std::string &key) +{ + IMAGE_LOGE("Unsupported operation"); + return false; +} + +const ImageMetadata::PropertyMapPtr BlobMetadata::GetAllProperties() +{ + IMAGE_LOGE("Unsupported operation"); + return nullptr; +} + +MetadataType BlobMetadata::GetType() const +{ + return type_; +} + +bool BlobMetadata::RemoveExifThumbnail() +{ + IMAGE_LOGE("Unsupported operation"); + return false; +} + +uint32_t BlobMetadata::GetUniqueId() const +{ + return uniqueId_; +} + +std::shared_ptr BlobMetadata::CloneMetadata() +{ + if (dataSize_ > MAX_BLOB_METADATA_LENGTH) { + IMAGE_LOGE("Failed to clone, the size of metadata exceeds the maximum limit %{public}llu.", + static_cast(MAX_BLOB_METADATA_LENGTH)); + return nullptr; + } + return std::make_shared(*this); +} + +void BlobMetadata::ReleaseMemory(void *addr, void *context, uint32_t size) +{ + if (context != nullptr) { + int *fd = static_cast(context); + if (addr != nullptr) { + ::munmap(addr, size); + } + if (fd != nullptr) { + ::close(*fd); + } + context = nullptr; + addr = nullptr; + } +} + +bool BlobMetadata::WriteDataToParcel(Parcel &parcel, size_t size) const +{ + if (data_ == nullptr) { + IMAGE_LOGE("WriteDataToParcel data_ is nullptr"); + return false; + } + const uint8_t *data = data_; + uint32_t id = GetUniqueId(); + std::string name = "Parcel Blob, uniqueId: " + std::to_string(getpid()) + '_' + std::to_string(id); + int fd = AshmemCreate(name.c_str(), size); + IMAGE_LOGI("Blob AshmemCreate:[%{public}d].", fd); + if (fd < 0) { + return false; + } + int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE); + IMAGE_LOGD("Blob AshmemSetProt:[%{public}d].", result); + if (result < 0) { + ::close(fd); + return false; + } + void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + ::close(fd); + IMAGE_LOGE("WriteDataToParcel map failed, errno:%{public}d", errno); + return false; + } + IMAGE_LOGD("mmap success"); + if (memcpy_s(ptr, size, data, size) != EOK) { + ::munmap(ptr, size); + ::close(fd); + IMAGE_LOGE("WriteDataToParcel memcpy_s error"); + return false; + } + if (!WriteFileDescriptor(parcel, fd)) { + ::munmap(ptr, size); + ::close(fd); + IMAGE_LOGE("WriteDataToParcel WriteFileDescriptor error"); + return false; + } + IMAGE_LOGD("WriteDataToParcel WriteFileDescriptor success"); + ::munmap(ptr, size); + ::close(fd); + return true; +} + +bool BlobMetadata::ReadDataFromAshmem(Parcel &parcel, std::unique_ptr &blobMetadataPtr, + std::function readFdDefaultFunc)> readSafeFdFunc) +{ + if (blobMetadataPtr == nullptr || blobMetadataPtr->data_ == nullptr || + blobMetadataPtr->dataSize_ <= 0 || blobMetadataPtr->dataSize_ > MAX_BLOB_METADATA_LENGTH) { + IMAGE_LOGE("Invalid BlobMetadataPtr or data buffer."); + return false; + } + auto readFdDefaultFunc = [](Parcel &parcel) -> int { return ReadFileDescriptor(parcel); }; + int fd = ((readSafeFdFunc != nullptr) ? readSafeFdFunc(parcel, readFdDefaultFunc) : readFdDefaultFunc(parcel)); + if (fd < 0) { + IMAGE_LOGE("Failed to read file descriptor from parcel."); + return false; + } + int32_t ashmemSize = AshmemGetSize(fd); + if (blobMetadataPtr->dataSize_ != static_cast(ashmemSize)) { + ::close(fd); + IMAGE_LOGE("ReadBlobDataFromParcel check ashmem size failed, fd:[%{public}d].", fd); + return false; + } + void *ptr = ::mmap(nullptr, blobMetadataPtr->dataSize_, PROT_READ, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + ::close(fd); + IMAGE_LOGE("ReadBlobData map failed, errno:%{public}d", errno); + return false; + } + if (memcpy_s(blobMetadataPtr->data_, blobMetadataPtr->dataSize_, ptr, blobMetadataPtr->dataSize_) != EOK) { + ::munmap(ptr, blobMetadataPtr->dataSize_); + ::close(fd); + IMAGE_LOGE("memcpy Blob data size:[%{public}d] error.", blobMetadataPtr->dataSize_); + return false; + } + ReleaseMemory(ptr, &fd, blobMetadataPtr->dataSize_); + return true; +} + +bool BlobMetadata::ReadDataFromParcel(Parcel &parcel, std::unique_ptr &blobMetadataPtr) +{ + const uint8_t *ptr = parcel.ReadUnpadBuffer(static_cast(blobMetadataPtr->dataSize_)); + if (ptr == nullptr) { + IMAGE_LOGE("Failed to read data from parcel."); + return false; + } + if (memcpy_s(blobMetadataPtr->data_, blobMetadataPtr->dataSize_, + ptr, blobMetadataPtr->dataSize_) != EOK) { + IMAGE_LOGE("memcpy_s failed to copy data."); + return false; + } + return true; +} + +int BlobMetadata::ReadFileDescriptor(Parcel &parcel) +{ + sptr descriptor = parcel.ReadObject(); + if (descriptor == nullptr) { + IMAGE_LOGE("ReadFileDescriptor get descriptor failed"); + return -1; + } + int fd = descriptor->GetFd(); + if (fd < 0) { + IMAGE_LOGE("ReadFileDescriptor get fd failed, fd:[%{public}d].", fd); + return -1; + } + return dup(fd); +} + +bool BlobMetadata::WriteFileDescriptor(Parcel &parcel, int fd) +{ + if (fd < 0) { + IMAGE_LOGE("WriteFileDescriptor get fd failed, fd:[%{public}d].", fd); + return false; + } + int dupFd = dup(fd); + if (dupFd < 0) { + IMAGE_LOGE("WriteFileDescriptor dup fd failed, dupFd:[%{public}d].", dupFd); + return false; + } + sptr descriptor = new IPCFileDescriptor(dupFd); + return parcel.WriteObject(descriptor); +} + +bool BlobMetadata::Marshalling(Parcel &parcel) const +{ + if (data_ == nullptr) { + IMAGE_LOGE("%{public}s Blob data is nullptr.", __func__); + return false; + } + if (dataSize_ > MAX_BLOB_METADATA_LENGTH) { + IMAGE_LOGE("The length of Blob metadata exceeds the maximum limit."); + return false; + } + if (!parcel.WriteUint32(static_cast(type_))) { + IMAGE_LOGE("Failed to write Blob data type."); + return false; + } + if (!parcel.WriteUint32(dataSize_)) { + IMAGE_LOGE("Failed to write Blob data size."); + return false; + } + if (dataSize_ < MAX_MARSHAL_BLOB_DATA_SIZE) { + if (!parcel.WriteUnpadBuffer(data_, dataSize_)) { + IMAGE_LOGE("Failed to write Blob data buffer."); + return false; + } + } else if (!WriteDataToParcel(parcel, dataSize_)) { + IMAGE_LOGE("Failed to write Blob data By Ashmem."); + return false; + } + return true; +} + +BlobMetadata *BlobMetadata::Unmarshalling(Parcel &parcel) +{ + PICTURE_ERR error; + BlobMetadata *dstBlobMetadata = Unmarshalling(parcel, error); + if (dstBlobMetadata == nullptr || error.errorCode != SUCCESS) { + IMAGE_LOGE("unmarshalling failed errorCode:%{public}d, errorInfo:%{public}s", + error.errorCode, error.errorInfo.c_str()); + } + return dstBlobMetadata; +} + +BlobMetadata *BlobMetadata::Unmarshalling(Parcel &parcel, PICTURE_ERR &error) +{ + uint32_t type; + if (!parcel.ReadUint32(type)) { + IMAGE_LOGE("Failed to read data type."); + return nullptr; + } + std::unique_ptr blobMetadataPtr = std::make_unique(static_cast(type)); + uint32_t dataSize; + if (!parcel.ReadUint32(dataSize)) { + IMAGE_LOGE("Failed to read data size."); + return nullptr; + } + if (dataSize <= 0 || dataSize > MAX_BLOB_METADATA_LENGTH) { + IMAGE_LOGE("The size of Blob metadata exceeds the maximum limit."); + return nullptr; + } + blobMetadataPtr->dataSize_ = dataSize; + blobMetadataPtr->data_ = new uint8_t[dataSize]; + + if (blobMetadataPtr->data_ == nullptr) { + IMAGE_LOGE("Failed to allocate memory for Blob data buffer."); + return nullptr; + } + const uint8_t *ptr = nullptr; + bool ret = false; + if (dataSize < MAX_MARSHAL_BLOB_DATA_SIZE) { + ret = ReadDataFromParcel(parcel, blobMetadataPtr); + } else { + ret = ReadDataFromAshmem(parcel, blobMetadataPtr); + } + if (!ret) { + delete[] blobMetadataPtr->data_; + blobMetadataPtr->data_ = nullptr; + blobMetadataPtr->type_ = MetadataType::UNKNOWN; + blobMetadataPtr->dataSize_ = 0; + IMAGE_LOGE("Failed to read data from parcel."); + } + return blobMetadataPtr.release(); +} + +uint32_t BlobMetadata::GetBlob(uint32_t bufferSize, uint8_t *dst) +{ + if (data_ == nullptr) { + IMAGE_LOGE("Get Blob by buffer current Blob data is null"); + return ERR_IMAGE_INVALID_PARAMETER; + } + if (bufferSize < dataSize_ || dst == nullptr) { + IMAGE_LOGE("Get Blob Input bufferSize or ptr Incorrect %{public}u", bufferSize); + return ERR_IMAGE_INVALID_PARAMETER; + } + + if (memcpy_s(dst, bufferSize, data_, dataSize_) != EOK) { + IMAGE_LOGE("get Blob Metadata blob to dst fail"); + return ERR_MEDIA_MALLOC_FAILED; + } + return SUCCESS; +} + +uint8_t *BlobMetadata::GetBlobPtr() +{ + return data_; +} + +uint32_t BlobMetadata::SetBlob(const uint8_t *source, const uint32_t bufferSize) +{ + if (source == nullptr || bufferSize == 0 || bufferSize > MAX_BLOB_METADATA_LENGTH) { + IMAGE_LOGE("Set Blob by buffer source is nullptr or size(%{public}llu) incorrect.", + static_cast(bufferSize)); + return ERR_IMAGE_INVALID_PARAMETER; + } + IMAGE_LOGI("setblob datasize_ %{public}u , bufferSize %{public}u", dataSize_, bufferSize); + uint8_t *resData = new uint8_t[bufferSize]; + if (resData == nullptr) { + IMAGE_LOGE("Failed to allocate memory for Blob Metadata Blob"); + return ERR_MEDIA_MALLOC_FAILED; + } + if (memcpy_s(resData, bufferSize, source, bufferSize) != EOK) { + delete[] resData; + resData = nullptr; + IMAGE_LOGE("Set blob data to Blob data_ fail."); + return ERR_MEDIA_MALLOC_FAILED; + } + if (data_ != nullptr) { + delete[] data_; + data_ = nullptr; + } + data_ = resData; + dataSize_ = bufferSize; + return SUCCESS; +} + +uint32_t BlobMetadata::GetBlobSize() +{ + return dataSize_; +} +} // namespace Media +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp b/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp index afbec5d3a..4ca7454ae 100644 --- a/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp +++ b/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp @@ -206,6 +206,11 @@ const static std::set READ_WRITE_KEYS = { "MovingPhotoVersion", "MicroVideoPresentationTimestampUS", "HwMnoteAiEdit", + "HwMnoteXtStyleTemplateName", + "HwMnoteXtStyleCustomLightAndShadow", + "HwMnoteXtStyleCustomSaturation", + "HwMnoteXtStyleCustomHue", + "HwMnoteXtStyleExposureParam", "MakerNote", }; @@ -1287,6 +1292,11 @@ std::multimap ExifMetadatFormatter::valueForma {"HwMnoteXmageBottom", singleInt}, {"HwMnoteCloudEnhancementMode", singleInt}, {"HwMnoteAiEdit", singleInt}, + {"HwMnoteXtStyleTemplateName", singleInt}, + {"HwMnoteXtStyleCustomLightAndShadow", singleRational}, + {"HwMnoteXtStyleCustomSaturation", singleRational}, + {"HwMnoteXtStyleCustomHue", singleRational}, + {"HwMnoteXtStyleExposureParam", tribleIntWithBlank}, {"DateTimeDigitized", dateTimeValidation}, {"DateTimeDigitized", dateValidation}, {"OffsetTime", dateTimeValidation}, diff --git a/frameworks/innerkitsimpl/accessor/src/metadata.cpp b/frameworks/innerkitsimpl/accessor/src/metadata.cpp new file mode 100644 index 000000000..d4767b132 --- /dev/null +++ b/frameworks/innerkitsimpl/accessor/src/metadata.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "metadata.h" +#include "media_errors.h" + +#undef LOG_DOMAIN +#define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE + +#undef LOG_TAG +#define LOG_TAG "Metadata" + +namespace OHOS { +namespace Media { + +uint32_t ImageMetadata::GetBlob(uint32_t bufferSize, uint8_t *dst) +{ + (void)dst; + (void)bufferSize; + return ERR_MEDIA_INVALID_OPERATION; +} + +uint32_t ImageMetadata::SetBlob(const uint8_t *source, const uint32_t bufferSize) +{ + (void)source; + (void)bufferSize; + return ERR_MEDIA_INVALID_OPERATION; +} + +uint32_t ImageMetadata::GetBlobSize() +{ + return 0; +}; + +uint8_t* ImageMetadata::GetBlobPtr() +{ + return nullptr; +} +} // namespace Media +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/innerkitsimpl/codec/src/image_source.cpp b/frameworks/innerkitsimpl/codec/src/image_source.cpp index 2f66124c6..4896383ba 100644 --- a/frameworks/innerkitsimpl/codec/src/image_source.cpp +++ b/frameworks/innerkitsimpl/codec/src/image_source.cpp @@ -4998,11 +4998,14 @@ std::unique_ptr ImageSource::CreatePicture(const DecodingOptionsForPict std::set auxTypes = (opts.desireAuxiliaryPictures.size() > 0) ? opts.desireAuxiliaryPictures : ImageUtils::GetAllAuxiliaryPictureType(); + std::set metadataTypes = (opts.desiredMetadatas.size() > 0) ? + opts.desiredMetadatas : ImageUtils::GetAllMetadataType(); if (info.encodedFormat == IMAGE_HEIF_FORMAT || info.encodedFormat == IMAGE_HEIC_FORMAT) { DecodeHeifAuxiliaryPictures(auxTypes, picture, errorCode); } else if (info.encodedFormat == IMAGE_JPEG_FORMAT) { DecodeJpegAuxiliaryPicture(auxTypes, picture, errorCode); } + DecodeBlobMetaData(picture, metadataTypes, info, errorCode); SetHdrMetadataForPicture(picture); if (errorCode != SUCCESS) { IMAGE_LOGE("Decode auxiliary pictures failed, error code: %{public}u", errorCode); @@ -5201,6 +5204,43 @@ void ImageSource::DecodeJpegAuxiliaryPicture( } #endif +void ImageSource::DecodeBlobMetaData(std::unique_ptr &picture, const std::set &metadataTypes, + ImageInfo &info, uint32_t &errorCode) +{ + if (mainDecoder_ == nullptr) { + IMAGE_LOGE("mainDecoder_ is nullptr"); + errorCode = ERR_IMAGE_PLUGIN_CREATE_FAILED; + return; + } + if (picture == nullptr || picture->GetMainPixel() == nullptr) { + IMAGE_LOGE("%{public}s: picture or mainPixelMap is nullptr", __func__); + errorCode = ERR_IMAGE_DATA_ABNORMAL; + return; + } + + std::map> metadataMap; + for (const auto& iter : BLOB_METADATA_TAG_MAP) { + if (metadataTypes.find(iter.first) == metadataTypes.end()) { + continue; + } + if (info.encodedFormat == IMAGE_JPEG_FORMAT) { + auto jpegMpfParser = std::make_unique(); + jpegMpfParser->ParsingBlobMetadata(sourceStreamPtr_->GetDataPtr(), sourceStreamPtr_->GetStreamSize(), + metadataMap[iter.first], iter.first); + } else { + mainDecoder_->GetHeifMetadataBlob(metadataMap[iter.first], iter.first); + } + } + + for (const auto& iter : metadataMap) { + if (iter.second.size()) { + IMAGE_LOGI("%{public}s: %{public}s size is: %{public}zu", + __func__, BLOB_METADATA_TAG_MAP.at(iter.first).c_str(), iter.second.size()); + errorCode = picture->SetBlobMetadataByType(iter.second, iter.first); + } + } +} + bool ImageSource::CompressToAstcFromPixelmap(const DecodeOptions &opts, unique_ptr &rgbaPixelmap, unique_ptr &dstMemory) { diff --git a/frameworks/innerkitsimpl/picture/picture.cpp b/frameworks/innerkitsimpl/picture/picture.cpp index 8f3f51cb8..8580fcce8 100644 --- a/frameworks/innerkitsimpl/picture/picture.cpp +++ b/frameworks/innerkitsimpl/picture/picture.cpp @@ -15,6 +15,8 @@ #include #include "exif_metadata.h" +#include "xtstyle_metadata.h" +#include "rfdatab_metadata.h" #include "picture.h" #include "pixel_yuv.h" #include "pixel_yuv_ext.h" @@ -120,6 +122,8 @@ namespace { } const static uint64_t MAX_AUXILIARY_PICTURE_COUNT = 32; const static uint64_t MAX_PICTURE_META_TYPE_COUNT = 64; + +// Define ExifData malloc max size 1MB const static uint64_t MAX_EXIFMETADATA_SIZE = 1024 * 1024; static const uint8_t NUM_0 = 0; static const uint8_t NUM_1 = 1; @@ -552,9 +556,8 @@ bool Picture::MarshalMetadata(Parcel &data) const bool Picture::Marshalling(Parcel &data) const { - bool cond = false; CHECK_ERROR_RETURN_RET_LOG(!mainPixelMap_, false, "Main PixelMap is null."); - cond = !mainPixelMap_->Marshalling(data); + bool cond = !mainPixelMap_->Marshalling(data); CHECK_ERROR_RETURN_RET_LOG(cond, false, "Failed to marshal main PixelMap."); size_t numAuxiliaryPictures = auxiliaryPictures_.size(); @@ -571,8 +574,8 @@ bool Picture::Marshalling(Parcel &data) const CHECK_ERROR_RETURN_RET_LOG(cond, false, "Failed to marshal auxiliary picture of type %{public}d.", static_cast(type)); } - CHECK_ERROR_RETURN_RET(!MarshalMetadata(data), false); - + cond = !MarshalMetadata(data); + CHECK_ERROR_RETURN_RET(cond, false); return true; } @@ -609,6 +612,10 @@ bool Picture::UnmarshalMetadata(Parcel &parcel, Picture &picture, PICTURE_ERR &e imagedataPtr.reset(ExifMetadata::Unmarshalling(parcel)); } else if (type == MetadataType::GIF) { imagedataPtr.reset(GifMetadata::Unmarshalling(parcel)); + } else if (type == MetadataType::XTSTYLE) { + imagedataPtr.reset(XtStyleMetadata::Unmarshalling(parcel)); + } else if (type == MetadataType::RFDATAB) { + imagedataPtr.reset(RfDataBMetadata::Unmarshalling(parcel)); } else { IMAGE_LOGE("Unsupported metadata type: %{public}d in picture", static_cast(type)); } @@ -627,6 +634,7 @@ Picture *Picture::Unmarshalling(Parcel &parcel, PICTURE_ERR &error) { std::unique_ptr picture = std::make_unique(); std::shared_ptr pixelmapPtr(PixelMap::Unmarshalling(parcel)); + CHECK_ERROR_RETURN_RET_LOG(!pixelmapPtr, nullptr, "Failed to unmarshal main PixelMap."); picture->SetMainPixel(pixelmapPtr); uint64_t numAuxiliaryPictures = parcel.ReadUint64(); @@ -642,9 +650,12 @@ Picture *Picture::Unmarshalling(Parcel &parcel, PICTURE_ERR &error) return picture.release(); } -int32_t Picture::CreateExifMetadata() +uint32_t Picture::CreateExifMetadata() { - CHECK_ERROR_RETURN_RET_LOG(GetExifMetadata() != nullptr, SUCCESS, "exifMetadata is already created"); + if (GetExifMetadata() != nullptr) { + IMAGE_LOGE("exifMetadata is already created"); + return SUCCESS; + } auto exifMetadata = std::make_shared(); if (exifMetadata == nullptr) { IMAGE_LOGE("Failed to create ExifMetadata object"); @@ -657,7 +668,7 @@ int32_t Picture::CreateExifMetadata() return SetExifMetadata(exifMetadata); } -int32_t Picture::SetExifMetadata(sptr &surfaceBuffer) +uint32_t Picture::SetExifMetadata(sptr &surfaceBuffer) { if (surfaceBuffer == nullptr) { return ERR_IMAGE_INVALID_PARAMETER; @@ -699,7 +710,7 @@ int32_t Picture::SetExifMetadata(sptr &surfaceBuffer) return SetExifMetadata(exifMetadata); } -int32_t Picture::SetExifMetadata(std::shared_ptr exifMetadata) +uint32_t Picture::SetExifMetadata(std::shared_ptr exifMetadata) { return SetMetadata(MetadataType::EXIF, exifMetadata); } @@ -727,6 +738,34 @@ sptr Picture::GetMaintenanceData() const return maintenanceData_; } +uint32_t Picture::SetXtStyleMetadata(std::shared_ptr xtStyleMetadata) +{ + return SetMetadata(MetadataType::XTSTYLE, xtStyleMetadata); +} + +std::shared_ptr Picture::GetXtStyleMetadata() +{ + auto xtStyleMetadata = GetMetadata(MetadataType::XTSTYLE); + if (xtStyleMetadata == nullptr) { + return nullptr; + } + return std::reinterpret_pointer_cast(xtStyleMetadata); +} + +uint32_t Picture::SetRfDataBMetadata(std::shared_ptr rfDataBMetadata) +{ + return SetMetadata(MetadataType::RFDATAB, rfDataBMetadata); +} + +std::shared_ptr Picture::GetRfDataBMetadata() +{ + auto rfDataBMetadata = GetMetadata(MetadataType::RFDATAB); + if (rfDataBMetadata == nullptr) { + return nullptr; + } + return std::reinterpret_pointer_cast(rfDataBMetadata); +} + std::shared_ptr Picture::GetMetadata(MetadataType type) { if (metadatas_.find(type) == metadatas_.end()) { @@ -764,6 +803,13 @@ uint32_t Picture::SetMetadata(MetadataType type, std::shared_ptr return SUCCESS; } +uint32_t Picture::SetBlobMetadataByType(const std::vector& metadata, MetadataType type) +{ + std::shared_ptr blobMetadata = std::make_shared(type); + blobMetadata->SetBlob(metadata.data(), metadata.size()); + return SetMetadata(type, blobMetadata); +} + void Picture::DumpPictureIfDumpEnabled(Picture& picture, std::string dumpType) { CHECK_ERROR_RETURN(!ImageSystemProperties::GetDumpPictureEnabled()); @@ -780,13 +826,21 @@ void Picture::DumpPictureIfDumpEnabled(Picture& picture, std::string dumpType) ImageUtils::DumpPixelMap(pixelMap.get(), dumpType + "_AuxiliaryType", static_cast(auxType)); } } + auto rfDataBMetadata = picture.GetRfDataBMetadata(); + if (rfDataBMetadata != nullptr && rfDataBMetadata->GetBlobPtr() != nullptr) { + ImageUtils::DumpDataIfDumpEnabled(reinterpret_cast(rfDataBMetadata->GetBlobPtr()), + rfDataBMetadata->GetBlobSize(), dumpType + "_RfDataB", static_cast(MetadataType::RFDATAB)); + } } bool Picture::IsValidPictureMetadataType(MetadataType metadataType) { const static std::set pictureMetadataTypes = { MetadataType::EXIF, + MetadataType::XTSTYLE, + MetadataType::RFDATAB, MetadataType::GIF, + MetadataType::STDATA, }; return pictureMetadataTypes.find(metadataType) != pictureMetadataTypes.end(); } diff --git a/frameworks/innerkitsimpl/test/unittest/image_common_ndk_test.cpp b/frameworks/innerkitsimpl/test/unittest/image_common_ndk_test.cpp index 0d28b5ac1..5a614380c 100644 --- a/frameworks/innerkitsimpl/test/unittest/image_common_ndk_test.cpp +++ b/frameworks/innerkitsimpl/test/unittest/image_common_ndk_test.cpp @@ -15,6 +15,7 @@ #include "exif_metadata.h" #include "fragment_metadata.h" +#include "xtstyle_metadata.h" #include "image_common.h" #include "image_common_impl.h" #include @@ -27,12 +28,16 @@ public: ImageCommonNdkTest() {} ~ImageCommonNdkTest() {} }; -static constexpr Image_MetadataType INVALID_METADATA = static_cast(100); + +static const Image_MetadataType INVALID_METADATA = static_cast(100); static void TestMetaDataClone(Image_MetadataType metadataType) { OH_PictureMetadata *oldMetadata = nullptr; Image_ErrorCode res = OH_PictureMetadata_Create(metadataType, &oldMetadata); + if (oldMetadata == nullptr) { + return; + } EXPECT_EQ(res, IMAGE_SUCCESS); OH_PictureMetadata *newMetadata = nullptr; res = OH_PictureMetadata_Clone(oldMetadata, &newMetadata); @@ -69,7 +74,10 @@ static void TestPictureMetadataGetSetProperty(Image_MetadataType metadataType, c res = OH_PictureMetadata_Release(metadataPtr); EXPECT_EQ(res, IMAGE_SUCCESS); free(key.data); - delete[] dstValue.data; + if (dstValue.data != nullptr) { + delete[] dstValue.data; + dstValue.data = nullptr; + } } /** @@ -276,5 +284,82 @@ HWTEST_F(ImageCommonNdkTest, OH_PictureMetadata_CloneTest003, TestSize.Level1) TestMetaDataClone(FRAGMENT_METADATA); } +/** + * @tc.name: OH_PictureMetadata_CloneTest004 + * @tc.desc: Tests cloning picture metadata for XTSTYLE_METADATA. + * The test checks if the metadata is cloned successfully. + * @tc.type: FUNC + */ +HWTEST_F(ImageCommonNdkTest, OH_PictureMetadata_CloneTest004, TestSize.Level1) +{ + TestMetaDataClone(XTSTYLE_METADATA); +} + +HWTEST_F(ImageCommonNdkTest, OH_PictureMetadata_SetBlobTest001, TestSize.Level3) +{ + OH_PictureMetadata *metadataPtr = nullptr; + Image_MetadataType metadataType = XTSTYLE_METADATA; + Image_ErrorCode res = OH_PictureMetadata_Create(metadataType, &metadataPtr); + ASSERT_NE(metadataPtr, nullptr); + uint8_t* blob = nullptr; + size_t blobSize = 0; + res = OH_PictureMetadata_SetBlob(metadataPtr, blob, &blobSize); + EXPECT_EQ(res, IMAGE_BAD_PARAMETER); +} + +HWTEST_F(ImageCommonNdkTest, OH_PictureMetadata_SetBlobTest002, TestSize.Level3) +{ + OH_PictureMetadata *metadataPtr = nullptr; + Image_MetadataType metadataType = XTSTYLE_METADATA; + Image_ErrorCode res = OH_PictureMetadata_Create(metadataType, &metadataPtr); + ASSERT_NE(metadataPtr, nullptr); + uint8_t blob[5] = {1, 2, 3, 4, 5}; + size_t blobSize = 5; + res = OH_PictureMetadata_SetBlob(metadataPtr, blob, &blobSize); + EXPECT_EQ(res, IMAGE_SUCCESS); +} + +HWTEST_F(ImageCommonNdkTest, OH_PictureMetadata_GetBlobTest001, TestSize.Level3) +{ + OH_PictureMetadata *metadataPtr = nullptr; + Image_MetadataType metadataType = XTSTYLE_METADATA; + Image_ErrorCode res = OH_PictureMetadata_Create(metadataType, &metadataPtr); + ASSERT_NE(metadataPtr, nullptr); + uint8_t* blob = nullptr; + size_t blobSize = 0; + res = OH_PictureMetadata_SetBlob(metadataPtr, blob, &blobSize); + EXPECT_EQ(res, IMAGE_BAD_PARAMETER); + res = OH_PictureMetadata_GetBlob(metadataPtr, blob, blobSize); + EXPECT_EQ(res, IMAGE_BAD_PARAMETER); +} + +HWTEST_F(ImageCommonNdkTest, OH_PictureMetadata_GetBlobTest002, TestSize.Level3) +{ + OH_PictureMetadata *metadataPtr = nullptr; + Image_MetadataType metadataType = XTSTYLE_METADATA; + Image_ErrorCode res = OH_PictureMetadata_Create(metadataType, &metadataPtr); + ASSERT_NE(metadataPtr, nullptr); + uint8_t blob[5] = {1, 2, 3, 4, 5}; + size_t blobSize = 5; + res = OH_PictureMetadata_SetBlob(metadataPtr, blob, &blobSize); + EXPECT_EQ(res, IMAGE_SUCCESS); + res = OH_PictureMetadata_GetBlob(metadataPtr, blob, blobSize); + EXPECT_EQ(res, IMAGE_SUCCESS); +} + +HWTEST_F(ImageCommonNdkTest, OH_PictureMetadata_GetBlobSizeTest001, TestSize.Level3) +{ + OH_PictureMetadata *metadataPtr = nullptr; + Image_MetadataType metadataType = XTSTYLE_METADATA; + Image_ErrorCode res = OH_PictureMetadata_Create(metadataType, &metadataPtr); + ASSERT_NE(metadataPtr, nullptr); + uint8_t blob[5] = {1, 2, 3, 4, 5}; + size_t blobSize = sizeof(blob); + res = OH_PictureMetadata_SetBlob(metadataPtr, blob, &blobSize); + EXPECT_EQ(res, IMAGE_SUCCESS); + res = OH_PictureMetadata_GetBlobSize(metadataPtr, &blobSize); + EXPECT_EQ(res, IMAGE_SUCCESS); +} + } // namespace Media } // namespace OHOS \ No newline at end of file diff --git a/frameworks/innerkitsimpl/utils/include/image_utils.h b/frameworks/innerkitsimpl/utils/include/image_utils.h index 4968f232f..e0352d793 100644 --- a/frameworks/innerkitsimpl/utils/include/image_utils.h +++ b/frameworks/innerkitsimpl/utils/include/image_utils.h @@ -91,6 +91,7 @@ public: static bool IsAuxiliaryPictureEncoded(AuxiliaryPictureType type); static bool IsMetadataTypeSupported(MetadataType metadataType); static const std::set GetAllAuxiliaryPictureType(); + static const std::set &GetAllMetadataType(); static size_t GetAstcBytesCount(const ImageInfo& imageInfo); static bool StrToUint32(const std::string& str, uint32_t& value); static bool IsInRange(uint32_t value, uint32_t minValue, uint32_t maxValue); diff --git a/frameworks/innerkitsimpl/utils/src/image_utils.cpp b/frameworks/innerkitsimpl/utils/src/image_utils.cpp index 6ef30c429..7bac8b5b1 100644 --- a/frameworks/innerkitsimpl/utils/src/image_utils.cpp +++ b/frameworks/innerkitsimpl/utils/src/image_utils.cpp @@ -1067,7 +1067,8 @@ bool ImageUtils::IsAuxiliaryPictureEncoded(AuxiliaryPictureType type) bool ImageUtils::IsMetadataTypeSupported(MetadataType metadataType) { - if (metadataType == MetadataType::EXIF || metadataType == MetadataType::FRAGMENT) { + if (metadataType == MetadataType::EXIF || metadataType == MetadataType::FRAGMENT || + metadataType == MetadataType::XTSTYLE || metadataType == MetadataType::RFDATAB) { return true; } else { return false; @@ -1085,6 +1086,18 @@ const std::set ImageUtils::GetAllAuxiliaryPictureType() return auxTypes; } +const std::set &ImageUtils::GetAllMetadataType() +{ + static const std::set metadataTypes = { + MetadataType::EXIF, + MetadataType::FRAGMENT, + MetadataType::XTSTYLE, + MetadataType::RFDATAB, + MetadataType::STDATA + }; + return metadataTypes; +} + size_t ImageUtils::GetAstcBytesCount(const ImageInfo& imageInfo) { size_t astcBytesCount = 0; diff --git a/frameworks/kits/js/common/image_source_napi.cpp b/frameworks/kits/js/common/image_source_napi.cpp index 55c9e5d5d..fbf376089 100644 --- a/frameworks/kits/js/common/image_source_napi.cpp +++ b/frameworks/kits/js/common/image_source_napi.cpp @@ -333,6 +333,11 @@ static std::vector sPropertyKeyMap = { {"CLOUD_ENHANCEMENT_MODE", 0, "HwMnoteCloudEnhancementMode"}, {"WIND_SNAPSHOT_MODE", 0, "HwMnoteWindSnapshotMode"}, {"GIF_LOOP_COUNT", 0, "GIFLoopCount"}, + {"XTSTYLE_TEMPLATE_NAME", 0, "HwMnoteXtStyleTemplateName"}, + {"XTSTYLE_CUSTOM_LIGHT_AND_SHADOW", 0, "HwMnoteXtStyleCustomLightAndShadow"}, + {"XTSTYLE_CUSTOM_SATURATION", 0, "HwMnoteXtStyleCustomSaturation"}, + {"XTSTYLE_CUSTOM_HUE", 0, "HwMnoteXtStyleCustomHue"}, + {"XTSTYLE_EXPOSUREPARAM_NAME", 0, "HwMnoteXtStyleExposureParam"}, }; static std::vector sImageFormatMap = { {"YCBCR_422_SP", 1000, ""}, diff --git a/frameworks/kits/js/common/metadata_napi.cpp b/frameworks/kits/js/common/metadata_napi.cpp index 1b1d9dddd..e0c2b9d86 100644 --- a/frameworks/kits/js/common/metadata_napi.cpp +++ b/frameworks/kits/js/common/metadata_napi.cpp @@ -55,6 +55,8 @@ struct MetadataNapiAsyncContext { std::vector keyStrArray; std::multimap errMsgArray; std::vector> KVSArray; + void *arrayBuffer; + size_t arrayBufferSize; }; using MetadataNapiAsyncContextPtr = std::unique_ptr; @@ -164,6 +166,8 @@ napi_value MetadataNapi::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("getProperties", GetProperties), DECLARE_NAPI_FUNCTION("setProperties", SetProperties), DECLARE_NAPI_FUNCTION("getAllProperties", GetAllProperties), + DECLARE_NAPI_FUNCTION("getBlob", GetBlob), + DECLARE_NAPI_FUNCTION("setBlob", SetBlob), DECLARE_NAPI_FUNCTION("clone", Clone), }; napi_property_descriptor static_prop[] = {}; @@ -695,5 +699,135 @@ void MetadataNapi::release() isRelease = true; } } + +static void GetBlobComplete(napi_env env, napi_status status, void *data) +{ + napi_value result = nullptr; + napi_get_undefined(env, &result); + auto context = static_cast(data); + + if (context->status == SUCCESS && + !ImageNapiUtils::CreateArrayBuffer(env, context->arrayBuffer, context->arrayBufferSize, &result)) { + context->status = ERROR; + IMAGE_LOGE("Fail to create napi arraybuffer!"); + napi_get_undefined(env, &result); + } + + delete[] static_cast(context->arrayBuffer); + context->arrayBuffer = nullptr; + context->arrayBufferSize = 0; + CommonCallbackRoutine(env, context, result); +} + +napi_value MetadataNapi::GetBlob(napi_env env, napi_callback_info info) +{ + napi_value result = nullptr; + napi_get_undefined(env, &result); + napi_status status; + napi_value thisVar = nullptr; + size_t argCount = NUM_0; + + IMG_JS_ARGS(env, info, status, argCount, nullptr, thisVar); + IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("Fail to get argments from info")); + + std::unique_ptr asyncContext = std::make_unique(); + status = napi_unwrap(env, thisVar, reinterpret_cast(&asyncContext->nConstructor)); + IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor), + nullptr, IMAGE_LOGE("Fail to unwrap context")); + + asyncContext->rMetadata = asyncContext->nConstructor->GetNativeMetadata(); + + IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rMetadata), nullptr, IMAGE_LOGE("Empty native rMetadata")); + + napi_create_promise(env, &(asyncContext->deferred), &result); + + IMG_CREATE_CREATE_ASYNC_WORK(env, status, "GetBlob", + [](napi_env env, void *data) { + auto context = static_cast(data); + context->arrayBufferSize = context->rMetadata->GetBlobSize(); + context->arrayBuffer = new uint8_t[context->arrayBufferSize]; + if (context->arrayBuffer != nullptr) { + context->status = context->rMetadata->GetBlob( + context->arrayBufferSize, static_cast(context->arrayBuffer)); + } else { + context->status = ERR_MEDIA_MALLOC_FAILED; + } + }, GetBlobComplete, asyncContext, asyncContext->work); + + IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), + nullptr, IMAGE_LOGE("Fail to create async work")); + return result; +} + +static void SetBlobComplete(napi_env env, napi_status status, void *data) +{ + napi_value valueParam = nullptr; + napi_get_undefined(env, &valueParam); + auto context = static_cast(data); + napi_value result[NUM_2] = {0}; + napi_get_undefined(env, &result[NUM_0]); + napi_get_undefined(env, &result[NUM_1]); + + if (context->status == SUCCESS) { + result[NUM_1] = valueParam; + } else { + ImageNapiUtils::CreateErrorObj(env, result[0], context->status, + "There is generic napi failure!"); + napi_get_undefined(env, &result[1]); + } + + if (context->deferred) { + if (context->status == SUCCESS) { + napi_resolve_deferred(env, context->deferred, result[NUM_1]); + } else { + napi_reject_deferred(env, context->deferred, result[NUM_0]); + } + } + + napi_delete_async_work(env, context->work); + delete context; + context = nullptr; +} + +napi_value MetadataNapi::SetBlob(napi_env env, napi_callback_info info) +{ + napi_value result = nullptr; + napi_get_undefined(env, &result); + napi_status status; + napi_value thisVar = nullptr; + size_t argCount = NUM_1; + napi_value argValue[NUM_1] = {0}; + + IMG_JS_ARGS(env, info, status, argCount, argValue, thisVar); + IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, IMAGE_LOGE("Fail to napi_get_cb_info")); + + std::unique_ptr asyncContext = std::make_unique(); + status = napi_unwrap(env, thisVar, reinterpret_cast(&asyncContext->nConstructor)); + IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor), + nullptr, IMAGE_LOGE("Fail to unwrap context")); + + asyncContext->rMetadata = asyncContext->nConstructor->GetNativeMetadata(); + IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->rMetadata), nullptr, IMAGE_LOGE("Empty native rMetadata")); + status = napi_get_arraybuffer_info(env, argValue[NUM_0], + &(asyncContext->arrayBuffer), &(asyncContext->arrayBufferSize)); + IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), + ImageNapiUtils::ThrowExceptionError(env, IMAGE_BAD_PARAMETER, + "Invalid args."), IMAGE_LOGE("Fail to get blob info")); + + napi_create_promise(env, &(asyncContext->deferred), &result); + + IMG_CREATE_CREATE_ASYNC_WORK(env, status, "SetBlob", + [](napi_env env, void *data) { + auto context = static_cast(data); + context->status = context->rMetadata->SetBlob( + static_cast(context->arrayBuffer), static_cast(context->arrayBufferSize)); + }, SetBlobComplete, asyncContext, asyncContext->work); + + IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), + nullptr, IMAGE_LOGE("Fail to create async work")); + return result; +} + + } // namespace Media } // namespace OHOS \ No newline at end of file diff --git a/frameworks/kits/js/common/picture_napi.cpp b/frameworks/kits/js/common/picture_napi.cpp index 016b9f38d..3ec307b2a 100644 --- a/frameworks/kits/js/common/picture_napi.cpp +++ b/frameworks/kits/js/common/picture_napi.cpp @@ -87,6 +87,8 @@ static std::vector auxiliaryPictureTypeMap = { static std::vector metadataTypeMap = { {"EXIF_METADATA", static_cast(MetadataType::EXIF), ""}, {"FRAGMENT_METADATA", static_cast(MetadataType::FRAGMENT), ""}, + {"XTSTYLE_METADATA", static_cast(MetadataType::XTSTYLE), ""}, + {"RFDATAB_METADATA", static_cast(MetadataType::RFDATAB), ""}, {"GIF_METADATA", static_cast(MetadataType::GIF), ""}, }; diff --git a/frameworks/kits/js/common/picture_ndk/image_common.cpp b/frameworks/kits/js/common/picture_ndk/image_common.cpp index a0abe9051..a7f404b31 100644 --- a/frameworks/kits/js/common/picture_ndk/image_common.cpp +++ b/frameworks/kits/js/common/picture_ndk/image_common.cpp @@ -15,9 +15,12 @@ #include "image_common.h" #include "image_common_impl.h" #include "image_utils.h" -#include "image_type.h" #include "exif_metadata.h" +#include "image_type.h" #include "fragment_metadata.h" +#include "xtstyle_metadata.h" +#include "rfdatab_metadata.h" +#include "image_log.h" #include "gif_metadata.h" #include "securec.h" #include "common_utils.h" @@ -38,6 +41,10 @@ Image_ErrorCode OH_PictureMetadata_Create(Image_MetadataType metadataType, OH_Pi exifMetadata->CreateExifdata(); } else if (metadataType == FRAGMENT_METADATA) { metadataPtr = std::make_shared(); + } else if (metadataType == XTSTYLE_METADATA) { + metadataPtr = std::make_shared(); + } else if (metadataType == RFDATAB_METADATA) { + metadataPtr = std::make_shared(); } else if (metadataType == GIF_METADATA) { metadataPtr = std::make_shared(); } else { @@ -179,6 +186,54 @@ Image_ErrorCode OH_PictureMetadata_Clone(OH_PictureMetadata *oldMetadata, OH_Pic return IMAGE_SUCCESS; } +Image_ErrorCode OH_PictureMetadata_SetBlob(OH_PictureMetadata *metadata, uint8_t *blob, size_t *blobSize) +{ + if (metadata == nullptr || blob == nullptr || blobSize == nullptr || *blobSize == 0) { + return IMAGE_BAD_PARAMETER; + } + if (!metadata->GetInnerAuxiliaryMetadata()) { + IMAGE_LOGE("blob metadata is null"); + return IMAGE_UNSUPPORTED_METADATA; + } + uint32_t ret = static_cast(metadata->GetInnerAuxiliaryMetadata()->SetBlob(blob, *blobSize)); + if (ret != IMAGE_SUCCESS) { + IMAGE_LOGE("OH_PictureMetadata_SetBlob failed"); + return IMAGE_BAD_PARAMETER; + } + return IMAGE_SUCCESS; +} + +Image_ErrorCode OH_PictureMetadata_GetBlob(OH_PictureMetadata *metadata, uint8_t *blob, size_t blobSize) +{ + if (metadata == nullptr || blob == nullptr || blobSize == 0) { + return IMAGE_BAD_PARAMETER; + } + if (!metadata->GetInnerAuxiliaryMetadata()) { + IMAGE_LOGE("blob metadata is null"); + return IMAGE_UNSUPPORTED_METADATA; + } + uint32_t ret = static_cast(metadata->GetInnerAuxiliaryMetadata()->GetBlob(blobSize, blob)); + if (ret != IMAGE_SUCCESS) { + IMAGE_LOGE("OH_PictureMetadata_GetBlob failed"); + return IMAGE_BAD_PARAMETER; + } + return IMAGE_SUCCESS; +} + +Image_ErrorCode OH_PictureMetadata_GetBlobSize(OH_PictureMetadata *metadata, size_t *blobSize) +{ + if (metadata == nullptr) { + IMAGE_LOGE("Invalid parameter: metadata is null"); + return IMAGE_BAD_PARAMETER; + } + if (!metadata->GetInnerAuxiliaryMetadata()) { + IMAGE_LOGE("Auxiliary metadata is null"); + return IMAGE_UNSUPPORTED_METADATA; + } + *blobSize = static_cast(metadata->GetInnerAuxiliaryMetadata()->GetBlobSize()); + return IMAGE_SUCCESS; +} + #ifdef __cplusplus }; #endif \ No newline at end of file diff --git a/frameworks/kits/js/common/picture_ndk/picture_native.cpp b/frameworks/kits/js/common/picture_ndk/picture_native.cpp index ede46bd0c..649e68316 100644 --- a/frameworks/kits/js/common/picture_ndk/picture_native.cpp +++ b/frameworks/kits/js/common/picture_ndk/picture_native.cpp @@ -343,7 +343,6 @@ Image_ErrorCode OH_AuxiliaryPictureNative_GetMetadata(OH_AuxiliaryPictureNative } else { metadataPtr = auxiliaryPicture->GetInnerAuxiliaryPicture()->GetMetadata(metadataTypeInner); } - if (metadataPtr == nullptr) { return IMAGE_BAD_PARAMETER; } @@ -374,7 +373,6 @@ Image_ErrorCode OH_AuxiliaryPictureNative_SetMetadata(OH_AuxiliaryPictureNative } else { auxiliaryPicture->GetInnerAuxiliaryPicture()->SetMetadata(metadataTypeInner, metadataPtr); } - return IMAGE_SUCCESS; } diff --git a/interfaces/innerkits/BUILD.gn b/interfaces/innerkits/BUILD.gn index d2072fae0..7746e53ef 100644 --- a/interfaces/innerkits/BUILD.gn +++ b/interfaces/innerkits/BUILD.gn @@ -152,6 +152,8 @@ if (use_clang_android) { "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/data_buf.cpp", "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/dng_exif_metadata_accessor.cpp", "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/exif_metadata.cpp", + "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/metadata.cpp", + "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/blob_metadata.cpp", "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp", "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/file_metadata_stream.cpp", "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/kv_metadata.cpp", @@ -337,6 +339,8 @@ if (use_mingw_win || use_clang_mac || use_clang_ios || use_clang_android) { "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/data_buf.cpp", "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/dng_exif_metadata_accessor.cpp", "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/exif_metadata.cpp", + "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/metadata.cpp", + "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/blob_metadata.cpp", "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp", "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/file_metadata_stream.cpp", "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/kv_metadata.cpp", diff --git a/interfaces/innerkits/include/blob_metadata.h b/interfaces/innerkits/include/blob_metadata.h new file mode 100644 index 000000000..15787550a --- /dev/null +++ b/interfaces/innerkits/include/blob_metadata.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_INNERKITS_INCLUDE_BLOB_METADATA_H +#define INTERFACES_INNERKITS_INCLUDE_BLOB_METADATA_H + +#include +#include "image_type.h" +#include "metadata.h" + +namespace OHOS { +namespace Media { +class BlobMetadata : public ImageMetadata { +public: + static std::atomic currentId; + BlobMetadata(); + BlobMetadata(MetadataType type); + BlobMetadata(const BlobMetadata &blobMetadata); + BlobMetadata& operator=(const BlobMetadata &blobMetadata); + ~BlobMetadata(); + int GetValue(const std::string &key, std::string &value) const override; + bool SetValue(const std::string &key, const std::string &value) override; + bool RemoveEntry(const std::string &key) override; + const ImageMetadata::PropertyMapPtr GetAllProperties() override; + MetadataType GetType() const override; + bool RemoveExifThumbnail() override; + std::shared_ptr CloneMetadata() override; + + NATIVEEXPORT uint32_t GetBlob(uint32_t bufferSize, uint8_t *dst) override; + NATIVEEXPORT uint32_t SetBlob(const uint8_t *source, const uint32_t bufferSize) override; + NATIVEEXPORT uint32_t GetBlobSize() override; + NATIVEEXPORT uint8_t* GetBlobPtr() override; + + uint32_t GetUniqueId() const; + bool Marshalling(Parcel &parcel) const override; + static BlobMetadata *Unmarshalling(Parcel &parcel); + static BlobMetadata *Unmarshalling(Parcel &parcel, PICTURE_ERR &error); + static bool WriteFileDescriptor(Parcel &parcel, int fd); + static void ReleaseMemory(void *addr, void *context, uint32_t size); + static int ReadFileDescriptor(Parcel &parcel); + bool WriteDataToParcel(Parcel &parcel, size_t size) const; + static bool ReadDataFromAshmem(Parcel &parcel, std::unique_ptr &blobMetadataPtr, + std::function readFdDefaultFunc)> readSafeFdFunc = nullptr); + static bool ReadDataFromParcel(Parcel &parcel, std::unique_ptr &blobMetadataPtr); +protected: + uint8_t *data_ = nullptr; + uint32_t dataSize_ = 0; + uint32_t uniqueId_ = 0; + MetadataType type_ = MetadataType::UNKNOWN; +}; +} // namespace Media +} // namespace OHOS +#endif // INTERFACES_INNERKITS_INCLUDE_BLOB_METADATA_H \ No newline at end of file diff --git a/interfaces/innerkits/include/image_source.h b/interfaces/innerkits/include/image_source.h index bcf81be0f..d0dbc2eb8 100644 --- a/interfaces/innerkits/include/image_source.h +++ b/interfaces/innerkits/include/image_source.h @@ -358,6 +358,8 @@ private: ImagePlugin::DecodeContext &context, ImagePlugin::PlImageInfo &plInfo); ImagePlugin::DecodeContext DecodeImageDataToContextExtended(uint32_t index, ImageInfo &info, ImagePlugin::PlImageInfo &plInfo, ImageEvent &imageEvent, uint32_t &errorCode); + void DecodeBlobMetaData(std::unique_ptr &picture, const std::set &metadataTypes, + ImageInfo &info, uint32_t &errorCode); void SetPixelMapColorSpace(ImagePlugin::DecodeContext& context, std::unique_ptr& pixelMap, std::unique_ptr& decoder); bool IsSingleHdrImage(ImageHdrType type); diff --git a/interfaces/innerkits/include/image_type.h b/interfaces/innerkits/include/image_type.h index 7debf06f2..d45248639 100644 --- a/interfaces/innerkits/include/image_type.h +++ b/interfaces/innerkits/include/image_type.h @@ -17,6 +17,7 @@ #define INTERFACES_INNERKITS_INCLUDE_IMAGE_TYPE_H_ #include +#include #include #include #include @@ -52,6 +53,12 @@ namespace Media { #define HEIF_AUXTTYPE_ID_UNREFOCUS_MAP "urn:com:huawei:photo:5:0:0:aux:unrefocusmap" #define HEIF_AUXTTYPE_ID_LINEAR_MAP "urn:com:huawei:photo:5:0:0:aux:linearhmap" #define HEIF_AUXTTYPE_ID_FRAGMENT_MAP "urn:com:huawei:photo:5:0:0:aux:fragmentmap" +#define HEIF_METADATA_ID_XTSTYLE "urn:com:huawei:photo:5:1:0:meta:xtstyle" + +#define METADATA_TAG_RFDATAB "RfDataB\0" +#define METADATA_TAG_XTSTYLE "XtStyle\0" +#define METADATA_TAG_STDATA "STData\0" + constexpr uint8_t ASTC_EXTEND_INFO_TLV_NUM_6 = 6; @@ -413,12 +420,24 @@ struct AuxiliaryPictureInfo { enum class MetadataType { EXIF = 1, FRAGMENT = 2, + XTSTYLE = 3, + RFDATAB = 4, GIF = 5, - UNKNOWN = 0 + STDATA = 6, + RESMAP = 7, + UNKNOWN = 0, +}; + +static const std::map BLOB_METADATA_TAG_MAP = { + {MetadataType::XTSTYLE, METADATA_TAG_XTSTYLE}, + {MetadataType::RFDATAB, METADATA_TAG_RFDATAB}, + {MetadataType::RESMAP, METADATA_TAG_RESMAP}, + {MetadataType::STDATA, METADATA_TAG_STDATA}, }; struct DecodingOptionsForPicture { std::set desireAuxiliaryPictures; + std::set desiredMetadatas; PixelFormat desiredPixelFormat = PixelFormat::RGBA_8888; AllocatorType allocatorType = AllocatorType::DMA_ALLOC; }; diff --git a/interfaces/innerkits/include/metadata.h b/interfaces/innerkits/include/metadata.h index db2b9d365..58cef7469 100644 --- a/interfaces/innerkits/include/metadata.h +++ b/interfaces/innerkits/include/metadata.h @@ -34,6 +34,10 @@ public: virtual std::shared_ptr CloneMetadata() = 0; virtual MetadataType GetType() const = 0; virtual bool RemoveExifThumbnail() = 0; + virtual uint32_t GetBlob(uint32_t bufferSize, uint8_t *dst); + virtual uint32_t SetBlob(const uint8_t *source, const uint32_t bufferSize); + virtual uint32_t GetBlobSize(); + virtual uint8_t* GetBlobPtr(); }; } // namespace Media } // namespace OHOS diff --git a/interfaces/innerkits/include/picture.h b/interfaces/innerkits/include/picture.h index 498b6ffd2..9cc7a96af 100644 --- a/interfaces/innerkits/include/picture.h +++ b/interfaces/innerkits/include/picture.h @@ -18,6 +18,8 @@ #include "pixel_map.h" #include "auxiliary_picture.h" +#include "xtstyle_metadata.h" +#include "rfdatab_metadata.h" #include "gif_metadata.h" #include "image_type.h" #include @@ -52,17 +54,22 @@ public: NATIVEEXPORT virtual bool Marshalling(Parcel &data) const override; NATIVEEXPORT static Picture *Unmarshalling(Parcel &data); NATIVEEXPORT static Picture *Unmarshalling(Parcel &data, PICTURE_ERR &error); - NATIVEEXPORT int32_t CreateExifMetadata(); - NATIVEEXPORT int32_t SetExifMetadata(sptr &surfaceBuffer); - NATIVEEXPORT int32_t SetExifMetadata(std::shared_ptr exifMetadata); + NATIVEEXPORT uint32_t CreateExifMetadata(); + NATIVEEXPORT uint32_t SetExifMetadata(sptr &surfaceBuffer); + NATIVEEXPORT uint32_t SetExifMetadata(std::shared_ptr exifMetadata); NATIVEEXPORT std::shared_ptr GetExifMetadata(); NATIVEEXPORT bool SetMaintenanceData(sptr &surfaceBuffer); NATIVEEXPORT sptr GetMaintenanceData() const; + NATIVEEXPORT uint32_t SetXtStyleMetadata(std::shared_ptr xtStyleMetadata); + NATIVEEXPORT std::shared_ptr GetXtStyleMetadata(); + NATIVEEXPORT uint32_t SetRfDataBMetadata(std::shared_ptr RfDataBMetadata); + NATIVEEXPORT std::shared_ptr GetRfDataBMetadata(); NATIVEEXPORT bool MarshalMetadata(Parcel &data) const; NATIVEEXPORT static bool UnmarshalMetadata(Parcel &parcel, Picture &picture, PICTURE_ERR &error); NATIVEEXPORT static void DumpPictureIfDumpEnabled(Picture& picture, std::string dumpType); NATIVEEXPORT std::shared_ptr GetMetadata(MetadataType type); NATIVEEXPORT uint32_t SetMetadata(MetadataType type, std::shared_ptr metadata); + NATIVEEXPORT uint32_t SetBlobMetadataByType(const std::vector& metadata, MetadataType type); NATIVEEXPORT static bool IsValidPictureMetadataType(MetadataType metadataType); private: diff --git a/interfaces/innerkits/include/rfdatab_metadata.h b/interfaces/innerkits/include/rfdatab_metadata.h new file mode 100644 index 000000000..16b9e8bb6 --- /dev/null +++ b/interfaces/innerkits/include/rfdatab_metadata.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_INNERKITS_INCLUDE_RFDATAB_METADATA_H +#define INTERFACES_INNERKITS_INCLUDE_RFDATAB_METADATA_H + +#include +#include "image_type.h" +#include "blob_metadata.h" + +namespace OHOS { +namespace Media { +class RfDataBMetadata : public BlobMetadata { +public: + RfDataBMetadata() : BlobMetadata(MetadataType::RFDATAB) {}; +}; +} // namespace Media +} // namespace OHOS +#endif // INTERFACES_INNERKITS_INCLUDE_RFDATAB_METADATA_H \ No newline at end of file diff --git a/interfaces/innerkits/include/xtstyle_metadata.h b/interfaces/innerkits/include/xtstyle_metadata.h new file mode 100644 index 000000000..2ec047cc8 --- /dev/null +++ b/interfaces/innerkits/include/xtstyle_metadata.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INTERFACES_INNERKITS_INCLUDE_XT_METADATA_H +#define INTERFACES_INNERKITS_INCLUDE_XT_METADATA_H + +#include "image_type.h" +#include "blob_metadata.h" + +namespace OHOS { +namespace Media { + +class XtStyleMetadata : public BlobMetadata { +public: + XtStyleMetadata() : BlobMetadata(MetadataType::XTSTYLE) {}; +}; +} // namespace Media +} // namespace OHOS +#endif // INTERFACES_INNERKITS_INCLUDE_XT_METADATA_H + diff --git a/interfaces/innerkits/libimage_native.versionscript b/interfaces/innerkits/libimage_native.versionscript index 0474573fd..ceacf359d 100644 --- a/interfaces/innerkits/libimage_native.versionscript +++ b/interfaces/innerkits/libimage_native.versionscript @@ -34,6 +34,10 @@ *IncrementalSourceStream*CreateSourceStream*; *NativeImage*; *ExifMetadata*; + *ImageMetadata*; + *BlobMetadata*; + *XtStyleMetadata*; + *RfDataBMetadata*; *ImageFormatConvert*; *PixelYuv*; *Picture*; diff --git a/interfaces/kits/js/common/include/metadata_napi.h b/interfaces/kits/js/common/include/metadata_napi.h index c7edb4f0c..ffecf519d 100644 --- a/interfaces/kits/js/common/include/metadata_napi.h +++ b/interfaces/kits/js/common/include/metadata_napi.h @@ -45,7 +45,9 @@ private: static napi_value SetProperties(napi_env env, napi_callback_info info); static napi_value GetAllProperties(napi_env env, napi_callback_info info); static napi_value Clone(napi_env env, napi_callback_info info); - + static napi_value GetBlob(napi_env env, napi_callback_info info); + static napi_value SetBlob(napi_env env, napi_callback_info info); + void release(); static thread_local napi_ref sConstructor_; static thread_local std::shared_ptr sMetadata_; diff --git a/interfaces/kits/native/include/image/image_common.h b/interfaces/kits/native/include/image/image_common.h index 7b813af1e..fbe841de4 100644 --- a/interfaces/kits/native/include/image/image_common.h +++ b/interfaces/kits/native/include/image/image_common.h @@ -169,6 +169,11 @@ typedef enum { * @since 13 */ IMAGE_UNSUPPORTED_MEMORY_FORMAT = 7600205, + /** + * @error Invalid parameter. + * @since 19 + */ + IMAGE_INVALID_PARAMETER = 7600206, /** failed to allocate memory */ IMAGE_ALLOC_FAILED = 7600301, /** memory copy failed */ @@ -209,16 +214,11 @@ typedef enum { IMAGE_SOURCE_ALLOC_FAILED = 7700302, /** * @error Invalid parameter for ImagePacker. - * @since 20 + * @since 19 */ IMAGE_PACKER_INVALID_PARAMETER = 7800202, /** encode failed */ IMAGE_ENCODE_FAILED = 7800301, - /** - * @error Invalid parameter for picture. - * @since 19 - */ - IMAGE_INVALID_PARAMETER = 7800302, /** * @error Invalid parameter for ImageReceiver * @since 20 @@ -261,6 +261,14 @@ typedef enum { * Fragment metadata. */ FRAGMENT_METADATA = 2, + /* + * Xtstyle metadata. + */ + XTSTYLE_METADATA = 3, + /* + * RfDataB metadata. + */ + RFDATAB_METADATA = 4, /** * Metadata of a GIF image. @@ -312,15 +320,56 @@ Image_ErrorCode OH_PictureMetadata_GetProperty(OH_PictureMetadata *metadata, Ima */ Image_ErrorCode OH_PictureMetadata_SetProperty(OH_PictureMetadata *metadata, Image_String *key, Image_String *value); +/** + * @brief Sets the blob data in picture metadata. + * + * @param metadata The PictureMetadata pointer to be operated. + * @param blob The pointer to the blob data. + * @param blobSize The size of the blob data. + * @return Image functions result code. + * {@link IMAGE_SUCCESS} if the execution is successful. + * {@link IMAGE_BAD_PARAMETER} metadata is nullptr, or blob is nullptr, or SetBlob is failed. + * {@link IMAGE_UNSUPPORTED_METADATA} unsupported metadata type. + * @since 16 + */ +Image_ErrorCode OH_PictureMetadata_SetBlob(OH_PictureMetadata *metadata, uint8_t *blob, size_t *blobSize); + +/** + * @brief Gets the blob data from picture metadata. + * + * @param metadata The PictureMetadata pointer to be operated. + * @param blob The pointer to store the blob data. + * @param blobSize The size of the blob data. + * @return Image functions result code. + * {@link IMAGE_SUCCESS} if the execution is successful. + * {@link IMAGE_BAD_PARAMETER} metadata is nullptr, or blob is nullptr, or Getblob is failed. + * {@link IMAGE_UNSUPPORTED_METADATA} unsupported metadata type. + * @since 16 + */ +Image_ErrorCode OH_PictureMetadata_GetBlob(OH_PictureMetadata *metadata, uint8_t *blob, size_t blobSize); + +/** + * @brief Gets the size of the blob data in picture metadata. + * + * @param metadata The PictureMetadata pointer to be operated. + * @param blobSize The size of the blob data. + * @return Image functions result code. + * {@link IMAGE_SUCCESS} if the execution is successful. + * {@link IMAGE_BAD_PARAMETER} metadata is nullptr. + * {@link IMAGE_UNSUPPORTED_METADATA} unsupported metadata type. + * @since 16 + */ +Image_ErrorCode OH_PictureMetadata_GetBlobSize(OH_PictureMetadata *metadata, size_t *blobSize); + /** * @brief Obtains the property of picture metadata. The output value.data is null-terminated. * * @param metadata The PictureMetadata pointer will be operated. * @param key The property's key. * @param value The property's value. - * @return Image functions result code: - * {@link IMAGE_SUCCESS} if successful. - * {@link IMAGE_INVALID_PARAMETER} metadata or key or value is nullptr. + * @return Image functions result code. + * {@link IMAGE_SUCCESS} if the execution is successful. + * {@link IMAGE_INVALID_PARAMETER} metadata is nullptr, or key is nullptr, or value is nullptr. * {@link IMAGE_UNSUPPORTED_METADATA} unsupported metadata type, or the metadata type does not match the * auxiliary picture type. * @since 19 @@ -1492,4 +1541,4 @@ static const char *IMAGE_PROPERTY_GIF_DISPOSAL_TYPE = "GifDisposalType"; #endif /** @} */ -#endif // INTERFACES_KITS_NATIVE_INCLUDE_IMAGE_IMAGE_COMMON_H_ +#endif // INTERFACES_KITS_NATIVE_INCLUDE_IMAGE_IMAGE_COMMON_H_ \ No newline at end of file diff --git a/plugins/common/libs/image/libextplugin/include/ext_decoder.h b/plugins/common/libs/image/libextplugin/include/ext_decoder.h index 70c16cb00..da84263d1 100644 --- a/plugins/common/libs/image/libextplugin/include/ext_decoder.h +++ b/plugins/common/libs/image/libextplugin/include/ext_decoder.h @@ -83,6 +83,8 @@ public: bool IsSupportICCProfile() override; #endif static void FillYuvInfo(DecodeContext &context, SkImageInfo &dstInfo); + bool GetHeifMetadataBlob(std::vector& metadata, Media::MetadataType type) override; + private: typedef struct FrameCacheInfo { int width; diff --git a/plugins/common/libs/image/libextplugin/include/ext_encoder.h b/plugins/common/libs/image/libextplugin/include/ext_encoder.h index 6e1c56133..743e0d1a2 100644 --- a/plugins/common/libs/image/libextplugin/include/ext_encoder.h +++ b/plugins/common/libs/image/libextplugin/include/ext_encoder.h @@ -91,12 +91,15 @@ private: uint32_t EncodeJpegPictureDualVivid(SkWStream& skStream); uint32_t EncodeJpegPictureSdr(SkWStream& skStream); void EncodeJpegAuxiliaryPictures(SkWStream& skStream); + void EncodeJpegAllBlobMetadata(SkWStream& skStream); uint32_t WriteJpegCodedData(std::shared_ptr& auxPicture, SkWStream& skStream); void EncodeLogVideoDataToBlobMetadata(sptr& surfaceBuffer, SkWStream& skStream); uint32_t SpliceFragmentStream(SkWStream& skStream, sk_sp& skData); uint32_t WriteJpegUncodedData(std::shared_ptr& auxPicture, SkWStream& skStream); void WriteJpegAuxiliarySizeAndTag(uint32_t size, std::shared_ptr& auxPicture, SkWStream& skStream); + void EncodeHeifMetadata(std::vector &refs, + std::vector &inputMetas); uint32_t EncodeHeifPicture(sptr& mainSptr, SkImageInfo mainInfo, bool sdrIsSRGB); sk_sp GetImageEncodeData(sptr& surfaceBuffer, SkImageInfo info, bool needExif); uint32_t EncodeImageBySurfaceBuffer(sptr& surfaceBuffer, SkImageInfo info, @@ -153,6 +156,8 @@ private: bool AssembleExifMetaItem(std::vector& metaItems); void AssembleExifRefItem(std::vector& refs); void AssembleAuxiliaryRefItem(AuxiliaryPictureType type, std::vector& refs); + bool AssembleBlobMetaItem(MetadataType type, std::vector& metaItems); + void AssembleBlobRefItem(MetadataType type, std::vector& refs); #endif uint32_t PixelmapEncode(ExtWStream& wStream); uint32_t EncodeHeifByPixelmap(Media::PixelMap* pixelmap, const PlEncodeOptions& opts); @@ -162,8 +167,8 @@ private: OutputDataStream* output_ = nullptr; PlEncodeOptions opts_; Media::PixelMap* pixelmap_ = nullptr; - Media::Picture* picture_ = nullptr; std::vector> tmpMemoryList_; + Media::Picture* picture_ = nullptr; }; } // namespace ImagePlugin } // namespace OHOS diff --git a/plugins/common/libs/image/libextplugin/include/hdr/jpeg_mpf_parser.h b/plugins/common/libs/image/libextplugin/include/hdr/jpeg_mpf_parser.h index 235982de3..812ad603d 100644 --- a/plugins/common/libs/image/libextplugin/include/hdr/jpeg_mpf_parser.h +++ b/plugins/common/libs/image/libextplugin/include/hdr/jpeg_mpf_parser.h @@ -38,6 +38,8 @@ public: bool ParsingAuxiliaryPictures(uint8_t* data, uint32_t dataSize, bool isBigEndian = true); std::vector images_; static bool ParsingFragmentMetadata(uint8_t* data, uint32_t size, Rect& fragmentRect, bool isBigEndian = true); + static bool ParsingBlobMetadata(uint8_t* data, uint32_t size, + std::vector &metadata, MetadataType type); private: bool ParsingMpIndexIFD(uint8_t* data, uint32_t size, uint32_t dataOffset, bool isBigEndian); diff --git a/plugins/common/libs/image/libextplugin/include/heif_impl/HeifDecoderImpl.h b/plugins/common/libs/image/libextplugin/include/heif_impl/HeifDecoderImpl.h index 1890418d0..46b4ac943 100644 --- a/plugins/common/libs/image/libextplugin/include/heif_impl/HeifDecoderImpl.h +++ b/plugins/common/libs/image/libextplugin/include/heif_impl/HeifDecoderImpl.h @@ -76,6 +76,8 @@ public: void setAuxiliaryDstBuffer(uint8_t* dstBuffer, size_t dstSize, size_t rowStride, void *context); void getFragmentMetadata(Media::Rect& fragmentMetadata); bool SwDecode(bool isSharedMemory = false); + void GetMetadataBlob(std::vector& metadata, Media::MetadataType type); + bool IsHeifGainmapYuv400(); bool IsHeifAlphaYuv400(); void SetSampleFormat(uint32_t sampleSize, ColorManager::ColorSpaceName colorSpaceName, bool isColorSpaceFromCicp); diff --git a/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/box/item_info_box.h b/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/box/item_info_box.h index 9bbb1144b..463e6b339 100644 --- a/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/box/item_info_box.h +++ b/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/box/item_info_box.h @@ -53,6 +53,8 @@ public: void SetItemName(const std::string &name) { itemName_ = name; } + const std::string &GetItemName() const { return itemName_; } + const std::string &GetContentType() const { return contentType_; } const std::string &GetContentEncoding() const { return contentEncoding_; } diff --git a/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/heif_image.h b/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/heif_image.h index 04a82bb87..c7ab1fb97 100644 --- a/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/heif_image.h +++ b/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/heif_image.h @@ -109,13 +109,19 @@ public: void SetTmapBoxId(heif_item_id id); void SetStaticMetadata(std::vector& display, std::vector& lightInfo); void SetUWAInfo(std::vector& uwaInfo); + void SetXtStyleData(std::vector& xtStyleMetadata); + void SetRfDataBData(std::vector& rfDataBMetadata); void SetISOMetadata(std::vector& isoMetadata); void SetFragmentMetadata(HeifFragmentMetadata fragmentMetadata); + void SetSTDataMetaData(std::vector& stDataMetadata); std::vector GetDisplayInfo(); std::vector GetLightInfo(); std::vector GetUWAInfo(); std::vector GetISOMetadata(); HeifFragmentMetadata GetFragmentMetadata(); + std::vector GetXtStyleData(); + std::vector GetRfDataBData(); + std::vector GetSTDataMetaData(); private: heif_item_id itemId_ = 0; @@ -153,6 +159,9 @@ private: std::vector uwaInfo_; std::vector isoMetadata_; HeifFragmentMetadata fragmentMetadata_; + std::vector xtStyledata_; + std::vector rfDataBdata_; + std::vector stDatadata_; }; } // namespace ImagePlugin } // namespace OHOS diff --git a/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/heif_parser.h b/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/heif_parser.h index f5f5ea460..9af7ebdde 100644 --- a/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/heif_parser.h +++ b/plugins/common/libs/image/libextplugin/include/heif_impl/heif_parser/heif_parser.h @@ -208,6 +208,12 @@ private: void ExtractFragmentMetadata(const heif_item_id& itemId); + void ExtractXtStyleMetadata(const std::vector& allItemIds); + + void ExtractRfDataBMetadata(const std::vector& allItemIds); + + void ExtractSTDataMetadata(const std::vector& allItemIds); + void SetTiffOffset(); }; } // namespace ImagePlugin diff --git a/plugins/common/libs/image/libextplugin/src/ext_decoder.cpp b/plugins/common/libs/image/libextplugin/src/ext_decoder.cpp index c31f5d784..024584b5c 100644 --- a/plugins/common/libs/image/libextplugin/src/ext_decoder.cpp +++ b/plugins/common/libs/image/libextplugin/src/ext_decoder.cpp @@ -2724,6 +2724,25 @@ bool ExtDecoder::GetHeifFragmentMetadata(Media::Rect &metadata) return false; } +bool ExtDecoder::GetHeifMetadataBlob(vector& metadata, MetadataType type) +{ +#ifdef HEIF_HW_DECODE_ENABLE + if (codec_ == nullptr) { + IMAGE_LOGE("Check codec_ failed!"); + return false; + } + + auto decoder = reinterpret_cast(codec_->getHeifContext()); + if (decoder == nullptr) { + IMAGE_LOGE("Get heif decoder failed."); + return false; + } + decoder->GetMetadataBlob(metadata, type); + return true; +#endif + return false; +} + bool ExtDecoder::DecodeHeifGainMap(DecodeContext& context) { #ifdef HEIF_HW_DECODE_ENABLE diff --git a/plugins/common/libs/image/libextplugin/src/ext_encoder.cpp b/plugins/common/libs/image/libextplugin/src/ext_encoder.cpp index f67bfe38f..41c0296c6 100644 --- a/plugins/common/libs/image/libextplugin/src/ext_encoder.cpp +++ b/plugins/common/libs/image/libextplugin/src/ext_encoder.cpp @@ -139,6 +139,9 @@ namespace { constexpr static uint32_t UNREFOCUS_MAP_ITEM_ID = 6; constexpr static uint32_t LINEAR_MAP_ITEM_ID = 7; constexpr static uint32_t FRAGMENT_MAP_ITEM_ID = 8; + constexpr static uint32_t XTSTYLE_META_ITEM_ID = 9; + constexpr static uint32_t RFDATAB_META_ITEM_ID = 10; + constexpr static uint32_t STDATA_META_ITEM_ID = 11; const static std::string COMPRESS_TYPE_TMAP = "tmap"; const static std::string COMPRESS_TYPE_HEVC = "hevc"; const static std::string COMPRESS_TYPE_NONE = "none"; @@ -149,17 +152,24 @@ namespace { const static std::string IMAGE_DATA_TAG = "Heif Encoder Image"; const static std::string HDR_GAINMAP_TAG = "Heif Encoder Gainmap"; const static std::string EXIF_ASHMEM_TAG = "Heif Encoder Exif"; + const static std::string XTSTYLE_ASHMEM_TAG = "Heif Encoder XtStyle"; + const static std::string RFDATAB_ASHMEM_TAG = "Heif Encoder RfDataB"; + const static std::string STDATA_ASHMEM_TAG = "Heif Encoder STData"; const static std::string GAINMAP_IMAGE_ITEM_NAME = "Gain map Image"; const static std::string DEPTH_MAP_ITEM_NAME = "Depth Map Image"; const static std::string UNREFOCUS_MAP_ITEM_NAME = "Unrefocus Map Image"; const static std::string LINEAR_MAP_ITEM_NAME = "Linear Map Image"; const static std::string FRAGMENT_MAP_ITEM_NAME = "Fragment Map Image"; + const static std::string XTSTYLE_METADATA_ITEM_NAME = "urn:com:huawei:photo:5:1:0:meta:xtstyle"; + const static std::string RFDATAB_METADATA_ITEM_NAME = "RfDataB\0"; + const static std::string STDATA_METADATA_ITEM_NAME = "STData\0"; const static size_t DEFAULT_OUTPUT_SIZE = 35 * 1024 * 1024; // 35M const static uint16_t STATIC_METADATA_COLOR_SCALE = 50000; const static uint16_t STATIC_METADATA_LUM_SCALE = 10000; const static uint8_t INDEX_ZERO = 0; const static uint8_t INDEX_ONE = 1; const static uint8_t INDEX_TWO = 2; + const static int32_t INVALID_FD = -1; constexpr uint32_t DEFAULT_DENOMINATOR = 1000000; constexpr uint8_t GAINMAP_CHANNEL_MULTI = 3; constexpr uint8_t GAINMAP_CHANNEL_SINGLE = 1; @@ -170,11 +180,18 @@ namespace { constexpr uint32_t PLACE_HOLDER_LENGTH = 1; constexpr uint32_t LOW_QUALITY_BOUNDARY = 50; constexpr uint32_t RGBA8888_PIXEL_BYTES = 4; - constexpr uint32_t HIGHEST_QUALITY = 100; - constexpr uint32_t DEFAULT_QUALITY = 75; static constexpr uint32_t TRANSFUNC_OFFSET = 8; static constexpr uint32_t MATRIX_OFFSET = 8; static constexpr uint32_t RANGE_OFFSET = 8; + constexpr uint32_t HIGHEST_QUALITY = 100; + constexpr uint32_t DEFAULT_QUALITY = 75; + + const static std::map> + HEIF_METADATA_MAPPING = { + {MetadataType::XTSTYLE, std::make_tuple(XTSTYLE_META_ITEM_ID, XTSTYLE_ASHMEM_TAG, XTSTYLE_METADATA_ITEM_NAME)}, + {MetadataType::RFDATAB, std::make_tuple(RFDATAB_META_ITEM_ID, RFDATAB_ASHMEM_TAG, RFDATAB_METADATA_ITEM_NAME)}, + {MetadataType::STDATA, std::make_tuple(STDATA_META_ITEM_ID, STDATA_ASHMEM_TAG, STDATA_METADATA_ITEM_NAME)} + }; // exif/0/0 constexpr uint8_t EXIF_PRE_TAG[EXIF_PRE_SIZE] = { @@ -208,6 +225,7 @@ static const std::map DEFAULT_AUXILIARY_TAG_M {AuxiliaryPictureType::FRAGMENT_MAP, AUXILIARY_TAG_FRAGMENT_MAP}, }; +static const uint8_t NUM_2 = 2; static const uint8_t NUM_3 = 3; static const uint8_t NUM_4 = 4; static const uint8_t RGBA_BIT_DEPTH = 4; @@ -1097,8 +1115,8 @@ std::shared_ptr ExtEncoder::AssembleHdrBaseImageItem(sptrcompressType = COMPRESS_TYPE_HEVC; item->quality = opts.quality; item->pixelBuffer = sptr::MakeSptr(surfaceBuffer->GetBufferHandle()); - item->sharedProperties.fd = -1; - item->pixelSharedBuffer.fd = -1; + item->sharedProperties.fd = INVALID_FD; + item->pixelSharedBuffer.fd = INVALID_FD; ColourInfo colorInfo; GetColourInfo(color, colorInfo); ContentLightLevel light; @@ -1134,8 +1152,8 @@ std::shared_ptr ExtEncoder::AssembleGainmapImageItem(sptrisHidden = true; item->compressType = COMPRESS_TYPE_HEVC; item->quality = opts.quality; - item->sharedProperties.fd = -1; - item->pixelSharedBuffer.fd = -1; + item->sharedProperties.fd = INVALID_FD; + item->pixelSharedBuffer.fd = INVALID_FD; item->pixelBuffer = sptr::MakeSptr(surfaceBuffer->GetBufferHandle()); ColourInfo colorInfo; GetColourInfo(color, colorInfo); @@ -1240,8 +1258,8 @@ ImageItem ExtEncoder::InitAuxiliaryImageItem(uint32_t id, std::string itemName) item.isPrimary = false; item.isHidden = true; item.quality = opts_.quality; - item.sharedProperties.fd = -1; - item.pixelSharedBuffer.fd = -1; + item.sharedProperties.fd = INVALID_FD; + item.pixelSharedBuffer.fd = INVALID_FD; if (id == DEPTH_MAP_ITEM_ID || id == LINEAR_MAP_ITEM_ID) { item.compressType = COMPRESS_TYPE_NONE; } else { @@ -1581,8 +1599,8 @@ uint32_t ExtEncoder::EncodeHeifSdrImage(sptr& sdr, SkImageInfo sd item.isHidden = false; item.compressType = COMPRESS_TYPE_HEVC; item.quality = opts_.quality; - item.sharedProperties.fd = -1; - item.pixelSharedBuffer.fd = -1; + item.sharedProperties.fd = INVALID_FD; + item.pixelSharedBuffer.fd = INVALID_FD; ImageInfo info; pixelmap_->GetImageInfo(info); #ifdef USE_M133_SKIA @@ -1735,6 +1753,18 @@ uint32_t ExtEncoder::EncodeEditScenePicture() return errorCode; } +void ExtEncoder::EncodeHeifMetadata(std::vector &refs, std::vector &inputMetas) +{ + if (AssembleExifMetaItem(inputMetas)) { + AssembleExifRefItem(refs); + } + for (const auto& iter : HEIF_METADATA_MAPPING) { + if (AssembleBlobMetaItem(iter.first, inputMetas)) { + AssembleBlobRefItem(iter.first, refs); + } + } +} + uint32_t ExtEncoder::EncodeHeifPicture(sptr& mainSptr, SkImageInfo mainInfo, bool sdrIsSRGB) { #ifdef HEIF_HW_ENCODE_ENABLE @@ -1772,9 +1802,7 @@ uint32_t ExtEncoder::EncodeHeifPicture(sptr& mainSptr, SkImageInf } bool cond = error != SUCCESS; CHECK_ERROR_RETURN_RET(cond, error); - if (AssembleExifMetaItem(inputMetas)) { - AssembleExifRefItem(refs); - } + EncodeHeifMetadata(refs, inputMetas); error = AssembleHeifAuxiliaryPicture(inputImgs, refs); cond = error != SUCCESS; CHECK_ERROR_RETURN_RET(cond, error); @@ -1858,6 +1886,7 @@ uint32_t ExtEncoder::EncodeJpegPictureDualVividInner(SkWStream& skStream, std::s if (error == SUCCESS) { sk_sp hdrSkData = hdrStream.detachAsData(); skStream.write(hdrSkData->data(), hdrSkData->size()); + EncodeJpegAllBlobMetadata(skStream); EncodeJpegAuxiliaryPictures(skStream); } return error; @@ -1905,6 +1934,7 @@ uint32_t ExtEncoder::EncodeJpegPictureSdr(SkWStream& skStream) IMAGE_LOGD("%{public}s encode hdr picture result is: %{public}u", __func__, error); } if (error == SUCCESS) { + EncodeJpegAllBlobMetadata(skStream); EncodeJpegAuxiliaryPictures(skStream); } return error; @@ -1980,6 +2010,34 @@ void ExtEncoder::EncodeJpegAuxiliaryPictures(SkWStream& skStream) } } +void ExtEncoder::EncodeJpegAllBlobMetadata(SkWStream& skStream) +{ + ImageFuncTimer imageFuncTimer("%s enter", __func__); + if (picture_ == nullptr || opts_.needsPackProperties == false) { + return; + } + for (const auto& iter : BLOB_METADATA_TAG_MAP) { + auto metadataPtr = picture_->GetMetadata(iter.first); + if (metadataPtr == nullptr) { + continue; + } + uint8_t* bytes = metadataPtr->GetBlobPtr(); + uint32_t writeSize = metadataPtr->GetBlobSize(); + if (bytes == nullptr || writeSize == 0) { + continue; + } + IMAGE_LOGI("%{public}s try to encode blob metadata, type is: %{public}d, datasize : %{public}u", + __func__, iter.first, writeSize); + skStream.write(bytes, writeSize); + std::vector dataSize = JpegMpfPacker::PackDataSize(writeSize, false); + skStream.write(dataSize.data(), dataSize.size()); + std::string tagName = iter.second; + std::vector dataTag(tagName.begin(), tagName.end()); + dataTag.push_back(0); + skStream.write(dataTag.data(), dataTag.size()); + } +} + bool ConvertBufferToData(sptr& surfaceBuffer, std::vector& pixels) { if (surfaceBuffer == nullptr) { @@ -2387,8 +2445,8 @@ std::shared_ptr ExtEncoder::AssembleTmapImageItem(ColorManager::Color item->isHidden = false; item->compressType = COMPRESS_TYPE_TMAP; item->quality = opts.quality; - item->sharedProperties.fd = -1; - item->pixelSharedBuffer.fd = -1; + item->sharedProperties.fd = INVALID_FD; + item->pixelSharedBuffer.fd = INVALID_FD; ColourInfo colorInfo; GetColourInfo(color, colorInfo); ContentLightLevel light; @@ -2434,8 +2492,8 @@ std::shared_ptr ExtEncoder::AssemblePrimaryImageItem(sptrisHidden = false; item->compressType = COMPRESS_TYPE_HEVC; item->quality = opts.quality; - item->sharedProperties.fd = -1; - item->pixelSharedBuffer.fd = -1; + item->sharedProperties.fd = INVALID_FD; + item->pixelSharedBuffer.fd = INVALID_FD; #ifdef USE_M133_SKIA sk_sp iccProfile = icc_from_color_space(ToSkInfo(pixelmap_), nullptr, nullptr); #else @@ -2465,11 +2523,11 @@ void ExtEncoder::AssembleExifRefItem(std::vector& refs) refs.push_back(*item); } -void inline FreeExifBlob(uint8_t** exifBlob) +void inline FreeBlob(uint8_t** Blob) { - if (exifBlob != nullptr && *exifBlob != nullptr) { - free(*exifBlob); - *exifBlob = nullptr; + if (Blob != nullptr && *Blob != nullptr) { + free(*Blob); + *Blob = nullptr; } } @@ -2497,10 +2555,10 @@ bool ExtEncoder::AssembleExifMetaItem(std::vector& metaItems) auto item = std::make_shared(); item->id = EXIF_META_ITEM_ID; item->itemName = "exif"; - item->data.fd = -1; + item->data.fd = INVALID_FD; std::shared_ptr propertyAshmem = AllocateNewSharedMem(exifSize + EXIF_PRE_SIZE, EXIF_ASHMEM_TAG); if (propertyAshmem == nullptr) { - FreeExifBlob(&exifBlob); + FreeBlob(&exifBlob); IMAGE_LOGE("AssembleExifMetaItem alloc propertyAshmem failed"); return false; } @@ -2515,7 +2573,7 @@ bool ExtEncoder::AssembleExifMetaItem(std::vector& metaItems) item->data.filledLen = propertyAshmem->data.size; metaItems.push_back(*item); } - FreeExifBlob(&exifBlob); + FreeBlob(&exifBlob); return fillRes; } @@ -2569,6 +2627,62 @@ void ExtEncoder::AssembleAuxiliaryRefItem(AuxiliaryPictureType type, std::vector } refs.push_back(*item); } + +void ExtEncoder::AssembleBlobRefItem(MetadataType type, std::vector& refs) +{ + auto metadataTuple = HEIF_METADATA_MAPPING.at(type); + auto item = std::make_shared(); + item->type = ReferenceType::CDSC; + item->from = std::get<0>(metadataTuple); + item->to.resize(INDEX_ONE); + item->to[INDEX_ZERO] = PRIMARY_IMAGE_ITEM_ID; + refs.push_back(*item); +} + +bool ExtEncoder::AssembleBlobMetaItem(MetadataType type, std::vector& metaItems) +{ + auto metadataTuple = HEIF_METADATA_MAPPING.at(type); + if (!opts_.needsPackProperties) { + IMAGE_LOGD("no need encode blob: %{public}d", type); + return false; + } + if (picture_ == nullptr || picture_->GetMetadata(type) == nullptr) { + IMAGE_LOGE("fail to get picture or fail to get blob"); + return false; + } + auto blobMetadata = picture_->GetMetadata(type); + uint32_t blobDataSize = blobMetadata->GetBlobSize(); + if (blobDataSize == 0) { + IMAGE_LOGE("blob size is 0"); + return false; + } + auto blobDataPtr = blobMetadata->GetBlobPtr(); + if (blobDataPtr == nullptr) { + IMAGE_LOGE("AssembleBlobMetaItem getBlob is nullptr"); + return false; + } + + auto item = std::make_shared(); + item->id = std::get<0>(metadataTuple); + item->itemName = std::get(metadataTuple); + item->data.fd = INVALID_FD; + std::shared_ptr propertyAshmem = AllocateNewSharedMem(blobDataSize, std::get<1>(metadataTuple)); + if (propertyAshmem == nullptr) { + IMAGE_LOGE("AssembleBlobMetaItem alloc propertyAshmem failed"); + return false; + } + tmpMemoryList_.push_back(propertyAshmem); + uint8_t* memData = reinterpret_cast(propertyAshmem->data.data); + size_t memSize = propertyAshmem->data.size; + bool fillRes = (memcpy_s(memData, memSize, blobDataPtr, blobDataSize) == EOK); + if (fillRes) { + item->data.fd = *static_cast(propertyAshmem->extend.data); + item->data.capacity = propertyAshmem->data.size; + item->data.filledLen = propertyAshmem->data.size; + metaItems.push_back(*item); + } + return fillRes; +} #endif } // namespace ImagePlugin } // namespace OHOS diff --git a/plugins/common/libs/image/libextplugin/src/hdr/jpeg_mpf_parser.cpp b/plugins/common/libs/image/libextplugin/src/hdr/jpeg_mpf_parser.cpp index 49b383a67..cdeec9df6 100644 --- a/plugins/common/libs/image/libextplugin/src/hdr/jpeg_mpf_parser.cpp +++ b/plugins/common/libs/image/libextplugin/src/hdr/jpeg_mpf_parser.cpp @@ -20,6 +20,7 @@ #include "image_log.h" #include "image_utils.h" #include "media_errors.h" +#include "picture.h" #undef LOG_DOMAIN #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE @@ -41,6 +42,8 @@ constexpr uint16_t TAG_TYPE_LONG = 0x04; constexpr uint16_t HDR_MULTI_PICTURE_APP_LENGTH = 90; constexpr uint16_t FRAGMENT_METADATA_LENGTH = 20; constexpr uint16_t AUXILIARY_TAG_NAME_LENGTH = 8; +constexpr uint32_t TAG_NAME_LENGTH = 8; +const static uint32_t MAX_BLOB_METADATA_LENGTH = 20 * 1024 * 1024; constexpr uint8_t JPEG_MARKER_PREFIX = 0xFF; constexpr uint8_t JPEG_MARKER_APP2 = 0xE2; @@ -48,6 +51,7 @@ constexpr uint8_t JPEG_MARKER_APP2 = 0xE2; constexpr uint8_t MAX_IMAGE_NUM = 32; constexpr uint32_t JPEG_MARKER_SIZE = 2; + static constexpr uint8_t MULTI_PICTURE_HEADER_FLAG[] = { 'M', 'P', 'F', '\0' }; @@ -299,6 +303,39 @@ bool JpegMpfParser::ParsingFragmentMetadata(uint8_t* data, uint32_t size, Rect& return false; } +// |<------------------ Blob Metadata structure ----------------->| +// |<- Data ->|<- dataSize(4 Bytes) ->|<- Tag name(8 Bytes) ->| +bool JpegMpfParser::ParsingBlobMetadata(uint8_t* data, uint32_t size, vector& metadata, + MetadataType type) +{ + if (data == nullptr || size < TAG_NAME_LENGTH) { + return false; + } + auto it = BLOB_METADATA_TAG_MAP.find(type); + if (it == BLOB_METADATA_TAG_MAP.end()) { + IMAGE_LOGW("%{public}s unknown blobmetadata tag: %{public}d", __func__, type); + return false; + } + std::string tagName = it->second; + for (uint32_t offset = size - TAG_NAME_LENGTH; offset > 0; --offset) { + if (memcmp((data + offset), tagName.c_str(), TAG_NAME_LENGTH) != 0) { + continue; + } + if (offset < UINT32_BYTE_SIZE) { + return false; + } + offset -= UINT32_BYTE_SIZE; + uint32_t dataSize = static_cast(ImageUtils::BytesToInt32(data, offset, size, false)); + if (dataSize == 0 || dataSize > MAX_BLOB_METADATA_LENGTH || offset < (dataSize + UINT32_BYTE_SIZE)) { + return false; + } + offset -= (dataSize + UINT32_BYTE_SIZE); + metadata.assign(data + offset, data + offset + dataSize); + return true; + } + return false; +} + static void WriteMPEntryToBytes(vector& bytes, uint32_t& offset, std::vector images) { for (uint32_t i = 0; i < images.size(); i++) { diff --git a/plugins/common/libs/image/libextplugin/src/heif_impl/HeifDecoderImpl.cpp b/plugins/common/libs/image/libextplugin/src/heif_impl/HeifDecoderImpl.cpp index adc835922..a762b0224 100644 --- a/plugins/common/libs/image/libextplugin/src/heif_impl/HeifDecoderImpl.cpp +++ b/plugins/common/libs/image/libextplugin/src/heif_impl/HeifDecoderImpl.cpp @@ -1262,6 +1262,17 @@ void HeifDecoderImpl::getVividMetadata(std::vector& uwaInfo, std::vecto lightInfo = primaryImage_->GetLightInfo(); } +void HeifDecoderImpl::GetMetadataBlob(std::vector& metadata, MetadataType type) +{ + if (type == MetadataType::XTSTYLE) { + metadata = primaryImage_->GetXtStyleData(); + } else if (type == MetadataType::RFDATAB) { + metadata = primaryImage_->GetRfDataBData(); + } else if (type == MetadataType::STDATA) { + metadata = primaryImage_->GetSTDataMetaData(); + } +} + void HeifDecoderImpl::getISOMetadata(std::vector& isoMetadata) { isoMetadata = primaryImage_->GetISOMetadata(); diff --git a/plugins/common/libs/image/libextplugin/src/heif_impl/heif_parser/heif_image.cpp b/plugins/common/libs/image/libextplugin/src/heif_impl/heif_parser/heif_image.cpp index d95716433..3ad04d2bd 100644 --- a/plugins/common/libs/image/libextplugin/src/heif_impl/heif_parser/heif_image.cpp +++ b/plugins/common/libs/image/libextplugin/src/heif_impl/heif_parser/heif_image.cpp @@ -304,5 +304,34 @@ HeifFragmentMetadata HeifImage::GetFragmentMetadata() return fragmentMetadata_; } +void HeifImage::SetXtStyleData(std::vector& xtStyleMetadata) +{ + xtStyledata_ = xtStyleMetadata; +} + +std::vector HeifImage::GetXtStyleData() +{ + return xtStyledata_; +} + +void HeifImage::SetRfDataBData(std::vector& rfDataBMetadata) +{ + rfDataBdata_ = rfDataBMetadata; +} + +std::vector HeifImage::GetRfDataBData() +{ + return rfDataBdata_; +} + +void HeifImage::SetSTDataMetaData(std::vector& stDataMetadata) +{ + stDatadata_ = stDataMetadata; +} + +std::vector HeifImage::GetSTDataMetaData() +{ + return stDatadata_; +} } // namespace ImagePlugin } // namespace OHOS diff --git a/plugins/common/libs/image/libextplugin/src/heif_impl/heif_parser/heif_parser.cpp b/plugins/common/libs/image/libextplugin/src/heif_impl/heif_parser/heif_parser.cpp index 78becd826..854b6e922 100644 --- a/plugins/common/libs/image/libextplugin/src/heif_impl/heif_parser/heif_parser.cpp +++ b/plugins/common/libs/image/libextplugin/src/heif_impl/heif_parser/heif_parser.cpp @@ -30,6 +30,9 @@ namespace ImagePlugin { const auto EXIF_ID = "Exif\0\0"; const auto HEIF_AUXTTYPE_ID_FRAGMENT_MAP = "urn:com:huawei:photo:5:0:0:aux:fragmentmap"; +const auto HEIF_METADATA_NAME_XTSTYLE = "urn:com:huawei:photo:5:1:0:meta:xtstyle"; +const auto HEIF_METADATA_NAME_RFDATAB = "RfDataB\0"; +const auto HEIF_METADATA_NAME_STDATA = "STData\0"; const std::set INFE_ITEM_TYPE = { "hvc1", "grid", "tmap", "iden", "mime" }; @@ -369,6 +372,9 @@ heif_error HeifParser::AssembleImages() ExtractDerivedImageProperties(); ExtractNonMasterImages(); ExtractMetadata(allItemIds); + ExtractXtStyleMetadata(allItemIds); + ExtractRfDataBMetadata(allItemIds); + ExtractSTDataMetadata(allItemIds); return heif_error_ok; } @@ -463,6 +469,66 @@ void HeifParser::ExtractGainmap(const std::vector& allItemIds) } } +void HeifParser::ExtractXtStyleMetadata(const std::vector& allItemIds) +{ + for (heif_item_id itemId: allItemIds) { + auto infe = GetInfeBox(itemId); + if (!infe) { + continue; + } + const std::string& itemType = infe->GetItemType(); + if (itemType == "mime" && infe->GetItemName() == HEIF_METADATA_NAME_XTSTYLE) { + std::vector extendInfo; + heif_error err = GetItemData(itemId, &(extendInfo)); + if (err != heif_error_ok || extendInfo.empty()) { + return; + } + primaryImage_->SetXtStyleData(extendInfo); + break; + } + } +} + +void HeifParser::ExtractSTDataMetadata(const std::vector& allItemIds) +{ + for (heif_item_id itemId: allItemIds) { + auto infe = GetInfeBox(itemId); + if (!infe) { + continue; + } + const std::string& itemType = infe->GetItemType(); + if (itemType == "mime" && infe->GetItemName() == HEIF_METADATA_NAME_STDATA) { + std::vector extendInfo; + heif_error err = GetItemData(itemId, &(extendInfo)); + if (err != heif_error_ok || extendInfo.empty()) { + return; + } + primaryImage_->SetSTDataMetaData(extendInfo); + break; + } + } +} + +void HeifParser::ExtractRfDataBMetadata(const std::vector& allItemIds) +{ + for (heif_item_id itemId: allItemIds) { + auto infe = GetInfeBox(itemId); + if (!infe) { + continue; + } + const std::string& itemType = infe->GetItemType(); + if (itemType == "mime" && infe->GetItemName() == HEIF_METADATA_NAME_RFDATAB) { + std::vector extendInfo; + heif_error err = GetItemData(itemId, &(extendInfo)); + if (err != heif_error_ok || extendInfo.empty()) { + return; + } + primaryImage_->SetRfDataBData(extendInfo); + break; + } + } +} + void HeifParser::ExtractImageProperties(std::shared_ptr &image) { heif_item_id itemId = image->GetItemId(); diff --git a/plugins/manager/include/image/abs_image_decoder.h b/plugins/manager/include/image/abs_image_decoder.h index d86822c42..207390b4c 100644 --- a/plugins/manager/include/image/abs_image_decoder.h +++ b/plugins/manager/include/image/abs_image_decoder.h @@ -278,6 +278,11 @@ public: return false; } + virtual bool GetHeifMetadataBlob(std::vector& metadata, Media::MetadataType type) + { + return false; + } + virtual std::string GetPluginType() = 0; virtual OHOS::Media::Size GetHeifGridTileSize() -- Gitee