Commit b1943651 for libheif

commit b194365135784e41716a0e5b432d7f79c867ec1d
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Tue Feb 24 00:13:20 2026 +0100

    improve decoded image size check to make it work with non-visual unci images (#1709)

diff --git a/libheif/api/libheif/heif_image.cc b/libheif/api/libheif/heif_image.cc
index e19af209..d0af524d 100644
--- a/libheif/api/libheif/heif_image.cc
+++ b/libheif/api/libheif/heif_image.cc
@@ -68,35 +68,15 @@ int heif_image_get_height(const heif_image* img, heif_channel channel)

 int heif_image_get_primary_width(const heif_image* img)
 {
-  return uint32_to_int(img->image->get_primary_width());
-  if (img->image->get_colorspace() == heif_colorspace_RGB) {
-    if (img->image->get_chroma_format() == heif_chroma_444) {
-      return uint32_to_int(img->image->get_width(heif_channel_G));
-    }
-    else {
-      return uint32_to_int(img->image->get_width(heif_channel_interleaved));
-    }
-  }
-  else {
-    return uint32_to_int(img->image->get_width(heif_channel_Y));
-  }
+  uint32_t primary_component = img->image->get_primary_component();
+  return uint32_to_int(img->image->get_width(primary_component));
 }


 int heif_image_get_primary_height(const heif_image* img)
 {
-  return uint32_to_int(img->image->get_primary_height());
-  if (img->image->get_colorspace() == heif_colorspace_RGB) {
-    if (img->image->get_chroma_format() == heif_chroma_444) {
-      return uint32_to_int(img->image->get_height(heif_channel_G));
-    }
-    else {
-      return uint32_to_int(img->image->get_height(heif_channel_interleaved));
-    }
-  }
-  else {
-    return uint32_to_int(img->image->get_height(heif_channel_Y));
-  }
+  uint32_t primary_component = img->image->get_primary_component();
+  return uint32_to_int(img->image->get_height(primary_component));
 }


diff --git a/libheif/context.cc b/libheif/context.cc
index 8ad18ee3..a2be4750 100644
--- a/libheif/context.cc
+++ b/libheif/context.cc
@@ -1313,16 +1313,17 @@ Result<std::shared_ptr<HeifPixelImage>> HeifContext::decode_image(heif_item_id I

   // --- check that the decoded image has the claimed size (only check if transformations are applied)

-  if (!options.ignore_transformations &&
-      !(img->get_colorspace() == heif_colorspace_nonvisual ||
-        img->get_colorspace() == heif_colorspace_undefined) &&
-      (imgitem->get_width() != img->get_primary_width() ||
-       imgitem->get_height() != img->get_primary_height())) {
-    return Error{
-      heif_error_Invalid_input,
-      heif_suberror_Invalid_image_size,
-      "Decoded image does not have the claimed size."
-    };
+  if (!options.ignore_transformations) {
+    uint32_t primary_component = img->get_primary_component();
+
+    if (imgitem->get_width() != img->get_width(primary_component) ||
+        imgitem->get_height() != img->get_height(primary_component)) {
+      return Error{
+        heif_error_Invalid_input,
+        heif_suberror_Invalid_image_size,
+        "Decoded image does not have the claimed size."
+      };
+    }
   }

   // --- convert to output chroma format
diff --git a/libheif/pixelimage.cc b/libheif/pixelimage.cc
index 113c6a5e..ccc42cc1 100644
--- a/libheif/pixelimage.cc
+++ b/libheif/pixelimage.cc
@@ -716,6 +716,59 @@ uint32_t HeifPixelImage::get_height(enum heif_channel channel) const
 }


+uint32_t HeifPixelImage::get_width(uint32_t component_idx) const
+{
+  if (component_idx >= m_planes.size()) {
+    return 0;
+  }
+
+  return m_planes[component_idx].m_width;
+}
+
+
+uint32_t HeifPixelImage::get_height(uint32_t component_idx) const
+{
+  if (component_idx >= m_planes.size()) {
+    return 0;
+  }
+
+  return m_planes[component_idx].m_height;
+}
+
+
+uint32_t HeifPixelImage::get_primary_component() const
+{
+  // first pass: search for color channel
+
+  for (uint32_t idx=0; idx<m_planes.size(); idx++) {
+    if (m_planes[idx].m_channel == heif_channel_interleaved) {
+      return idx;
+    }
+
+    switch (m_planes[idx].m_component_type) {
+      case component_type_Y:
+      case component_type_monochrome:
+      case component_type_red:
+      case component_type_green:
+      case component_type_blue:
+      case component_type_cyan:
+      case component_type_magenta:
+      case component_type_yellow:
+      case component_type_key_black:
+      case component_type_filter_array:
+      case component_type_palette:
+        return idx;
+
+      default:
+        ; // NOP
+    }
+  }
+
+  // second pass: allow anything
+
+  return 0;
+}
+#if 0
 uint32_t HeifPixelImage::get_primary_width() const
 {
   if (m_colorspace == heif_colorspace_RGB) {
@@ -746,7 +799,7 @@ uint32_t HeifPixelImage::get_primary_height() const
     return get_height(heif_channel_Y);
   }
 }
-
+#endif

 std::set<heif_channel> HeifPixelImage::get_channel_set() const
 {
diff --git a/libheif/pixelimage.h b/libheif/pixelimage.h
index f11a4a60..396c10a6 100644
--- a/libheif/pixelimage.h
+++ b/libheif/pixelimage.h
@@ -239,15 +239,21 @@ public:

   uint32_t get_height(heif_channel channel) const;

+  uint32_t get_width(uint32_t component_idx) const;
+
+  uint32_t get_height(uint32_t component_idx) const;
+
   bool has_odd_width() const { return !!(m_width & 1); }

   bool has_odd_height() const { return !!(m_height & 1); }

   // TODO: currently only defined for colorspace RGB, YCbCr, Monochrome
-  uint32_t get_primary_width() const;
+  //uint32_t get_primary_width() const;

   // TODO: currently only defined for colorspace RGB, YCbCr, Monochrome
-  uint32_t get_primary_height() const;
+  //uint32_t get_primary_height() const;
+
+  uint32_t get_primary_component() const;

   heif_chroma get_chroma_format() const { return m_chroma; }