Commit e72315d3 for libheif
commit e72315d3f522e065c4e4b3e170bb477eb5e1a569
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Sun Dec 14 01:03:31 2025 +0100
[BSD3] 'uncv': alpha channel can be stored in main visual track
diff --git a/libheif/codecs/uncompressed/unc_boxes.cc b/libheif/codecs/uncompressed/unc_boxes.cc
index a338d93e..b3f49fc0 100644
--- a/libheif/codecs/uncompressed/unc_boxes.cc
+++ b/libheif/codecs/uncompressed/unc_boxes.cc
@@ -185,6 +185,13 @@ std::string Box_cmpd::Component::get_component_type_name(uint16_t component_type
}
+bool Box_cmpd::has_component(heif_uncompressed_component_type type) const
+{
+ return std::any_of(m_components.begin(), m_components.end(),
+ [type](const auto& cmp) { return cmp.component_type == type; });
+}
+
+
std::string Box_cmpd::dump(Indent& indent) const
{
std::ostringstream sstr;
diff --git a/libheif/codecs/uncompressed/unc_boxes.h b/libheif/codecs/uncompressed/unc_boxes.h
index dc421fd6..79bdd4eb 100644
--- a/libheif/codecs/uncompressed/unc_boxes.h
+++ b/libheif/codecs/uncompressed/unc_boxes.h
@@ -60,6 +60,8 @@ public:
const std::vector<Component>& get_components() const { return m_components; }
+ bool has_component(heif_uncompressed_component_type) const;
+
void add_component(const Component& component)
{
m_components.push_back(component);
diff --git a/libheif/sequences/track_visual.cc b/libheif/sequences/track_visual.cc
index 53b056a2..7cf8e6fd 100644
--- a/libheif/sequences/track_visual.cc
+++ b/libheif/sequences/track_visual.cc
@@ -28,6 +28,7 @@
#include "context.h"
#include "api_structs.h"
#include "codecs/hevc_boxes.h"
+#include "codecs/uncompressed/unc_boxes.h"
Track_Visual::Track_Visual(HeifContext* ctx)
@@ -134,6 +135,31 @@ Track_Visual::Track_Visual(HeifContext* ctx, uint32_t track_id, uint16_t width,
}
+bool Track_Visual::has_alpha_channel() const
+{
+ if (m_aux_alpha_track != nullptr) {
+ return true;
+ }
+
+ // --- special case: 'uncv' with alpha component
+
+ if (m_stsd) {
+ auto sampleEntry = m_stsd->get_sample_entry(0);
+ if (sampleEntry) {
+ if (auto box_uncv = std::dynamic_pointer_cast<const Box_uncv>(sampleEntry)) {
+ if (auto cmpd = box_uncv->get_child_box<const Box_cmpd>()) {
+ if (cmpd->has_component(component_type_alpha)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
Result<std::shared_ptr<HeifPixelImage> > Track_Visual::decode_next_image_sample(const heif_decoding_options& options)
{
// --- If we ignore the editlist, we stop when we reached the end of the original samples.
@@ -356,7 +382,8 @@ Error Track_Visual::encode_image(std::shared_ptr<HeifPixelImage> image,
// --- If input has an alpha channel, add an alpha auxiliary track.
- if (in_options->save_alpha_channel && image->has_alpha() && !m_aux_alpha_track) {
+ if (in_options->save_alpha_channel && image->has_alpha() && !m_aux_alpha_track &&
+ h_encoder->plugin->compression_format != heif_compression_uncompressed) { // TODO: ask plugin
if (m_active_encoder) {
return {
heif_error_Usage_error,
diff --git a/libheif/sequences/track_visual.h b/libheif/sequences/track_visual.h
index 4eeab87f..e99534e5 100644
--- a/libheif/sequences/track_visual.h
+++ b/libheif/sequences/track_visual.h
@@ -47,7 +47,7 @@ public:
uint16_t get_height() const { return m_height; }
- bool has_alpha_channel() const override { return m_aux_alpha_track != nullptr; }
+ bool has_alpha_channel() const override;
Result<std::shared_ptr<HeifPixelImage>> decode_next_image_sample(const heif_decoding_options& options);