diff --git a/frameworks/innerkitsimpl/codec/src/image_source.cpp b/frameworks/innerkitsimpl/codec/src/image_source.cpp index 1b93255e66d214c222a5876805027f632b060cc9..837229a116a1046753e3f781c61a199eec63b25e 100644 --- a/frameworks/innerkitsimpl/codec/src/image_source.cpp +++ b/frameworks/innerkitsimpl/codec/src/image_source.cpp @@ -1192,6 +1192,7 @@ unique_ptr ImageSource::CreatePixelMapByInfos(ImagePlugin::PlImageInfo return nullptr; } pixelMap->SetEditable(saveEditable); + pixelMap->UpdatePixelsAlphaType(pixelMap); return pixelMap; } diff --git a/frameworks/innerkitsimpl/common/src/pixel_map.cpp b/frameworks/innerkitsimpl/common/src/pixel_map.cpp index 62254fbfd5bbecf438e317f406e6e5e9ad549ed1..8fb9f4e9f6c1cba609e352cbf84e9a69d3ad7b09 100644 --- a/frameworks/innerkitsimpl/common/src/pixel_map.cpp +++ b/frameworks/innerkitsimpl/common/src/pixel_map.cpp @@ -424,6 +424,56 @@ static int AllocPixelMapMemory(std::unique_ptr &dstMemory, int32_t &d return IMAGE_RESULT_SUCCESS; } +static constexpr uint16_t HEIGHT_MIN = 198; +static constexpr uint16_t HEIGHT_MAX = 760; +static constexpr uint16_t WIDTH_MIN = 345; +static constexpr uint16_t WIDTH_MAX = 960; +void PixelMap::UpdatePixelsAlphaType(std::unique_ptr& pixelMap) +{ + const uint8_t *dstPixels = pixelMap->GetPixels(); + if (dstPixels == nullptr) { + IMAGE_LOGD("[PixelMap]UpdatePixelsAlphaType invalid input parameter: dstPixels is Null"); + return; + } + + int32_t height = pixelMap->GetHeight(); + int32_t width = pixelMap->GetWidth(); + if (height < HEIGHT_MIN || width < WIDTH_MIN || height > HEIGHT_MAX || width > WIDTH_MAX) { + return; + } + + ImageInfo imageInfo; + pixelMap->GetImageInfo(imageInfo); + + int8_t alphaIndex = -1; + if (imageInfo.pixelFormat == PixelFormat::RGBA_8888 || + imageInfo.pixelFormat == PixelFormat::BGRA_8888) { + alphaIndex = BGRA_ALPHA_INDEX; + } else if (imageInfo.pixelFormat == PixelFormat::ARGB_8888) { + alphaIndex = 0; + } + if (alphaIndex == -1) { + IMAGE_LOGE("[PixelMap]Pixel format is not supported"); + return; + } + + uint8_t pixelBytes = pixelMap->GetPixelBytes(); + int32_t stride = pixelMap->GetRowStride(); + int32_t rowBytes = pixelMap->GetRowBytes(); + + for (int32_t i = 0; i < height; ++i) { + for (int32_t j = 0; j < rowBytes; j += pixelBytes) { + int32_t index = i * stride + j; + const uint8_t *rpixel = dstPixels + index; + if (rpixel[alphaIndex] != ALPHA_OPAQUE) { + return; + } + } + } + + pixelMap->SetSupportOpaqueOpt(true); +} + unique_ptr PixelMap::Create(const uint32_t *colors, uint32_t colorLength, BUILD_PARAM &info, const InitializationOptions &opts, int &errorCode) { @@ -478,6 +528,7 @@ unique_ptr PixelMap::Create(const uint32_t *colors, uint32_t colorLeng ImageUtils::DumpPixelMapIfDumpEnabled(dstPixelMap); SetYUVDataInfoToPixelMap(dstPixelMap); ImageUtils::FlushSurfaceBuffer(const_cast(dstPixelMap.get())); + dstPixelMap->UpdatePixelsAlphaType(dstPixelMap); return dstPixelMap; } @@ -1081,6 +1132,7 @@ unique_ptr PixelMap::Clone(int32_t &errorCode) return nullptr; } pixelMap->SetTransformered(isTransformered_); + pixelMap->SetSupportOpaqueOpt(supportOpaqueOpt_); TransformData transformData; GetTransformData(transformData); pixelMap->SetTransformData(transformData); @@ -1915,6 +1967,16 @@ bool PixelMap::SetAlphaType(const AlphaType &alphaType) return true; } +void PixelMap::SetSupportOpaqueOpt(bool supportOpaqueOpt) +{ + supportOpaqueOpt_ = supportOpaqueOpt; +} + +bool PixelMap::GetSupportOpaqueOpt() +{ + return supportOpaqueOpt_; +} + uint32_t PixelMap::WritePixel(const Position &pos, const uint32_t &color) { if (pos.x < 0 || pos.y < 0 || pos.x >= GetWidth() || pos.y >= GetHeight()) { @@ -2392,6 +2454,11 @@ bool PixelMap::WritePropertiesToParcel(Parcel &parcel) const return false; } + if (!parcel.WriteBool(supportOpaqueOpt_)) { + IMAGE_LOGE("write pixel map supportOpaqueOpt to parcel failed."); + return false; + } + if (!parcel.WriteBool(isAstc_)) { IMAGE_LOGE("write pixel map isAstc_ to parcel failed."); return false; @@ -2795,6 +2862,8 @@ bool PixelMap::ReadPropertiesFromParcel(Parcel& parcel, PixelMap*& pixelMap, Ima pixelMap->SetReadVersion(readVersion); pixelMap->SetEditable(parcel.ReadBool()); + bool supportOpaqueOpt = parcel.ReadBool(); + pixelMap->SetSupportOpaqueOpt(supportOpaqueOpt); memInfo.isAstc = parcel.ReadBool(); pixelMap->SetAstc(memInfo.isAstc); if (pixelMap->GetReadVersion() >= PIXELMAP_VERSION_DISPLAY_ONLY) { diff --git a/interfaces/innerkits/include/pixel_map.h b/interfaces/innerkits/include/pixel_map.h index aaacf4cff4c15f4c02be325ae86052dab8f288b2..003e3ab2c0ca8137d0fdc66828c0b2322e6b482c 100644 --- a/interfaces/innerkits/include/pixel_map.h +++ b/interfaces/innerkits/include/pixel_map.h @@ -199,6 +199,19 @@ public: NATIVEEXPORT virtual uint32_t ReadPixel(const Position &pos, uint32_t &dst); NATIVEEXPORT virtual uint32_t ResetConfig(const Size &size, const PixelFormat &format); NATIVEEXPORT virtual bool SetAlphaType(const AlphaType &alphaType); + /** + * Set whether to support opaque optimization. + * + * @param supportOpaqueOpt whether to support opaque optimization. + */ + NATIVEEXPORT virtual void SetSupportOpaqueOpt(bool supportOpaqueOpt); + + /** + * Get whether to support opaque optimization. + * + * @return Return true if support opaque optimization, otherwise return false. + */ + NATIVEEXPORT virtual bool GetSupportOpaqueOpt(); NATIVEEXPORT virtual uint32_t WritePixel(const Position &pos, const uint32_t &color); NATIVEEXPORT virtual uint32_t WritePixels(const RWPixelsOptions &opts); NATIVEEXPORT virtual uint32_t WritePixels(const uint8_t *source, const uint64_t &bufferSize, const uint32_t &offset, @@ -415,6 +428,7 @@ public: NATIVEEXPORT uint32_t GetVersionId(); NATIVEEXPORT void AddVersionId(); + void UpdatePixelsAlphaType(std::unique_ptr& pixelMap); protected: static constexpr uint8_t TLV_VARINT_BITS = 7; @@ -615,6 +629,8 @@ private: bool displayOnly_ = false; friend class OHOS::Rosen::RSModifiersDraw; + + bool supportOpaqueOpt_ = false; }; } // namespace Media } // namespace OHOS