Commit d0f4669c for libheif

commit d0f4669c287b87b0d2352db30f6f58b7e77995b0
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Fri Apr 3 15:08:23 2026 +0200

    fix type mismatches because of new uint16_t bpp

diff --git a/libheif/box.h b/libheif/box.h
index 103ccab6..14a85ca3 100644
--- a/libheif/box.h
+++ b/libheif/box.h
@@ -1260,9 +1260,15 @@ public:

   int get_bits_per_channel(int channel) const { return m_bits_per_channel[channel]; }

-  void add_channel_bits(uint8_t c)
+  bool add_channel_bits(uint16_t c)
   {
-    m_bits_per_channel.push_back(c);
+    if (c <= 255) {
+      m_bits_per_channel.push_back(static_cast<uint8_t>(c));
+      return true;
+    }
+    else {
+      return false;
+    }
   }

   std::string dump(Indent&) const override;
diff --git a/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc
index 80b18c89..fe904b73 100644
--- a/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_rgb_block_pixel_interleave.cc
@@ -62,9 +62,10 @@ unc_encoder_rgb_block_pixel_interleave::unc_encoder_rgb_block_pixel_interleave(c
   auto cmpd_idx = image->get_component_cmpd_indices_interleaved();
   assert(cmpd_idx.size() == 3);

-  uint8_t bpp = image->get_bits_per_pixel(heif_channel_interleaved);
+  uint16_t bpp = image->get_bits_per_pixel(heif_channel_interleaved);

-  uint8_t nBits = static_cast<uint8_t>(3 * bpp);
+  uint16_t nBits = 3 * bpp;
+  assert(nBits <= 256-8);
   m_bytes_per_pixel = static_cast<uint8_t>((nBits + 7) / 8);

   m_uncC->set_interleave_type(interleave_mode_pixel);
@@ -89,7 +90,7 @@ std::vector<uint8_t> unc_encoder_rgb_block_pixel_interleave::encode_tile(const s
 {
   std::vector<uint8_t> data;

-  uint8_t bpp = src_image->get_bits_per_pixel(heif_channel_interleaved);
+  uint16_t bpp = src_image->get_bits_per_pixel(heif_channel_interleaved);

   size_t src_stride;
   const auto* src_data = reinterpret_cast<const uint16_t*>(src_image->get_plane(heif_channel_interleaved, &src_stride));
diff --git a/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc
index 64cf7444..c337f643 100644
--- a/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_rgb_bytealign_pixel_interleave.cc
@@ -69,7 +69,7 @@ unc_encoder_rgb_bytealign_pixel_interleave::unc_encoder_rgb_bytealign_pixel_inte
   bool little_endian = (image->get_chroma_format() == heif_chroma_interleaved_RRGGBB_LE ||
                         image->get_chroma_format() == heif_chroma_interleaved_RRGGBBAA_LE);

-  uint8_t bpp = image->get_bits_per_pixel(heif_channel_interleaved);
+  uint16_t bpp = image->get_bits_per_pixel(heif_channel_interleaved);

   uint8_t component_align_size = 2;
   if (bpp == 16) {
diff --git a/libheif/codecs/uncompressed/unc_encoder_rgb_pixel_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_rgb_pixel_interleave.cc
index bfac3a46..484ac5ef 100644
--- a/libheif/codecs/uncompressed/unc_encoder_rgb_pixel_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_rgb_pixel_interleave.cc
@@ -61,7 +61,7 @@ unc_encoder_rgb_pixel_interleave::unc_encoder_rgb_pixel_interleave(const std::sh
   m_bytes_per_pixel = save_alpha ? 4 : 3;
   assert(cmpd_idx.size() == m_bytes_per_pixel);

-  uint8_t bpp = image->get_bits_per_pixel(heif_channel_interleaved);
+  uint16_t bpp = image->get_bits_per_pixel(heif_channel_interleaved);

   if (bpp == 8) {
     if (save_alpha) {
diff --git a/libheif/context.cc b/libheif/context.cc
index 8b7841c3..05719cb7 100644
--- a/libheif/context.cc
+++ b/libheif/context.cc
@@ -1434,7 +1434,7 @@ Result<std::shared_ptr<HeifPixelImage>> HeifContext::convert_to_output_colorspac
   bool different_chroma = (target_chroma != img->get_chroma_format());
   bool different_colorspace = (target_colorspace != img->get_colorspace());

-  uint8_t img_bpp = img->get_visual_image_bits_per_pixel();
+  uint16_t img_bpp = img->get_visual_image_bits_per_pixel();
   uint8_t converted_output_bpp = (options.convert_hdr_to_8bit && img_bpp > 8) ? 8 : 0 /* keep input depth */;

   nclx_profile img_nclx = img->get_color_profile_nclx_with_fallback();
diff --git a/libheif/image-items/image_item.cc b/libheif/image-items/image_item.cc
index ab3bf239..50df0b92 100644
--- a/libheif/image-items/image_item.cc
+++ b/libheif/image-items/image_item.cc
@@ -321,22 +321,24 @@ Result<Encoder::CodedImageData> ImageItem::encode_to_bitstream_and_boxes(const s
   // --- write PIXI property

   std::shared_ptr<Box_pixi> pixi = std::make_shared<Box_pixi>();
+  bool valid_pixi = false;
+
   if (colorspace == heif_colorspace_filter_array) {
     // Skip pixi for filter array images — bit depth info is in uncC
   }
   else if (colorspace == heif_colorspace_monochrome) {
-    pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_Y));
+    valid_pixi = pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_Y));
   }
   else if (colorspace == heif_colorspace_YCbCr) {
-    pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_Y));
-    pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_Cb));
-    pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_Cr));
+    valid_pixi = (pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_Y)) ||
+                  pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_Cb)) ||
+                  pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_Cr)));
   }
   else if (colorspace == heif_colorspace_RGB) {
     if (chroma == heif_chroma_444) {
-      pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_R));
-      pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_G));
-      pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_B));
+      valid_pixi = (pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_R)) ||
+                    pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_G)) ||
+                    pixi->add_channel_bits(image->get_bits_per_pixel(heif_channel_B)));
     }
     else if (chroma == heif_chroma_interleaved_RGB ||
              chroma == heif_chroma_interleaved_RGBA ||
@@ -344,14 +346,14 @@ Result<Encoder::CodedImageData> ImageItem::encode_to_bitstream_and_boxes(const s
              chroma == heif_chroma_interleaved_RRGGBB_BE ||
              chroma == heif_chroma_interleaved_RRGGBBAA_LE ||
              chroma == heif_chroma_interleaved_RRGGBBAA_BE) {
-      uint8_t bpp = image->get_bits_per_pixel(heif_channel_interleaved);
-      pixi->add_channel_bits(bpp);
-      pixi->add_channel_bits(bpp);
-      pixi->add_channel_bits(bpp);
+      uint16_t bpp = image->get_bits_per_pixel(heif_channel_interleaved);
+      valid_pixi = (pixi->add_channel_bits(bpp) ||
+                    pixi->add_channel_bits(bpp) ||
+                    pixi->add_channel_bits(bpp));
     }
   }

-  if (pixi->get_num_channels() != 0) {
+  if (valid_pixi) {
     codedImage.properties.push_back(pixi);
   }

diff --git a/libheif/image-items/mask_image.cc b/libheif/image-items/mask_image.cc
index 5492304d..ae783da1 100644
--- a/libheif/image-items/mask_image.cc
+++ b/libheif/image-items/mask_image.cc
@@ -193,7 +193,15 @@ Result<Encoder::CodedImageData> ImageItem_mask::encode(const std::shared_ptr<Hei
   }

   std::shared_ptr<Box_mskC> mskC = std::make_shared<Box_mskC>();
-  mskC->set_bits_per_pixel(image->get_bits_per_pixel(heif_channel_Y));
+  uint16_t bpp = image->get_bits_per_pixel(heif_channel_Y);
+  if (bpp > 255) {
+    return Error{
+      heif_error_Invalid_input,
+      heif_suberror_Unspecified,
+      "Too many bits per pixel for mask image."
+    };
+  }
+  mskC->set_bits_per_pixel(static_cast<uint8_t>(bpp));
   codedImageData.properties.push_back(mskC);

   return codedImageData;
diff --git a/libheif/pixelimage.cc b/libheif/pixelimage.cc
index c945976d..aec45672 100644
--- a/libheif/pixelimage.cc
+++ b/libheif/pixelimage.cc
@@ -955,7 +955,7 @@ std::set<heif_channel> HeifPixelImage::get_channel_set() const
 }


-uint8_t HeifPixelImage::get_storage_bits_per_pixel(enum heif_channel channel) const
+uint16_t HeifPixelImage::get_storage_bits_per_pixel(enum heif_channel channel) const
 {
   auto* comp = find_component_for_channel(channel);
   if (!comp) {
@@ -963,12 +963,12 @@ uint8_t HeifPixelImage::get_storage_bits_per_pixel(enum heif_channel channel) co
   }

   uint32_t bpp = comp->get_bytes_per_pixel() * 8;
-  assert(bpp <= 255);
+  assert(bpp <= 256);
   return static_cast<uint8_t>(bpp);
 }


-uint8_t HeifPixelImage::get_bits_per_pixel(enum heif_channel channel) const
+uint16_t HeifPixelImage::get_bits_per_pixel(enum heif_channel channel) const
 {
   auto* comp = find_component_for_channel(channel);
   if (!comp) {
@@ -979,7 +979,7 @@ uint8_t HeifPixelImage::get_bits_per_pixel(enum heif_channel channel) const
 }


-uint8_t HeifPixelImage::get_visual_image_bits_per_pixel() const
+uint16_t HeifPixelImage::get_visual_image_bits_per_pixel() const
 {
   switch (m_colorspace) {
     case heif_colorspace_monochrome:
@@ -2246,7 +2246,7 @@ uint16_t HeifPixelImage::get_component_storage_bits_per_pixel(uint32_t component
   auto* comp = find_component_by_index(component_idx);
   assert(comp);
   uint32_t bpp = comp->get_bytes_per_pixel() * 8;
-  assert(bpp <= 256);
+  assert(bpp);
   return static_cast<uint16_t>(bpp);
 }

diff --git a/libheif/pixelimage.h b/libheif/pixelimage.h
index c07513ce..40c7b92a 100644
--- a/libheif/pixelimage.h
+++ b/libheif/pixelimage.h
@@ -380,12 +380,12 @@ public:

   std::set<heif_channel> get_channel_set() const;

-  uint8_t get_storage_bits_per_pixel(heif_channel channel) const;
+  uint16_t get_storage_bits_per_pixel(heif_channel channel) const;

-  uint8_t get_bits_per_pixel(heif_channel channel) const;
+  uint16_t get_bits_per_pixel(heif_channel channel) const;

   // Get the maximum bit depth of a visual channel (YCbCr or RGB).
-  uint8_t get_visual_image_bits_per_pixel() const;
+  uint16_t get_visual_image_bits_per_pixel() const;

   heif_channel_datatype get_datatype(heif_channel channel) const;