Commit d50abb3e for libheif

commit d50abb3e78d27557ab03a60582ddc748e5d8998c
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Fri Feb 27 00:14:14 2026 +0100

    unci: implement sensor bad pixels map (sbpm)

diff --git a/libheif/api/libheif/heif_security.h b/libheif/api/libheif/heif_security.h
index 3760db22..f63f86c3 100644
--- a/libheif/api/libheif/heif_security.h
+++ b/libheif/api/libheif/heif_security.h
@@ -69,6 +69,10 @@ typedef struct heif_security_limits

   uint32_t max_sequence_frames;
   uint32_t max_number_of_file_brands;
+
+  // --- version 4
+
+  uint32_t max_bad_pixels;
 } heif_security_limits;


diff --git a/libheif/api/libheif/heif_uncompressed.cc b/libheif/api/libheif/heif_uncompressed.cc
index d40efcd0..4e129d24 100644
--- a/libheif/api/libheif/heif_uncompressed.cc
+++ b/libheif/api/libheif/heif_uncompressed.cc
@@ -254,6 +254,149 @@ int heif_image_get_polarization_pattern_index_for_component(const heif_image* im
 }


+heif_error heif_image_add_sensor_bad_pixels_map(heif_image* image,
+                                                 uint32_t num_component_indices,
+                                                 const uint32_t* component_indices,
+                                                 int correction_applied,
+                                                 uint32_t num_bad_rows,
+                                                 const uint32_t* bad_rows,
+                                                 uint32_t num_bad_columns,
+                                                 const uint32_t* bad_columns,
+                                                 uint32_t num_bad_pixels,
+                                                 const struct heif_bad_pixel* bad_pixels)
+{
+  if (image == nullptr) {
+    return heif_error_null_pointer_argument;
+  }
+
+  if (num_component_indices > 0 && component_indices == nullptr) {
+    return heif_error_null_pointer_argument;
+  }
+
+  if (num_bad_rows > 0 && bad_rows == nullptr) {
+    return heif_error_null_pointer_argument;
+  }
+
+  if (num_bad_columns > 0 && bad_columns == nullptr) {
+    return heif_error_null_pointer_argument;
+  }
+
+  if (num_bad_pixels > 0 && bad_pixels == nullptr) {
+    return heif_error_null_pointer_argument;
+  }
+
+  SensorBadPixelsMap map;
+  map.component_indices.assign(component_indices, component_indices + num_component_indices);
+  map.correction_applied = (correction_applied != 0);
+
+  map.bad_rows.assign(bad_rows, bad_rows + num_bad_rows);
+  map.bad_columns.assign(bad_columns, bad_columns + num_bad_columns);
+
+  map.bad_pixels.resize(num_bad_pixels);
+  for (uint32_t i = 0; i < num_bad_pixels; i++) {
+    map.bad_pixels[i].row = bad_pixels[i].row;
+    map.bad_pixels[i].column = bad_pixels[i].column;
+  }
+
+  image->image->add_sensor_bad_pixels_map(map);
+
+  return heif_error_success;
+}
+
+
+int heif_image_get_number_of_sensor_bad_pixels_maps(const heif_image* image)
+{
+  if (image == nullptr) {
+    return 0;
+  }
+
+  return static_cast<int>(image->image->get_sensor_bad_pixels_maps().size());
+}
+
+
+heif_error heif_image_get_sensor_bad_pixels_map_info(const heif_image* image,
+                                                      int map_index,
+                                                      uint32_t* out_num_component_indices,
+                                                      int* out_correction_applied,
+                                                      uint32_t* out_num_bad_rows,
+                                                      uint32_t* out_num_bad_columns,
+                                                      uint32_t* out_num_bad_pixels)
+{
+  if (image == nullptr) {
+    return heif_error_null_pointer_argument;
+  }
+
+  const auto& maps = image->image->get_sensor_bad_pixels_maps();
+  if (map_index < 0 || static_cast<size_t>(map_index) >= maps.size()) {
+    return {heif_error_Usage_error,
+            heif_suberror_Invalid_parameter_value,
+            "Sensor bad pixels map index out of range."};
+  }
+
+  const auto& m = maps[map_index];
+  if (out_num_component_indices) {
+    *out_num_component_indices = static_cast<uint32_t>(m.component_indices.size());
+  }
+  if (out_correction_applied) {
+    *out_correction_applied = m.correction_applied ? 1 : 0;
+  }
+  if (out_num_bad_rows) {
+    *out_num_bad_rows = static_cast<uint32_t>(m.bad_rows.size());
+  }
+  if (out_num_bad_columns) {
+    *out_num_bad_columns = static_cast<uint32_t>(m.bad_columns.size());
+  }
+  if (out_num_bad_pixels) {
+    *out_num_bad_pixels = static_cast<uint32_t>(m.bad_pixels.size());
+  }
+
+  return heif_error_success;
+}
+
+
+heif_error heif_image_get_sensor_bad_pixels_map_data(const heif_image* image,
+                                                      int map_index,
+                                                      uint32_t* out_component_indices,
+                                                      uint32_t* out_bad_rows,
+                                                      uint32_t* out_bad_columns,
+                                                      struct heif_bad_pixel* out_bad_pixels)
+{
+  if (image == nullptr) {
+    return heif_error_null_pointer_argument;
+  }
+
+  const auto& maps = image->image->get_sensor_bad_pixels_maps();
+  if (map_index < 0 || static_cast<size_t>(map_index) >= maps.size()) {
+    return {heif_error_Usage_error,
+            heif_suberror_Invalid_parameter_value,
+            "Sensor bad pixels map index out of range."};
+  }
+
+  const auto& m = maps[map_index];
+
+  if (out_component_indices && !m.component_indices.empty()) {
+    std::copy(m.component_indices.begin(), m.component_indices.end(), out_component_indices);
+  }
+
+  if (out_bad_rows && !m.bad_rows.empty()) {
+    std::copy(m.bad_rows.begin(), m.bad_rows.end(), out_bad_rows);
+  }
+
+  if (out_bad_columns && !m.bad_columns.empty()) {
+    std::copy(m.bad_columns.begin(), m.bad_columns.end(), out_bad_columns);
+  }
+
+  if (out_bad_pixels && !m.bad_pixels.empty()) {
+    for (size_t i = 0; i < m.bad_pixels.size(); i++) {
+      out_bad_pixels[i].row = m.bad_pixels[i].row;
+      out_bad_pixels[i].column = m.bad_pixels[i].column;
+    }
+  }
+
+  return heif_error_success;
+}
+
+
 heif_unci_image_parameters* heif_unci_image_parameters_alloc()
 {
   auto* params = new heif_unci_image_parameters();
diff --git a/libheif/api/libheif/heif_uncompressed.h b/libheif/api/libheif/heif_uncompressed.h
index c6e680d2..2d8bef15 100644
--- a/libheif/api/libheif/heif_uncompressed.h
+++ b/libheif/api/libheif/heif_uncompressed.h
@@ -152,6 +152,55 @@ int heif_image_get_polarization_pattern_index_for_component(const heif_image*,
                                                             uint32_t component_index);


+// --- Sensor bad pixels map (ISO 23001-17, Section 6.1.7)
+
+struct heif_bad_pixel { uint32_t row; uint32_t column; };
+
+// Add a sensor bad pixels map to an image.
+// component_indices: array of component indices this map applies to (may be NULL if num_component_indices == 0,
+//                    meaning the map applies to all components).
+// Multiple maps can be added (one per distinct component group with different defects).
+LIBHEIF_API
+heif_error heif_image_add_sensor_bad_pixels_map(heif_image*,
+                                                 uint32_t num_component_indices,
+                                                 const uint32_t* component_indices,
+                                                 int correction_applied,
+                                                 uint32_t num_bad_rows,
+                                                 const uint32_t* bad_rows,
+                                                 uint32_t num_bad_columns,
+                                                 const uint32_t* bad_columns,
+                                                 uint32_t num_bad_pixels,
+                                                 const struct heif_bad_pixel* bad_pixels);
+
+// Returns the number of sensor bad pixels maps on this image (0 if none).
+LIBHEIF_API
+int heif_image_get_number_of_sensor_bad_pixels_maps(const heif_image*);
+
+// Get the sizes of a sensor bad pixels map (to allocate arrays for the data query).
+LIBHEIF_API
+heif_error heif_image_get_sensor_bad_pixels_map_info(const heif_image*,
+                                                      int map_index,
+                                                      uint32_t* out_num_component_indices,
+                                                      int* out_correction_applied,
+                                                      uint32_t* out_num_bad_rows,
+                                                      uint32_t* out_num_bad_columns,
+                                                      uint32_t* out_num_bad_pixels);
+
+// Get the actual data of a sensor bad pixels map.
+// Caller must provide pre-allocated arrays:
+//   out_component_indices: num_component_indices entries (may be NULL if num_component_indices == 0)
+//   out_bad_rows: num_bad_rows entries (may be NULL if num_bad_rows == 0)
+//   out_bad_columns: num_bad_columns entries (may be NULL if num_bad_columns == 0)
+//   out_bad_pixels: num_bad_pixels entries (may be NULL if num_bad_pixels == 0)
+LIBHEIF_API
+heif_error heif_image_get_sensor_bad_pixels_map_data(const heif_image*,
+                                                      int map_index,
+                                                      uint32_t* out_component_indices,
+                                                      uint32_t* out_bad_rows,
+                                                      uint32_t* out_bad_columns,
+                                                      struct heif_bad_pixel* out_bad_pixels);
+
+
 // --- 'unci' images

 // This is similar to heif_metadata_compression. We should try to keep the integers compatible, but each enum will just
diff --git a/libheif/box.cc b/libheif/box.cc
index 945d1de9..47edd2bc 100644
--- a/libheif/box.cc
+++ b/libheif/box.cc
@@ -676,6 +676,10 @@ Error Box::read(BitstreamRange& range, std::shared_ptr<Box>* result, const heif_
       box = std::make_shared<Box_splz>();
       break;

+    case fourcc("sbpm"):
+      box = std::make_shared<Box_sbpm>();
+      break;
+
     case fourcc("uncv"):
       box = std::make_shared<Box_uncv>();
       break;
diff --git a/libheif/codecs/uncompressed/unc_boxes.cc b/libheif/codecs/uncompressed/unc_boxes.cc
index 0ddcd106..c2859e5e 100644
--- a/libheif/codecs/uncompressed/unc_boxes.cc
+++ b/libheif/codecs/uncompressed/unc_boxes.cc
@@ -1122,3 +1122,127 @@ Error Box_splz::write(StreamWriter& writer) const

   return Error::Ok;
 }
+
+
+Error Box_sbpm::parse(BitstreamRange& range, const heif_security_limits* limits)
+{
+  parse_full_box_header(range);
+
+  if (get_version() != 0) {
+    return unsupported_version_error("sbpm");
+  }
+
+  uint32_t component_count = range.read32();
+
+  if (limits->max_components && component_count > limits->max_components) {
+    return {heif_error_Invalid_input,
+            heif_suberror_Security_limit_exceeded,
+            "sbpm component_count exceeds security limit."};
+  }
+
+  m_map.component_indices.resize(component_count);
+  for (uint32_t i = 0; i < component_count; i++) {
+    m_map.component_indices[i] = range.read32();
+  }
+
+  uint8_t flags = range.read8();
+  m_map.correction_applied = !!(flags & 0x80);
+
+  uint32_t num_bad_rows = range.read32();
+  uint32_t num_bad_cols = range.read32();
+  uint32_t num_bad_pixels = range.read32();
+
+  // Security check: limit total number of entries
+  uint64_t total_entries = static_cast<uint64_t>(num_bad_rows) + num_bad_cols + num_bad_pixels;
+  if (limits->max_bad_pixels && total_entries > limits->max_bad_pixels) {
+    return {heif_error_Invalid_input,
+            heif_suberror_Security_limit_exceeded,
+            "sbpm total bad pixel entries exceed security limit."};
+  }
+
+  m_map.bad_rows.resize(num_bad_rows);
+  for (uint32_t i = 0; i < num_bad_rows; i++) {
+    m_map.bad_rows[i] = range.read32();
+  }
+
+  m_map.bad_columns.resize(num_bad_cols);
+  for (uint32_t i = 0; i < num_bad_cols; i++) {
+    m_map.bad_columns[i] = range.read32();
+  }
+
+  m_map.bad_pixels.resize(num_bad_pixels);
+  for (uint32_t i = 0; i < num_bad_pixels; i++) {
+    m_map.bad_pixels[i].row = range.read32();
+    m_map.bad_pixels[i].column = range.read32();
+  }
+
+  return range.get_error();
+}
+
+
+std::string Box_sbpm::dump(Indent& indent) const
+{
+  std::ostringstream sstr;
+
+  sstr << FullBox::dump(indent);
+
+  sstr << indent << "component_count: " << m_map.component_indices.size() << "\n";
+  for (size_t i = 0; i < m_map.component_indices.size(); i++) {
+    sstr << indent << "  component_index[" << i << "]: " << m_map.component_indices[i] << "\n";
+  }
+
+  sstr << indent << "correction_applied: " << m_map.correction_applied << "\n";
+
+  sstr << indent << "num_bad_rows: " << m_map.bad_rows.size() << "\n";
+  for (size_t i = 0; i < m_map.bad_rows.size(); i++) {
+    sstr << indent << "  bad_row[" << i << "]: " << m_map.bad_rows[i] << "\n";
+  }
+
+  sstr << indent << "num_bad_columns: " << m_map.bad_columns.size() << "\n";
+  for (size_t i = 0; i < m_map.bad_columns.size(); i++) {
+    sstr << indent << "  bad_column[" << i << "]: " << m_map.bad_columns[i] << "\n";
+  }
+
+  sstr << indent << "num_bad_pixels: " << m_map.bad_pixels.size() << "\n";
+  for (size_t i = 0; i < m_map.bad_pixels.size(); i++) {
+    sstr << indent << "  bad_pixel[" << i << "]: row=" << m_map.bad_pixels[i].row
+         << ", column=" << m_map.bad_pixels[i].column << "\n";
+  }
+
+  return sstr.str();
+}
+
+
+Error Box_sbpm::write(StreamWriter& writer) const
+{
+  size_t box_start = reserve_box_header_space(writer);
+
+  writer.write32(static_cast<uint32_t>(m_map.component_indices.size()));
+  for (uint32_t idx : m_map.component_indices) {
+    writer.write32(idx);
+  }
+
+  uint8_t flags = m_map.correction_applied ? 0x80 : 0;
+  writer.write8(flags);
+
+  writer.write32(static_cast<uint32_t>(m_map.bad_rows.size()));
+  writer.write32(static_cast<uint32_t>(m_map.bad_columns.size()));
+  writer.write32(static_cast<uint32_t>(m_map.bad_pixels.size()));
+
+  for (uint32_t row : m_map.bad_rows) {
+    writer.write32(row);
+  }
+
+  for (uint32_t col : m_map.bad_columns) {
+    writer.write32(col);
+  }
+
+  for (const auto& pixel : m_map.bad_pixels) {
+    writer.write32(pixel.row);
+    writer.write32(pixel.column);
+  }
+
+  prepend_header(writer, box_start);
+
+  return Error::Ok;
+}
diff --git a/libheif/codecs/uncompressed/unc_boxes.h b/libheif/codecs/uncompressed/unc_boxes.h
index e2f22962..5457ea3b 100644
--- a/libheif/codecs/uncompressed/unc_boxes.h
+++ b/libheif/codecs/uncompressed/unc_boxes.h
@@ -403,6 +403,33 @@ protected:
 };


+/**
+ * Sensor bad pixels map box (sbpm).
+ *
+ * Identifies bad pixels on a sensor for which at least one component
+ * value is corrupted. Supports bad rows, bad columns, and individual
+ * bad pixel coordinates.
+ *
+ * This is from ISO/IEC 23001-17 Section 6.1.7.
+ */
+class Box_sbpm : public FullBox
+{
+public:
+  Box_sbpm() { set_short_type(fourcc("sbpm")); }
+
+  const SensorBadPixelsMap& get_bad_pixels_map() const { return m_map; }
+  void set_bad_pixels_map(const SensorBadPixelsMap& map) { m_map = map; }
+
+  std::string dump(Indent&) const override;
+  Error write(StreamWriter& writer) const override;
+
+protected:
+  Error parse(BitstreamRange& range, const heif_security_limits* limits) override;
+
+  SensorBadPixelsMap m_map;
+};
+
+
 void fill_uncC_and_cmpd_from_profile(const std::shared_ptr<Box_uncC>& uncC,
                                      std::shared_ptr<Box_cmpd>& cmpd);

diff --git a/libheif/codecs/uncompressed/unc_codec.cc b/libheif/codecs/uncompressed/unc_codec.cc
index 787a501c..aaadafcf 100644
--- a/libheif/codecs/uncompressed/unc_codec.cc
+++ b/libheif/codecs/uncompressed/unc_codec.cc
@@ -448,6 +448,7 @@ void UncompressedImageCodec::unci_properties::fill_from_image_item(const std::sh
   icef = image->get_property<Box_icef>();
   cpat = image->get_property<Box_cpat>();
   splz = image->get_all_properties<Box_splz>();
+  sbpm = image->get_all_properties<Box_sbpm>();
 }


diff --git a/libheif/codecs/uncompressed/unc_codec.h b/libheif/codecs/uncompressed/unc_codec.h
index 8ad09922..83f2d4ef 100644
--- a/libheif/codecs/uncompressed/unc_codec.h
+++ b/libheif/codecs/uncompressed/unc_codec.h
@@ -65,6 +65,7 @@ public:
     std::shared_ptr<const Box_icef> icef;
     std::shared_ptr<const Box_cpat> cpat;
     std::vector<std::shared_ptr<const Box_splz>> splz;
+    std::vector<std::shared_ptr<const Box_sbpm>> sbpm;

     void fill_from_image_item(const std::shared_ptr<const ImageItem>&);
   };
diff --git a/libheif/codecs/uncompressed/unc_decoder.cc b/libheif/codecs/uncompressed/unc_decoder.cc
index b47779e0..86ac86f6 100644
--- a/libheif/codecs/uncompressed/unc_decoder.cc
+++ b/libheif/codecs/uncompressed/unc_decoder.cc
@@ -474,6 +474,10 @@ Result<std::shared_ptr<HeifPixelImage> > unc_decoder::decode_full_image(
     img->add_polarization_pattern(splz_box->get_pattern());
   }

+  for (const auto& sbpm_box : properties.sbpm) {
+    img->add_sensor_bad_pixels_map(sbpm_box->get_bad_pixels_map());
+  }
+
   auto decoderResult = unc_decoder_factory::get_unc_decoder(width, height, cmpd, uncC);
   if (!decoderResult) {
     return decoderResult.error();
diff --git a/libheif/codecs/uncompressed/unc_encoder.cc b/libheif/codecs/uncompressed/unc_encoder.cc
index 77dc871f..3d830a6f 100644
--- a/libheif/codecs/uncompressed/unc_encoder.cc
+++ b/libheif/codecs/uncompressed/unc_encoder.cc
@@ -168,6 +168,10 @@ Result<Encoder::CodedImageData> unc_encoder::encode_static(const std::shared_ptr
     codedImageData.properties.push_back(splz);
   }

+  for (const auto& sbpm : m_sbpm) {
+    codedImageData.properties.push_back(sbpm);
+  }
+

   // --- encode image

diff --git a/libheif/codecs/uncompressed/unc_encoder.h b/libheif/codecs/uncompressed/unc_encoder.h
index 1187ed72..12301423 100644
--- a/libheif/codecs/uncompressed/unc_encoder.h
+++ b/libheif/codecs/uncompressed/unc_encoder.h
@@ -33,6 +33,7 @@ class Box_uncC;
 class Box_cmpd;
 class Box_cpat;
 class Box_splz;
+class Box_sbpm;
 class HeifPixelImage;

 heif_uncompressed_component_type heif_channel_to_component_type(heif_channel channel);
@@ -51,6 +52,7 @@ public:
   std::shared_ptr<Box_uncC> get_uncC() const { return m_uncC; }
   std::shared_ptr<Box_cpat> get_cpat() const { return m_cpat; }
   std::vector<std::shared_ptr<Box_splz>> get_splz() const { return m_splz; }
+  std::vector<std::shared_ptr<Box_sbpm>> get_sbpm() const { return m_sbpm; }


   virtual uint64_t compute_tile_data_size_bytes(uint32_t tile_width, uint32_t tile_height) const = 0;
@@ -68,6 +70,7 @@ protected:
   std::shared_ptr<Box_uncC> m_uncC;
   std::shared_ptr<Box_cpat> m_cpat;
   std::vector<std::shared_ptr<Box_splz>> m_splz;
+  std::vector<std::shared_ptr<Box_sbpm>> m_sbpm;
 };


diff --git a/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc b/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
index 06f48117..f13c437a 100644
--- a/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
+++ b/libheif/codecs/uncompressed/unc_encoder_component_interleave.cc
@@ -151,6 +151,14 @@ unc_encoder_component_interleave::unc_encoder_component_interleave(const std::sh
       m_splz.push_back(splz);
     }
   }
+
+  if (image->has_sensor_bad_pixels_maps()) {
+    for (const auto& bpm : image->get_sensor_bad_pixels_maps()) {
+      auto sbpm = std::make_shared<Box_sbpm>();
+      sbpm->set_bad_pixels_map(bpm);
+      m_sbpm.push_back(sbpm);
+    }
+  }
 }


diff --git a/libheif/context.cc b/libheif/context.cc
index fdc7fe7b..bf9f38b4 100644
--- a/libheif/context.cc
+++ b/libheif/context.cc
@@ -152,6 +152,10 @@ static void copy_security_limits(heif_security_limits* dst, const heif_security_
     dst->max_sequence_frames = src->max_sequence_frames;
     dst->max_number_of_file_brands = src->max_number_of_file_brands;
   }
+
+  if (src->version >= 4) {
+    dst->max_bad_pixels = src->max_bad_pixels;
+  }
 }


diff --git a/libheif/pixelimage.h b/libheif/pixelimage.h
index 788248b1..afda1086 100644
--- a/libheif/pixelimage.h
+++ b/libheif/pixelimage.h
@@ -57,6 +57,16 @@ struct PolarizationPattern
                                             // 0xFFFFFFFF bit-pattern (NaN) = no polarization filter
 };

+struct SensorBadPixelsMap
+{
+  std::vector<uint32_t> component_indices;  // empty = applies to all components
+  bool correction_applied = false;
+  std::vector<uint32_t> bad_rows;
+  std::vector<uint32_t> bad_columns;
+  struct BadPixel { uint32_t row; uint32_t column; };
+  std::vector<BadPixel> bad_pixels;
+};
+
 heif_chroma chroma_from_subsampling(int h, int v);

 uint32_t chroma_width(uint32_t w, heif_chroma chroma);
@@ -219,6 +229,17 @@ public:
   virtual void add_polarization_pattern(const PolarizationPattern& p) { m_polarization_patterns.push_back(p); }


+  // --- sensor bad pixels map
+
+  bool has_sensor_bad_pixels_maps() const { return !m_sensor_bad_pixels_maps.empty(); }
+
+  const std::vector<SensorBadPixelsMap>& get_sensor_bad_pixels_maps() const { return m_sensor_bad_pixels_maps; }
+
+  virtual void set_sensor_bad_pixels_maps(const std::vector<SensorBadPixelsMap>& m) { m_sensor_bad_pixels_maps = m; }
+
+  virtual void add_sensor_bad_pixels_map(const SensorBadPixelsMap& m) { m_sensor_bad_pixels_maps.push_back(m); }
+
+
 #if HEIF_WITH_OMAF
   bool has_omaf_image_projection() const {
     return (m_omaf_image_projection != heif_omaf_image_projection_flat);
@@ -251,6 +272,8 @@ private:

   std::vector<PolarizationPattern> m_polarization_patterns;

+  std::vector<SensorBadPixelsMap> m_sensor_bad_pixels_maps;
+
 #if HEIF_WITH_OMAF
   heif_omaf_image_projection m_omaf_image_projection = heif_omaf_image_projection::heif_omaf_image_projection_flat;
 #endif
diff --git a/libheif/security_limits.cc b/libheif/security_limits.cc
index 11910c46..ed8241c6 100644
--- a/libheif/security_limits.cc
+++ b/libheif/security_limits.cc
@@ -25,7 +25,7 @@


 heif_security_limits global_security_limits{
-    .version = 3,
+    .version = 4,

     // --- version 1

@@ -54,12 +54,13 @@ heif_security_limits global_security_limits{
     // --- version 3

     .max_sequence_frames = 18'000'000,  // 100 hours at 50 fps
-    .max_number_of_file_brands = 1000
+    .max_number_of_file_brands = 1000,
+    .max_bad_pixels = 1000
 };


 heif_security_limits disabled_security_limits{
-    .version = 3
+    .version = 4
 };