Commit bf71aa19 for libheif

commit bf71aa19169c554ae4f8cfd7906d5800ffce0e25
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Thu Mar 5 21:35:54 2026 +0100

    check if unci's icef is compatible with tili

diff --git a/libheif/image-items/tiled.cc b/libheif/image-items/tiled.cc
index eaff6917..3afb9f73 100644
--- a/libheif/image-items/tiled.cc
+++ b/libheif/image-items/tiled.cc
@@ -24,6 +24,7 @@
 #include <algorithm>
 #include "security_limits.h"
 #include "codecs/hevc_dec.h"
+#include "codecs/uncompressed/unc_boxes.h"
 #include "api_structs.h"


@@ -553,7 +554,24 @@ Error ImageItem_Tiled::initialize_decoder()
       return propertiesResult.error();
     }

-    m_tile_item->set_properties(*propertiesResult);
+    // Filter out per-tile boxes incompatible with tili's shared template
+    auto props = *propertiesResult;
+    for (const auto& box : props) {
+      if (box->get_short_type() == fourcc("icef")) {
+        auto icef = std::dynamic_pointer_cast<Box_icef>(box);
+        if (icef && icef->get_units().size() > 1) {
+          return {heif_error_Invalid_input,
+                  heif_suberror_Unspecified,
+                  "icef box with multiple units is incompatible with tili shared tile template."};
+        }
+      }
+    }
+    std::erase_if(props, [](const std::shared_ptr<Box>& box) {
+      uint32_t type = box->get_short_type();
+      return type == fourcc("icef") || type == fourcc("sbpm") || type == fourcc("snuc");
+    });
+
+    m_tile_item->set_properties(props);
   }
   else {
     // --- This is the new method
@@ -562,6 +580,22 @@ Error ImageItem_Tiled::initialize_decoder()

     auto tile_properties = tilC_box->get_all_child_boxes();

+    // Filter out per-tile boxes incompatible with tili's shared template
+    for (const auto& box : tile_properties) {
+      if (box->get_short_type() == fourcc("icef")) {
+        auto icef = std::dynamic_pointer_cast<Box_icef>(box);
+        if (icef && icef->get_units().size() > 1) {
+          return {heif_error_Invalid_input,
+                  heif_suberror_Unspecified,
+                  "icef box with multiple units is incompatible with tili shared tile template."};
+        }
+      }
+    }
+    std::erase_if(tile_properties, [](const std::shared_ptr<Box>& box) {
+      uint32_t type = box->get_short_type();
+      return type == fourcc("icef") || type == fourcc("sbpm") || type == fourcc("snuc");
+    });
+
     bool have_ispe = false;
     for (const auto& property : tile_properties) {
       if (property->get_short_type() == fourcc("ispe")) {
@@ -734,6 +768,24 @@ Error ImageItem_Tiled::add_image_tile(uint32_t tile_x, uint32_t tile_y,
       continue;
     }

+    // icef/sbpm/snuc contain per-tile data incompatible with tili's shared tile template
+    uint32_t ptype = propertyBox->get_short_type();
+    if (ptype == fourcc("icef")) {
+      auto icef = std::dynamic_pointer_cast<Box_icef>(propertyBox);
+      if (icef && icef->get_units().size() > 1) {
+        return {heif_error_Usage_error,
+                heif_suberror_Unspecified,
+                "icef box with multiple units is incompatible with tili shared tile template."};
+      }
+      // Single-unit icef can be safely skipped
+      continue;
+    }
+    if (ptype == fourcc("sbpm") || ptype == fourcc("snuc")) {
+      return {heif_error_Usage_error,
+              heif_suberror_Unspecified,
+              "Cannot store per-tile property (" + fourcc_to_string(ptype) + ") in tili shared tile template."};
+    }
+
     // skip properties that exist already

     bool exists = std::any_of(tile_properties.begin(),