From c0574b738834f18ada2f4adb64a394fb2a7018d8 Mon Sep 17 00:00:00 2001 From: Dirk Farin Date: Thu, 30 Jan 2025 15:23:33 +0100 Subject: [PATCH] fix heif_image_handle_has_alpha_channel() for unci images (#1450) --- libheif/codecs/uncompressed/unc_codec.cc | 34 +++++++++++++++++++----- libheif/codecs/uncompressed/unc_codec.h | 3 ++- libheif/codecs/uncompressed/unc_dec.cc | 14 +++++++++- libheif/codecs/uncompressed/unc_dec.h | 2 ++ libheif/context.cc | 4 +++ libheif/image-items/image_item.h | 2 ++ libheif/image-items/unc_image.cc | 6 +++++ libheif/image-items/unc_image.h | 2 ++ 8 files changed, 59 insertions(+), 8 deletions(-) diff --git a/libheif/codecs/uncompressed/unc_codec.cc b/libheif/codecs/uncompressed/unc_codec.cc index 08aa7b537e..6ee8ba12a8 100644 --- a/libheif/codecs/uncompressed/unc_codec.cc +++ b/libheif/codecs/uncompressed/unc_codec.cc @@ -241,22 +241,42 @@ static Error uncompressed_image_type_is_supported(const std::shared_ptr& uncC, const std::shared_ptr& cmpd, - heif_chroma* out_chroma, heif_colorspace* out_colourspace) + heif_chroma* out_chroma, heif_colorspace* out_colourspace, + bool* out_has_alpha) { + bool dummy_has_alpha; + if (out_has_alpha == nullptr) { + out_has_alpha = &dummy_has_alpha; + } + *out_chroma = heif_chroma_undefined; *out_colourspace = heif_colorspace_undefined; + *out_has_alpha = false; Error error = check_header_validity(std::nullopt, cmpd, uncC); if (error) { return error; } - if (isKnownUncompressedFrameConfigurationBoxProfile(uncC)) { - *out_chroma = heif_chroma_444; - *out_colourspace = heif_colorspace_RGB; - return Error::Ok; + + if (uncC != nullptr && uncC->get_version() == 1) { + switch (uncC->get_profile()) { + case fourcc("rgb3"): { + *out_chroma = heif_chroma_444; + *out_colourspace = heif_colorspace_RGB; + *out_has_alpha = false; + return Error::Ok; + } + case fourcc("abgr"): { + *out_chroma = heif_chroma_444; + *out_colourspace = heif_colorspace_RGB; + *out_has_alpha = true; + return Error::Ok; + } + } } + // each 1-bit represents an existing component in the image uint16_t componentSet = 0; @@ -276,6 +296,8 @@ Error UncompressedImageCodec::get_heif_chroma_uncompressed(const std::shared_ptr componentSet |= (1 << component_type); } + *out_has_alpha = (componentSet & (1 << component_type_alpha)) != 0; + if (componentSet == ((1 << component_type_red) | (1 << component_type_green) | (1 << component_type_blue)) || componentSet == ((1 << component_type_red) | (1 << component_type_green) | (1 << component_type_blue) | (1 << component_type_alpha))) { *out_chroma = heif_chroma_444; @@ -448,7 +470,7 @@ Result> UncompressedImageCodec::create_image(con heif_chroma chroma = heif_chroma_undefined; heif_colorspace colourspace = heif_colorspace_undefined; - Error error = get_heif_chroma_uncompressed(uncC, cmpd, &chroma, &colourspace); + Error error = get_heif_chroma_uncompressed(uncC, cmpd, &chroma, &colourspace, nullptr); if (error) { return error; } diff --git a/libheif/codecs/uncompressed/unc_codec.h b/libheif/codecs/uncompressed/unc_codec.h index 24ca3241dc..535d6b7aa0 100644 --- a/libheif/codecs/uncompressed/unc_codec.h +++ b/libheif/codecs/uncompressed/unc_codec.h @@ -63,7 +63,8 @@ class UncompressedImageCodec static Error get_heif_chroma_uncompressed(const std::shared_ptr& uncC, const std::shared_ptr& cmpd, heif_chroma* out_chroma, - heif_colorspace* out_colourspace); + heif_colorspace* out_colourspace, + bool* out_has_alpha); static Result> create_image(std::shared_ptr, std::shared_ptr, diff --git a/libheif/codecs/uncompressed/unc_dec.cc b/libheif/codecs/uncompressed/unc_dec.cc index d348b306f2..8f03ac0f24 100644 --- a/libheif/codecs/uncompressed/unc_dec.cc +++ b/libheif/codecs/uncompressed/unc_dec.cc @@ -140,7 +140,7 @@ Error Decoder_uncompressed::get_coded_image_colorspace(heif_colorspace* out_colo return Error::Ok; } else if (m_cmpd) { - UncompressedImageCodec::get_heif_chroma_uncompressed(m_uncC, m_cmpd, out_chroma, out_colorspace); + UncompressedImageCodec::get_heif_chroma_uncompressed(m_uncC, m_cmpd, out_chroma, out_colorspace, nullptr); return Error::Ok; } else { @@ -149,3 +149,15 @@ Error Decoder_uncompressed::get_coded_image_colorspace(heif_colorspace* out_colo "Missing 'cmpd' box."}; } } + + +bool Decoder_uncompressed::has_alpha_component() const +{ + heif_colorspace dummy_colorspace; + heif_chroma dummy_chroma; + bool has_alpha; + + UncompressedImageCodec::get_heif_chroma_uncompressed(m_uncC, m_cmpd, &dummy_chroma, &dummy_colorspace, &has_alpha); + + return has_alpha; +} diff --git a/libheif/codecs/uncompressed/unc_dec.h b/libheif/codecs/uncompressed/unc_dec.h index 2521df1493..2275688303 100644 --- a/libheif/codecs/uncompressed/unc_dec.h +++ b/libheif/codecs/uncompressed/unc_dec.h @@ -47,6 +47,8 @@ class Decoder_uncompressed : public Decoder Error get_coded_image_colorspace(heif_colorspace*, heif_chroma*) const override; + bool has_alpha_component() const; + Result> read_bitstream_configuration_data() const override; private: diff --git a/libheif/context.cc b/libheif/context.cc index 187297a05f..2d7c5e7b9b 100644 --- a/libheif/context.cc +++ b/libheif/context.cc @@ -941,6 +941,10 @@ bool HeifContext::has_alpha(heif_item_id ID) const return true; } + if (img->has_coded_alpha_channel()) { + return true; + } + heif_colorspace colorspace; heif_chroma chroma; Error err = img->get_coded_image_colorspace(&colorspace, &chroma); diff --git a/libheif/image-items/image_item.h b/libheif/image-items/image_item.h index 2d222a4fdb..996c848339 100644 --- a/libheif/image-items/image_item.h +++ b/libheif/image-items/image_item.h @@ -192,6 +192,8 @@ class ImageItem : public ErrorBuffer bool is_premultiplied_alpha() const { return m_premultiplied_alpha; } + // Whether the image has an alpha channel coded in the main image (not as an auxiliary image) + virtual bool has_coded_alpha_channel() const { return false; } // --- depth channel diff --git a/libheif/image-items/unc_image.cc b/libheif/image-items/unc_image.cc index 98adbd5a11..bbac66a26c 100644 --- a/libheif/image-items/unc_image.cc +++ b/libheif/image-items/unc_image.cc @@ -530,3 +530,9 @@ Error ImageItem_uncompressed::on_load_file() return Error::Ok; } + + +bool ImageItem_uncompressed::has_coded_alpha_channel() const +{ + return m_decoder->has_alpha_component(); +} diff --git a/libheif/image-items/unc_image.h b/libheif/image-items/unc_image.h index e1453ad2f8..a5028ae6e5 100644 --- a/libheif/image-items/unc_image.h +++ b/libheif/image-items/unc_image.h @@ -48,6 +48,8 @@ class ImageItem_uncompressed : public ImageItem // Instead of storing alpha in a separate unci, this is put into the main image item const char* get_auxC_alpha_channel_type() const override { return nullptr; } + bool has_coded_alpha_channel() const override; + const heif_color_profile_nclx* get_forced_output_nclx() const override { return nullptr; } bool is_ispe_essential() const override { return true; }