Commit ed3aba98 for libheif

commit ed3aba982de376f80ab083fdcbc184f927fd48fd
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Mon Oct 5 17:59:44 2026 +0200

    Do not compare the luma bit depth of 'unci' images with several luma components

    check_decoded_image_bit_depth() (770b0d8d) compares the bit depth that
    the image handle reports with the Y plane of the decoded image. For an
    'unci' image, the handle reports the largest bit depth of its luma or
    monochrome components, while the Y plane of the decoded image is the
    first of them. An image with several such components, of which the first
    has fewer bits than a later one (e.g. two monochrome bands with 8 and 16
    bits), was therefore refused with "Decoded image does not have the bit
    depth signaled in the file". v1.23.5 decoded these images.

    A single value cannot describe several components with different bit
    depths, which is also why the chroma depth is only compared when Cb and
    Cr agree. The luma depth is not compared anymore when the image has more
    than one component that is mapped to the Y channel.

    For such an image, the bit depth of the handle can still differ from the
    bit depth of its first luma plane, as it did in v1.23.5.

diff --git a/libheif/image-items/image_item.cc b/libheif/image-items/image_item.cc
index 303ded2c..f468e9cc 100644
--- a/libheif/image-items/image_item.cc
+++ b/libheif/image-items/image_item.cc
@@ -1669,7 +1669,18 @@ Error ImageItem::check_decoded_image_bit_depth(const HeifPixelImage& img) const

   bool mismatch = false;

-  if (luma_bpp > 0 && img.has_channel(heif_channel_Y) &&
+  // The handle reports a single luma bit depth. An 'unci' image can have several components
+  // that are mapped to the Y channel (e.g. several monochrome bands) with different bit
+  // depths. A single value cannot describe them (the handle reports the largest one), so the
+  // luma depth is not compared when there are several such components.
+  int num_luma_components = 0;
+  for (const ComponentDescription& component : img.get_component_descriptions()) {
+    if (component.channel == heif_channel_Y && component.has_data_plane) {
+      num_luma_components++;
+    }
+  }
+
+  if (luma_bpp > 0 && num_luma_components <= 1 && img.has_channel(heif_channel_Y) &&
       img.get_bits_per_pixel(heif_channel_Y) != luma_bpp) {
     mismatch = true;
   }