Commit d10444cb for libheif
commit d10444cb3c12c8a14e391dffcf415f5b9b9fda2b
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Fri Apr 3 14:38:48 2026 +0200
unci: support up to 256bpp in unc_encoder_component_interleave
diff --git a/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
index 67a2e0e8..874b040d 100644
--- a/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
@@ -33,6 +33,43 @@ bool unc_encoder_factory_component_interleave::can_encode(const std::shared_ptr<
return false;
}
+ // If any component is not byte-aligned, we use the bit-packing path which
+ // reads samples as uint32_t, limiting all components to 32 bpp.
+ bool any_non_aligned = false;
+ uint32_t num_components = image->get_number_of_used_components();
+ for (uint32_t idx = 0; idx < num_components; idx++) {
+ uint16_t bpp = image->get_component_bits_per_pixel(idx);
+ if (bpp % 8 != 0) {
+ any_non_aligned = true;
+ }
+ }
+
+ if (any_non_aligned) {
+ for (uint32_t idx = 0; idx < num_components; idx++) {
+ if (image->get_component_bits_per_pixel(idx) > 32) {
+ return false;
+ }
+ }
+ }
+
+ if (!any_non_aligned) {
+ // All components are byte-aligned. Only accept typical integer widths.
+ for (uint32_t idx = 0; idx < num_components; idx++) {
+ uint16_t bpp = image->get_component_bits_per_pixel(idx);
+ switch (bpp) {
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ case 256:
+ break;
+ default:
+ return false;
+ }
+ }
+ }
+
return true;
}
@@ -68,7 +105,7 @@ unc_encoder_component_interleave::unc_encoder_component_interleave(const std::sh
}
}
- uint8_t bpp = image->get_component_bits_per_pixel(idx);
+ uint16_t bpp = image->get_component_bits_per_pixel(idx);
auto comp_format = to_unc_component_format(image->get_component_datatype(idx));
bool aligned = (bpp % 8 == 0);
@@ -153,7 +190,7 @@ std::vector<uint8_t> unc_encoder_component_interleave::encode_tile(const std::sh
for (const auto& comp : m_components) {
uint32_t plane_width = src_image->get_component_width(comp.component_idx);
uint32_t plane_height = src_image->get_component_height(comp.component_idx);
- uint8_t bpp = comp.bpp;
+ uint16_t bpp = comp.bpp;
size_t src_stride;
const uint8_t* src_data = src_image->get_component(comp.component_idx, &src_stride);
diff --git a/libheif/codecs/uncompressed/unc_encoder_component_interleave.h b/libheif/codecs/uncompressed/unc_encoder_component_interleave.h
index b2c954c3..db84e99b 100644
--- a/libheif/codecs/uncompressed/unc_encoder_component_interleave.h
+++ b/libheif/codecs/uncompressed/unc_encoder_component_interleave.h
@@ -44,7 +44,7 @@ private:
heif_channel channel;
heif_uncompressed_component_type component_type;
heif_uncompressed_component_format component_format;
- uint8_t bpp;
+ uint16_t bpp;
bool byte_aligned;
};
diff --git a/libheif/pixelimage.cc b/libheif/pixelimage.cc
index 2ce28579..c945976d 100644
--- a/libheif/pixelimage.cc
+++ b/libheif/pixelimage.cc
@@ -2233,7 +2233,7 @@ uint32_t HeifPixelImage::get_component_height(uint32_t component_idx) const
}
-uint8_t HeifPixelImage::get_component_bits_per_pixel(uint32_t component_idx) const
+uint16_t HeifPixelImage::get_component_bits_per_pixel(uint32_t component_idx) const
{
auto* comp = find_component_by_index(component_idx);
assert(comp);
@@ -2241,13 +2241,13 @@ uint8_t HeifPixelImage::get_component_bits_per_pixel(uint32_t component_idx) con
}
-uint8_t HeifPixelImage::get_component_storage_bits_per_pixel(uint32_t component_idx) const
+uint16_t HeifPixelImage::get_component_storage_bits_per_pixel(uint32_t component_idx) const
{
auto* comp = find_component_by_index(component_idx);
assert(comp);
uint32_t bpp = comp->get_bytes_per_pixel() * 8;
- assert(bpp <= 255);
- return static_cast<uint8_t>(bpp);
+ assert(bpp <= 256);
+ return static_cast<uint16_t>(bpp);
}
diff --git a/libheif/pixelimage.h b/libheif/pixelimage.h
index 56c4d7f0..c07513ce 100644
--- a/libheif/pixelimage.h
+++ b/libheif/pixelimage.h
@@ -433,8 +433,8 @@ public:
uint32_t get_component_width(uint32_t component_idx) const;
uint32_t get_component_height(uint32_t component_idx) const;
- uint8_t get_component_bits_per_pixel(uint32_t component_idx) const;
- uint8_t get_component_storage_bits_per_pixel(uint32_t component_idx) const;
+ uint16_t get_component_bits_per_pixel(uint32_t component_idx) const;
+ uint16_t get_component_storage_bits_per_pixel(uint32_t component_idx) const;
heif_channel_datatype get_component_datatype(uint32_t component_idx) const;
// Look up the component type from the cmpd table. Works for any cmpd index,
@@ -571,7 +571,7 @@ private:
// logical bit depth per component
// For interleaved formats, it is the number of bits for one component.
// It is not the storage width.
- uint8_t m_bit_depth = 0;
+ uint16_t m_bit_depth = 0; // 1-256
uint8_t m_num_interleaved_components = 1;
// the "visible" area of the plane