From 416169353d544a25b6062480853dff5ecb0daf5b Mon Sep 17 00:00:00 2001 From: yaozhupeng Date: Sun, 18 Aug 2024 20:30:47 +0800 Subject: [PATCH] add astc colorspace Signed-off-by: yaozhupeng --- .../innerkitsimpl/codec/src/image_source.cpp | 145 +++++++++++++++--- .../innerkitsimpl/common/src/pixel_map.cpp | 10 +- .../innerkitsimpl/utils/include/image_utils.h | 1 + .../innerkitsimpl/utils/src/image_utils.cpp | 35 +++++ interfaces/innerkits/include/image_source.h | 2 + interfaces/innerkits/include/pixel_map.h | 2 +- .../include/texture_encode/astc_codec.h | 4 + .../include/texture_encode/texture_type.h | 21 ++- .../src/texture_encode/astc_codec.cpp | 113 +++++++++++++- 9 files changed, 305 insertions(+), 28 deletions(-) diff --git a/frameworks/innerkitsimpl/codec/src/image_source.cpp b/frameworks/innerkitsimpl/codec/src/image_source.cpp index eaa1407bf..3b49b145a 100644 --- a/frameworks/innerkitsimpl/codec/src/image_source.cpp +++ b/frameworks/innerkitsimpl/codec/src/image_source.cpp @@ -155,16 +155,21 @@ static const uint8_t ASTC_HEADER_BLOCK_Y = 5; static const uint8_t ASTC_HEADER_DIM_X = 7; static const uint8_t ASTC_HEADER_DIM_Y = 10; static const int IMAGE_HEADER_SIZE = 12; +constexpr uint8_t ASTC_EXTEND_INFO_TLV_NUM = 1; // curren only one group TLV +constexpr uint32_t ASTC_EXTEND_INFO_SIZE_DEFINITION_LENGTH = 4; // 4 bytes to discripte for extend info summary bytes +constexpr uint32_t ASTC_EXTEND_INFO_LENGTH_LENGTH = 4; // 4 bytes to discripte the content bytes for every TLV group + +struct AstcExtendInfo { + uint32_t extendBufferSumBytes = 0; + uint8_t extendNums = ASTC_EXTEND_INFO_TLV_NUM; + uint8_t extendInfoType[ASTC_EXTEND_INFO_TLV_NUM]; + uint32_t extendInfoLength[ASTC_EXTEND_INFO_TLV_NUM]; + uint8_t *extendInfoValue[ASTC_EXTEND_INFO_TLV_NUM]; +}; + #ifdef SUT_DECODE_ENABLE constexpr uint8_t ASTC_HEAD_BYTES = 16; -constexpr uint8_t ASTC_MAGIC_0 = 0x13; -constexpr uint8_t ASTC_MAGIC_1 = 0xAB; -constexpr uint8_t ASTC_MAGIC_2 = 0xA1; -constexpr uint8_t ASTC_MAGIC_3 = 0x5C; -constexpr uint8_t BYTE_POS_0 = 0; -constexpr uint8_t BYTE_POS_1 = 1; -constexpr uint8_t BYTE_POS_2 = 2; -constexpr uint8_t BYTE_POS_3 = 3; +constexpr uint8_t SUT_HEAD_BYTES = 16 constexpr uint32_t SUT_FILE_SIGNATURE = 0x53555401; static const std::string g_textureSuperDecSo = "/system/lib64/module/hms/graphic/libtextureSuperDecompress.z.so"; @@ -2864,11 +2869,6 @@ static size_t GetAstcSizeBytes(const uint8_t *fileBuf, size_t fileSize) IMAGE_LOGE("astc GetAstcSizeBytes input is nullptr or fileSize is smaller than ASTC HEADER"); return 0; } - if ((fileBuf[BYTE_POS_0] == ASTC_MAGIC_0) && (fileBuf[BYTE_POS_1] == ASTC_MAGIC_1) && - (fileBuf[BYTE_POS_2] == ASTC_MAGIC_2) && (fileBuf[BYTE_POS_3] == ASTC_MAGIC_3)) { - IMAGE_LOGI("astc GetAstcSizeBytes input is pure astc!"); - return fileSize; - } if (g_sutDecSoManager.sutDecSoGetSizeFunc_ != nullptr) { return g_sutDecSoManager.sutDecSoGetSizeFunc_(fileBuf, fileSize); } else { @@ -2900,6 +2900,112 @@ static bool TextureSuperCompressDecode(const uint8_t *inData, size_t inBytes, ui } #endif +static uint32_t GetDataSize(uint8_t *buf) +{ + return static_cast(buf[NUM_0]) + + (static_cast(buf[NUM_1]) << NUM_8) + + (static_cast(buf[NUM_2]) << NUM_16) + + (static_cast(buf[NUM_3]) << NUM_24); +} + +void ReleaseExtendInfoMemory(AstcExtendInfo &extendInfo) +{ + for (uint8_t idx = 0; idx < extendInfo.extendNums; idx++) { + if (extendInfo.extendInfoValue[idx] != nullptr) { + free(extendInfo.extendInfoValue[idx]); + extendInfo.extendInfoValue[idx] = nullptr; + } + } +} + +enum class AstcExtendInfoType : uint8_t { + COLOR_SPACE = 0 +}; + +static bool GetExtInfoForPixelAstc(AstcExtendInfo &extInfo, unique_ptr &pixelAstc) +{ + uint8_t colorSpace = 0; + for (uint8_t idx = 0; idx < extInfo.extendNums; idx++) { + switch (static_cast(extInfo.extendInfoType[idx])) { + case AstcExtendInfoType::COLOR_SPACE: + colorSpace = *extInfo.extendInfoValue[idx]; + break; + default: + return false; + } + } +#ifdef IMAGE_COLORSPACE_FLAG + ColorManager::ColorSpace grColorspace (static_cast(colorSpace)); + pixelAstc->InnerSetColorSpace(grColorspace, true); +#endif + return true; +} + +static bool ResolveExtInfo(const uint8_t *sourceFilePtr, size_t astcSize, size_t fileSize, + unique_ptr &pixelAstc) +{ + uint8_t *extInfoBuf = const_cast(sourceFilePtr) + astcSize; + /* */ + AstcExtendInfo extInfo = {0}; + bool invalidData = (astcSize + ASTC_EXTEND_INFO_SIZE_DEFINITION_LENGTH >= fileSize) || + (memset_s(&extInfo, sizeof(AstcExtendInfo), 0, sizeof(AstcExtendInfo)) != 0); + if (invalidData) { + IMAGE_LOGE("ResolveExtInfo file data is invalid!"); + return false; + } + extInfo.extendBufferSumBytes = GetDataSize(extInfoBuf); + if (extInfo.extendBufferSumBytes + astcSize + ASTC_EXTEND_INFO_SIZE_DEFINITION_LENGTH != fileSize) { + IMAGE_LOGE("ResolveExtInfo file size is not equal to astc add ext bytes!"); + return false; + } + extInfoBuf += ASTC_EXTEND_INFO_SIZE_DEFINITION_LENGTH; + int32_t leftBytes = static_cast(extInfo.extendBufferSumBytes); + for (; leftBytes > 0;) { + if (extInfo.extendNums >= ASTC_EXTEND_INFO_TLV_NUM) { + return false; + } + extInfo.extendInfoType[extInfo.extendNums] = *extInfoBuf++; + leftBytes--; + extInfo.extendInfoLength[extInfo.extendNums] = GetDataSize(extInfoBuf); + leftBytes -= ASTC_EXTEND_INFO_LENGTH_LENGTH; + extInfoBuf += ASTC_EXTEND_INFO_LENGTH_LENGTH; + if (extInfo.extendInfoLength[extInfo.extendNums] > 0) { + extInfo.extendInfoValue[extInfo.extendNums] = + static_cast(malloc(extInfo.extendInfoLength[extInfo.extendNums])); + bool ret = (extInfo.extendInfoValue[extInfo.extendNums] != nullptr) && + (memcpy_s(extInfo.extendInfoValue[extInfo.extendNums], extInfo.extendInfoLength[extInfo.extendNums], + extInfoBuf, extInfo.extendInfoLength[extInfo.extendNums]) == 0); + if (!ret) { + ReleaseExtendInfoMemory(extInfo); + return false; + } + leftBytes -= extInfo.extendInfoLength[extInfo.extendNums]; + extInfoBuf += extInfo.extendInfoLength[extInfo.extendNums]; + } + extInfo.extendNums++; + } + if (!GetExtInfoForPixelAstc(extInfo, pixelAstc)) { + IMAGE_LOGE("ResolveExtInfo Could not get ext info!"); + } + ReleaseExtendInfoMemory(extInfo); + return true; +} + +#ifdef SUT_DECODE_ENABLE +static bool FormatIsSUT(const uint8_t *fileData, size_t fileSize) +{ + if (fileData == nullptr || fileSize < SUT_HEAD_BYTES) { + IMAGE_LOGE("FormatIsSUT fileData incorrect."); + return false; + } + uint32_t magicVal = static_cast(fileData[NUM_0]) + + (static_cast(fileData[NUM_1]) << NUM_8) + + (static_cast(fileData[NUM_2]) << NUM_16) + + (static_cast(fileData[NUM_3]) << NUM_24); + return magicVal == SUT_FILE_SIGNATURE; +} +#endif + static bool ReadFileAndResoveAstc(size_t fileSize, size_t astcSize, unique_ptr &pixelAstc, const uint8_t *sourceFilePtr) { @@ -2919,7 +3025,8 @@ static bool ReadFileAndResoveAstc(size_t fileSize, size_t astcSize, unique_ptr

(dstMemory->data.data), astcSize) != true) { IMAGE_LOGE("[ImageSource] astc SuperDecompressTexture failed!"); @@ -2927,15 +3034,16 @@ static bool ReadFileAndResoveAstc(size_t fileSize, size_t astcSize, unique_ptr

data.data, fileSize, sourceFilePtr, fileSize) != 0) { + if (memcpy_s(dstMemory->data.data, astcSize, sourceFilePtr, astcSize) != 0) { IMAGE_LOGE("[ImageSource] astc memcpy_s failed!"); successMemCpyOrDec = false; } + successMemCpyOrDec = successMemCpyOrDec && ((fileSize == astcSize) || + ((fileSize > astcSize) && ResolveExtInfo(sourceFilePtr, astcSize, fileSize, pixelAstc))); #ifdef SUT_DECODE_ENABLE } #endif if (!successMemCpyOrDec) { - dstMemory->Release(); return false; } #endif @@ -2967,13 +3075,14 @@ unique_ptr ImageSource::CreatePixelMapForASTC(uint32_t &errorCode, boo pixelAstc->SetEditable(false); size_t fileSize = sourceStreamPtr_->GetStreamSize(); #ifdef SUT_DECODE_ENABLE - size_t astcSize = GetAstcSizeBytes(sourceFilePtr, fileSize); + size_t astcSize = (!FormatIsSUT(sourceFilePtr, fileSize)) ? + ImageUtils::GetAstcBytesCount(info) : GetAstcSizeBytes(sourceFilePtr, fileSize); if (astcSize == 0) { IMAGE_LOGE("[ImageSource] astc GetAstcSizeBytes failed."); return nullptr; } #else - size_t astcSize = fileSize; + size_t astcSize = ImageUtils::GetAstcBytesCount(info); #endif if (!ReadFileAndResoveAstc(fileSize, astcSize, pixelAstc, sourceFilePtr)) { IMAGE_LOGE("[ImageSource] astc ReadFileAndResoveAstc failed."); diff --git a/frameworks/innerkitsimpl/common/src/pixel_map.cpp b/frameworks/innerkitsimpl/common/src/pixel_map.cpp index 195ed1bfb..2771e2813 100644 --- a/frameworks/innerkitsimpl/common/src/pixel_map.cpp +++ b/frameworks/innerkitsimpl/common/src/pixel_map.cpp @@ -3469,10 +3469,14 @@ uint32_t PixelMap::ToSdr(PixelFormat format, bool toSRGB) } #ifdef IMAGE_COLORSPACE_FLAG -void PixelMap::InnerSetColorSpace(const OHOS::ColorManager::ColorSpace &grColorSpace) +void PixelMap::InnerSetColorSpace(const OHOS::ColorManager::ColorSpace &grColorSpace, bool direct) { - grColorSpace_ = std::make_shared(grColorSpace.ToSkColorSpace(), - grColorSpace.GetColorSpaceName()); + if (direct) { + grColorSpace_ = std::make_shared(grColorSpace); + } else { + grColorSpace_ = std::make_shared(grColorSpace.ToSkColorSpace(), + grColorSpace.GetColorSpaceName()); + } } OHOS::ColorManager::ColorSpace PixelMap::InnerGetGrColorSpace() diff --git a/frameworks/innerkitsimpl/utils/include/image_utils.h b/frameworks/innerkitsimpl/utils/include/image_utils.h index a6afd00b9..fc0649bb6 100644 --- a/frameworks/innerkitsimpl/utils/include/image_utils.h +++ b/frameworks/innerkitsimpl/utils/include/image_utils.h @@ -69,6 +69,7 @@ public: static bool IsAuxiliaryPictureTypeSupported(AuxiliaryPictureType auxiliaryPictureType); static bool IsMetadataTypeSupported(MetadataType metadataType); static const std::set GetAllAuxiliaryPictureType(); + static size_t GetAstcBytesCount(const ImageInfo& imageInfo); private: static uint32_t RegisterPluginServer(); static uint32_t SaveDataToFile(const std::string& fileName, const char* data, const size_t& totalSize); diff --git a/frameworks/innerkitsimpl/utils/src/image_utils.cpp b/frameworks/innerkitsimpl/utils/src/image_utils.cpp index 183ad36e8..b9a5771c7 100644 --- a/frameworks/innerkitsimpl/utils/src/image_utils.cpp +++ b/frameworks/innerkitsimpl/utils/src/image_utils.cpp @@ -72,6 +72,11 @@ constexpr uint8_t MOVE_BITS_16 = 16; constexpr uint8_t MOVE_BITS_24 = 24; constexpr int32_t NV21P010_BYTES = 3; constexpr int32_t ASTC_4X4_BYTES = 1; +constexpr int32_t ASTC_4X4_BLOCK = 4; +constexpr int32_t ASTC_6X6_BLOCK = 6; +constexpr int32_t ASTC_8X8_BLOCK = 8; +constexpr int32_t ASTC_BLOCK_SIZE = 16; +constexpr int32_t ASTC_HEADER_SIZE = 16; constexpr float EPSILON = 1e-6; constexpr int MAX_DIMENSION = INT32_MAX >> 2; constexpr int32_t DMA_SIZE = 512 * 512; @@ -720,5 +725,35 @@ const std::set ImageUtils::GetAllAuxiliaryPictureType() return auxTypes; } +size_t ImageUtils::GetAstcBytesCount(const ImageInfo& imageInfo) +{ + size_t astcBytesCount = 0; + uint32_t blockWidth = 0; + uint32_t blockHeight = 0; + + switch (imageInfo.pixelFormat) { + case PixelFormat::ASTC_4x4: + blockWidth = ASTC_4X4_BLOCK; + blockHeight = ASTC_4X4_BLOCK; + break; + case PixelFormat::ASTC_6x6: + blockWidth = ASTC_6X6_BLOCK; + blockHeight = ASTC_6X6_BLOCK; + break; + case PixelFormat::ASTC_8x8: + blockWidth = ASTC_8X8_BLOCK; + blockHeight = ASTC_8X8_BLOCK; + break; + default: + IMAGE_LOGE("ImageUtils GetAstcBytesCount failed, format is not supported %{public}d", + imageInfo.pixelFormat); + return 0; + } + if ((blockWidth >= ASTC_4X4_BLOCK) && (blockHeight >= ASTC_4X4_BLOCK)) { + astcBytesCount = ((imageInfo.size.width + blockWidth - 1) / blockWidth) * + ((imageInfo.size.height + blockHeight - 1) / blockHeight) * ASTC_BLOCK_SIZE + ASTC_HEADER_SIZE; + } + return astcBytesCount; +} } // namespace Media } // namespace OHOS diff --git a/interfaces/innerkits/include/image_source.h b/interfaces/innerkits/include/image_source.h index 58d5f4203..194b6a635 100644 --- a/interfaces/innerkits/include/image_source.h +++ b/interfaces/innerkits/include/image_source.h @@ -28,6 +28,7 @@ #include "image_type.h" #include "incremental_pixel_map.h" #include "peer_listener.h" +#include "pixel_astc.h" #include "pixel_map.h" #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) #include "picture.h" @@ -366,6 +367,7 @@ private: void DecodeJpegAuxiliaryPicture(const std::set &auxTypes, std::unique_ptr &picture, uint32_t &errorCode); #endif + uint32_t SetColorSpaceForAstc(PixelAstc& pixelAstc, size_t fileSize); const std::string NINE_PATCH = "ninepatch"; const std::string SKIA_DECODER = "SKIA_DECODER"; diff --git a/interfaces/innerkits/include/pixel_map.h b/interfaces/innerkits/include/pixel_map.h index d1d59d96c..3cf72dc30 100644 --- a/interfaces/innerkits/include/pixel_map.h +++ b/interfaces/innerkits/include/pixel_map.h @@ -245,7 +245,7 @@ public: } #ifdef IMAGE_COLORSPACE_FLAG // -------[inner api for ImageSource/ImagePacker codec] it will get a colorspace object pointer----begin---- - NATIVEEXPORT void InnerSetColorSpace(const OHOS::ColorManager::ColorSpace &grColorSpace); + NATIVEEXPORT void InnerSetColorSpace(const OHOS::ColorManager::ColorSpace &grColorSpace, bool direct = false); NATIVEEXPORT OHOS::ColorManager::ColorSpace InnerGetGrColorSpace(); NATIVEEXPORT std::shared_ptr InnerGetGrColorSpacePtr() { diff --git a/plugins/common/libs/image/libextplugin/include/texture_encode/astc_codec.h b/plugins/common/libs/image/libextplugin/include/texture_encode/astc_codec.h index 083281d39..9a1b02f7f 100644 --- a/plugins/common/libs/image/libextplugin/include/texture_encode/astc_codec.h +++ b/plugins/common/libs/image/libextplugin/include/texture_encode/astc_codec.h @@ -36,6 +36,10 @@ public: #ifdef SUT_ENCODE_ENABLE static bool TryTextureSuperCompress(TextureEncodeOptions ¶m, uint8_t *astcBuffer); #endif + bool InitAstcExtendInfo(AstcExtendInfo &extendInfo); + uint32_t SetColorSpace(uint8_t* astcBuffer); + void ReleaseExtendInfoMemory(AstcExtendInfo &extendInfo); + void WriteAstcExtendInfo(uint8_t* outBuffer, uint32_t offset, AstcExtendInfo &extendInfo); private: DISALLOW_COPY_AND_MOVE(AstcCodec); OutputDataStream* astcOutput_ = nullptr; diff --git a/plugins/common/libs/image/libextplugin/include/texture_encode/texture_type.h b/plugins/common/libs/image/libextplugin/include/texture_encode/texture_type.h index 88d707cff..cd7504abf 100644 --- a/plugins/common/libs/image/libextplugin/include/texture_encode/texture_type.h +++ b/plugins/common/libs/image/libextplugin/include/texture_encode/texture_type.h @@ -27,6 +27,12 @@ enum class SutProfile { SKIP_SUT = 255 }; // the profile of superCompress for texture +constexpr uint8_t ASTC_EXTEND_INFO_TLV_NUM = 1; // curren only one group TLV +constexpr uint32_t ASTC_EXTEND_INFO_SIZE_DEFINITION_LENGTH = 4; // 4 bytes to discripte for extend info summary bytes +constexpr uint8_t ASTC_EXTEND_INFO_TYPE_LENGTH = 1; // 1 byte to discripte the content type for every TLV group +constexpr uint32_t ASTC_EXTEND_INFO_LENGTH_LENGTH = 4; // 4 bytes to discripte the content bytes for every TLV group +constexpr uint8_t ASTC_EXTEND_INFO_COLOR_SPACE_VALUE_LENGTH = 1; // 1 bytes to discripte the content for color space + struct TextureEncodeOptions { int32_t width_; int32_t height_; @@ -40,6 +46,7 @@ struct TextureEncodeOptions { bool hardwareFlag; SutProfile sutProfile; int32_t sutBytes; + bool outIsSut; }; struct AstcEncoder { @@ -55,7 +62,19 @@ struct AstcEncoder { int32_t *mse[RGBA_COM + 1]; #endif }; + +struct AstcExtendInfo { + uint32_t extendBufferSumBytes = 0; + uint8_t extendNums = ASTC_EXTEND_INFO_TLV_NUM; + uint8_t extendInfoType[ASTC_EXTEND_INFO_TLV_NUM]; + uint32_t extendInfoLength[ASTC_EXTEND_INFO_TLV_NUM]; + uint8_t *extendInfoValue[ASTC_EXTEND_INFO_TLV_NUM]; +}; + +enum class AstcExtendInfoType : uint8_t { + COLOR_SPACE = 0 +}; } // namespace ImagePlugin } // namespace OHOS -#endif // PLUGINS_COMMON_LIBS_IMAGE_LIBEXTPLUGIN_INCLUDE_TEXTURE_ENCODE_TEXTURE_TYPE_H \ No newline at end of file +#endif // PLUGINS_COMMON_LIBS_IMAGE_LIBEXTPLUGIN_INCLUDE_TEXTURE_ENCODE_TEXTURE_TYPE_H diff --git a/plugins/common/libs/image/libextplugin/src/texture_encode/astc_codec.cpp b/plugins/common/libs/image/libextplugin/src/texture_encode/astc_codec.cpp index b53e72c8c..f989f20a2 100644 --- a/plugins/common/libs/image/libextplugin/src/texture_encode/astc_codec.cpp +++ b/plugins/common/libs/image/libextplugin/src/texture_encode/astc_codec.cpp @@ -45,6 +45,10 @@ static const uint32_t ASTC_MAGIC_ID = 0x5CA1AB13; constexpr uint8_t DEFAULT_DIM = 4; constexpr uint8_t HIGH_SPEED_PROFILE_MAP_QUALITY = 20; // quality level is 20 for thumbnail constexpr uint8_t RGBA_BYTES_PIXEL_LOG2 = 2; +constexpr uint8_t MASKBITS_FOR_8BITS = 255; +constexpr uint8_t UINT32_1TH_BYTES = 8; +constexpr uint8_t UINT32_2TH_BYTES = 16; +constexpr uint8_t UINT32_3TH_BYTES = 24; #ifdef ENABLE_ASTC_ENCODE_BASED_GPU constexpr int32_t WIDTH_CL_THRESHOLD = 256; constexpr int32_t HEIGHT_CL_THRESHOLD = 256; @@ -428,6 +432,7 @@ bool AstcCodec::TryTextureSuperCompress(TextureEncodeOptions ¶m, uint8_t *as } free(sutBuffer); param.astcBytes = param.sutBytes; + param.outIsSut = true; return true; } #endif @@ -443,6 +448,7 @@ static bool InitAstcEncPara(TextureEncodeOptions ¶m, param.height_ = height; param.stride_ = stride; param.privateProfile_ = GetAstcQuality(astcOpts.quality); + param.outIsSut = false; extractDimensions(astcOpts.format, param); if ((param.blockX_ < DEFAULT_DIM) || (param.blockY_ < DEFAULT_DIM)) { // DEFAULT_DIM = 4 IMAGE_LOGE("InitAstcEncPara failed %{public}dx%{public}d is invalid!", param.blockX_, param.blockY_); @@ -508,31 +514,128 @@ uint32_t AstcCodec::ASTCEncode() IMAGE_LOGE("InitAstcEncPara failed"); return ERROR; } - IMAGE_LOGD("astcenc start: %{public}dx%{public}d, enableQualityCheck %{public}d, astcProfile %{public}d", - imageInfo.size.width, imageInfo.size.height, param.enableQualityCheck, param.privateProfile_); - uint8_t *astcBuffer = static_cast(malloc(param.astcBytes)); + AstcExtendInfo extendInfo = {0}; + if (!InitAstcExtendInfo(extendInfo)) { + IMAGE_LOGE("InitAstcExtendInfo failed"); + return ERROR; + } + uint32_t packSize = static_cast(param.astcBytes) + + extendInfo.extendBufferSumBytes + ASTC_EXTEND_INFO_SIZE_DEFINITION_LENGTH; + uint8_t *astcBuffer = static_cast(malloc(packSize)); if (astcBuffer == nullptr) { IMAGE_LOGE("astc astcBuffer malloc failed!"); + ReleaseExtendInfoMemory(extendInfo); return ERROR; } if (!AstcEncProcess(param, pixmapIn, astcBuffer)) { IMAGE_LOGE("astc AstcEncProcess failed!"); + ReleaseExtendInfoMemory(extendInfo); free(astcBuffer); return ERROR; } #ifdef SUT_ENCODE_ENABLE if (!TryTextureSuperCompress(param, astcBuffer)) { IMAGE_LOGE("astc TryTextureSuperCompress failed!"); + ReleaseExtendInfoMemory(extendInfo); free(astcBuffer); return ERROR; } #endif - astcOutput_->Write(astcBuffer, param.astcBytes); + if (!param.outIsSut) { // only support astc for color space + WriteAstcExtendInfo(astcBuffer, static_cast(param.astcBytes), extendInfo); + } else { + packSize = param.sutBytes; + } + ReleaseExtendInfoMemory(extendInfo); + astcOutput_->Write(astcBuffer, packSize); free(astcBuffer); IMAGE_LOGD("astcenc end: %{public}dx%{public}d, GpuFlag %{public}d, sut%{public}d", imageInfo.size.width, imageInfo.size.height, param.hardwareFlag, param.sutProfile); - astcOutput_->SetOffset(param.astcBytes); + astcOutput_->SetOffset(packSize); return SUCCESS; } + +bool AllocMemForExtInfo(AstcExtendInfo &extendInfo, uint8_t idx) +{ + AstcExtendInfoType type = static_cast(idx); + switch (type) { + case AstcExtendInfoType::COLOR_SPACE: + extendInfo.extendInfoLength[idx] = ASTC_EXTEND_INFO_COLOR_SPACE_VALUE_LENGTH; + extendInfo.extendBufferSumBytes += ASTC_EXTEND_INFO_TYPE_LENGTH + + ASTC_EXTEND_INFO_LENGTH_LENGTH + ASTC_EXTEND_INFO_COLOR_SPACE_VALUE_LENGTH; + extendInfo.extendInfoValue[idx] = static_cast(malloc(extendInfo.extendInfoLength[idx])); + if (extendInfo.extendInfoValue[idx] == nullptr) { + IMAGE_LOGE("[AstcCodec] SetColorSpaceInfo malloc failed!"); + return false; + } + break; + default: + return false; + } + return true; +} + +bool AstcCodec::InitAstcExtendInfo(AstcExtendInfo &extendInfo) +{ + if (memset_s(&extendInfo, sizeof(AstcExtendInfo), 0, sizeof(AstcExtendInfo)) != 0) { + return false; + } + extendInfo.extendNums = ASTC_EXTEND_INFO_TLV_NUM; + extendInfo.extendBufferSumBytes = 0; + for (uint8_t idx = 0; idx < extendInfo.extendNums; idx++) { + if (!AllocMemForExtInfo(extendInfo, idx)) { + ReleaseExtendInfoMemory(extendInfo); + IMAGE_LOGE("[AstcCodec] AllocMemForExtInfo failed!"); + return false; + } + } + return true; +} + +void AstcCodec::ReleaseExtendInfoMemory(AstcExtendInfo &extendInfo) +{ + for (uint8_t idx = 0; idx < extendInfo.extendNums; idx++) { + if (extendInfo.extendInfoValue[idx] != nullptr) { + free(extendInfo.extendInfoValue[idx]); + extendInfo.extendInfoValue[idx] = nullptr; + } + } +} + +static void FillDataSize(uint8_t *buf, uint32_t bytes) +{ + *buf++ = (bytes) & MASKBITS_FOR_8BITS; + *buf++ = (bytes >> UINT32_1TH_BYTES) & MASKBITS_FOR_8BITS; + *buf++ = (bytes >> UINT32_2TH_BYTES) & MASKBITS_FOR_8BITS; + *buf++ = (bytes >> UINT32_3TH_BYTES) & MASKBITS_FOR_8BITS; +} + +void AstcCodec::WriteAstcExtendInfo(uint8_t *buffer, uint32_t offset, AstcExtendInfo &extendInfo) +{ + uint8_t* offsetBuffer = buffer + offset; + FillDataSize(offsetBuffer, extendInfo.extendBufferSumBytes); + offsetBuffer += ASTC_EXTEND_INFO_SIZE_DEFINITION_LENGTH; +#ifdef IMAGE_COLORSPACE_FLAG + ColorManager::ColorSpace colorspace = astcPixelMap_->InnerGetGrColorSpace(); + ColorManager::ColorSpaceName csName = colorspace.GetColorSpaceName(); +#endif + for (uint8_t idx = 0; idx < extendInfo.extendNums; idx++) { + *offsetBuffer++ = idx; + FillDataSize(offsetBuffer, extendInfo.extendInfoLength[idx]); + offsetBuffer += ASTC_EXTEND_INFO_LENGTH_LENGTH; + AstcExtendInfoType type = static_cast(idx); + switch (type) { + case AstcExtendInfoType::COLOR_SPACE: +#ifdef IMAGE_COLORSPACE_FLAG + *offsetBuffer = static_cast(csName); +#else + *offsetBuffer = 0; +#endif + break; + default: + return; + } + } +} } // namespace ImagePlugin } // namespace OHOS -- Gitee