Commit 0d974ae0 for libheif
commit 0d974ae0896b0057ec895aa544a1ab7bb02d9f81
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Fri Feb 27 12:56:38 2026 +0100
unci: adapt public API to handle non-contiguous component indices
diff --git a/libheif/api/libheif/heif_experimental.cc b/libheif/api/libheif/heif_experimental.cc
index e9183451..9fedd7bc 100644
--- a/libheif/api/libheif/heif_experimental.cc
+++ b/libheif/api/libheif/heif_experimental.cc
@@ -340,65 +340,36 @@ void heif_pyramid_layer_info_release(heif_pyramid_layer_info* infos)
}
-heif_error heif_image_add_channel(heif_image* image,
- heif_channel channel,
- int width, int height,
- heif_channel_datatype datatype, int bit_depth)
-{
- if (auto err = image->image->add_channel(channel, width, height, datatype, bit_depth, nullptr)) {
- return err.error_struct(image->image.get());
- }
- else {
- return heif_error_success;
- }
-}
-
+// --- index-based component access
-heif_channel_datatype heif_image_get_datatype(const heif_image* image, heif_channel channel)
+uint32_t heif_image_get_number_of_used_components(const heif_image* image)
{
- if (image == nullptr) {
- return heif_channel_datatype_undefined;
+ if (!image || !image->image) {
+ return 0;
}
-
- return image->image->get_datatype(channel);
+ return image->image->get_number_of_used_components();
}
-int heif_image_list_channels(heif_image* image,
- heif_channel** out_channels)
+uint32_t heif_image_get_total_number_of_cmpd_components(const heif_image* image)
{
- if (!image || !out_channels) {
+ if (!image || !image->image) {
return 0;
}
-
- auto channels = image->image->get_channel_set();
-
- *out_channels = new heif_channel[channels.size()];
- heif_channel* p = *out_channels;
- for (heif_channel c : channels) {
- *p++ = c;
- }
-
- assert(channels.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
-
- return static_cast<int>(channels.size());
+ return image->image->get_total_number_of_cmpd_components();
}
-void heif_channel_release_list(heif_channel** channels)
+void heif_image_get_used_component_indices(const heif_image* image, uint32_t* out_component_indices)
{
- delete[] channels;
-}
-
-
-// --- index-based component access
+ if (!image || !image->image || !out_component_indices) {
+ return;
+ }
-uint32_t heif_image_get_number_of_components(const heif_image* image)
-{
- if (!image || !image->image) {
- return 0;
+ auto indices = image->image->get_used_component_indices();
+ for (size_t i = 0; i < indices.size(); i++) {
+ out_component_indices[i] = indices[i];
}
- return image->image->get_number_of_components();
}
diff --git a/libheif/api/libheif/heif_experimental.h b/libheif/api/libheif/heif_experimental.h
index 1b8e3bde..d2d7a546 100644
--- a/libheif/api/libheif/heif_experimental.h
+++ b/libheif/api/libheif/heif_experimental.h
@@ -188,23 +188,6 @@ typedef enum heif_channel_datatype
heif_channel_datatype_complex_number = 4
} heif_channel_datatype;
-#if HEIF_ENABLE_EXPERIMENTAL_FEATURES
-LIBHEIF_API
-heif_error heif_image_add_channel(heif_image* image,
- enum heif_channel channel,
- int width, int height,
- enum heif_channel_datatype datatype,
- int bit_depth);
-
-
-LIBHEIF_API
-int heif_image_list_channels(heif_image*,
- enum heif_channel** out_channels);
-
-LIBHEIF_API
-void heif_channel_release_list(enum heif_channel** channels);
-#endif
-
typedef struct heif_complex32
{
float real, imaginary;
@@ -216,15 +199,21 @@ typedef struct heif_complex64
} heif_complex64;
#if HEIF_ENABLE_EXPERIMENTAL_FEATURES
-LIBHEIF_API
-enum heif_channel_datatype heif_image_get_datatype(const heif_image* img,
- enum heif_channel channel);
-
// --- index-based component access (for ISO 23001-17 multi-component images)
+// Returns the number of components that have pixel data (planes) in this image.
+LIBHEIF_API
+uint32_t heif_image_get_number_of_used_components(const heif_image*);
+
+// Returns the total number of components declared in the cmpd box.
+LIBHEIF_API
+uint32_t heif_image_get_total_number_of_cmpd_components(const heif_image*);
+
+// Fills `out_component_indices` with the valid component indices.
+// The caller must allocate an array of at least heif_image_get_number_of_used_components() elements.
LIBHEIF_API
-uint32_t heif_image_get_number_of_components(const heif_image*);
+void heif_image_get_used_component_indices(const heif_image*, uint32_t* out_component_indices);
LIBHEIF_API
enum heif_channel heif_image_get_component_channel(const heif_image*, uint32_t component_idx);
diff --git a/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
index a24bc808..0fac9295 100644
--- a/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
@@ -50,7 +50,7 @@ unc_encoder_component_interleave::unc_encoder_component_interleave(const std::sh
const heif_encoding_options& options)
{
bool is_nonvisual = (image->get_colorspace() == heif_colorspace_nonvisual);
- uint32_t num_components = image->get_number_of_components();
+ uint32_t num_components = image->get_number_of_used_components();
for (uint32_t idx = 0; idx < num_components; idx++) {
heif_uncompressed_component_type comp_type;
diff --git a/libheif/pixelimage.cc b/libheif/pixelimage.cc
index e76fc271..0ff24ef8 100644
--- a/libheif/pixelimage.cc
+++ b/libheif/pixelimage.cc
@@ -2232,7 +2232,7 @@ Result<uint32_t> HeifPixelImage::add_component_for_index(uint32_t component_inde
}
-std::vector<uint32_t> HeifPixelImage::get_component_indices() const
+std::vector<uint32_t> HeifPixelImage::get_used_component_indices() const
{
std::vector<uint32_t> indices;
indices.reserve(m_planes.size());
diff --git a/libheif/pixelimage.h b/libheif/pixelimage.h
index f79e4bf0..5e53888d 100644
--- a/libheif/pixelimage.h
+++ b/libheif/pixelimage.h
@@ -416,7 +416,9 @@ public:
// --- index-based component access (for ISO 23001-17 multi-component images)
- uint32_t get_number_of_components() const { return static_cast<uint32_t>(m_planes.size()); }
+ uint32_t get_number_of_used_components() const { return static_cast<uint32_t>(m_planes.size()); }
+
+ uint32_t get_total_number_of_cmpd_components() const { return static_cast<uint32_t>(m_cmpd_component_types.size()); }
heif_channel get_component_channel(uint32_t component_idx) const;
@@ -445,8 +447,8 @@ public:
// Populate the cmpd component types table (decoder path).
void set_cmpd_component_types(std::vector<uint16_t> types) { m_cmpd_component_types = std::move(types); }
- // Returns the sorted list of component_indices of all planes.
- std::vector<uint32_t> get_component_indices() const;
+ // Returns the sorted list of component_indices of all planes that have pixel data.
+ std::vector<uint32_t> get_used_component_indices() const;
uint8_t* get_component(uint32_t component_idx, size_t* out_stride);
const uint8_t* get_component(uint32_t component_idx, size_t* out_stride) const;
diff --git a/tests/uncompressed_encode_multicomponent.cc b/tests/uncompressed_encode_multicomponent.cc
index 96bb8105..b531a9d8 100644
--- a/tests/uncompressed_encode_multicomponent.cc
+++ b/tests/uncompressed_encode_multicomponent.cc
@@ -308,7 +308,7 @@ bool values_equal<heif_complex64>(heif_complex64 a, heif_complex64 b)
template <typename T>
static void verify_image_data(const heif_image* image)
{
- uint32_t num_components = heif_image_get_number_of_components(image);
+ uint32_t num_components = heif_image_get_number_of_used_components(image);
REQUIRE(num_components == kNumComponents);
for (uint32_t c = 0; c < kNumComponents; c++) {