Commit d9ff25fb for libheif
commit d9ff25fb34bfbcf5ed32a9c8117809a0f07c22a2
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Tue May 26 16:50:59 2026 +0200
only reject decoding images with errors (e.g., do not reject file completely when 'rref' check fails) (#1823)
diff --git a/libheif/api/libheif/heif_context.cc b/libheif/api/libheif/heif_context.cc
index 04cb516f..b25ab494 100644
--- a/libheif/api/libheif/heif_context.cc
+++ b/libheif/api/libheif/heif_context.cc
@@ -166,8 +166,7 @@ heif_error heif_context_get_primary_image_handle(heif_context* ctx, heif_image_h
return err.error_struct(ctx->context.get());
}
- if (auto errImage = std::dynamic_pointer_cast<ImageItem_Error>(primary_image)) {
- Error error = errImage->get_item_error();
+ if (Error error = primary_image->get_item_error()) {
return error.error_struct(ctx->context.get());
}
@@ -189,17 +188,16 @@ heif_error heif_context_get_image_handle(heif_context* ctx,
auto image = ctx->context->get_image(id, true);
- if (auto errImage = std::dynamic_pointer_cast<ImageItem_Error>(image)) {
- Error error = errImage->get_item_error();
- return error.error_struct(ctx->context.get());
- }
-
if (!image) {
*imgHdl = nullptr;
return {heif_error_Usage_error, heif_suberror_Nonexisting_item_referenced, ""};
}
+ if (Error error = image->get_item_error()) {
+ return error.error_struct(ctx->context.get());
+ }
+
*imgHdl = new heif_image_handle();
(*imgHdl)->image = std::move(image);
(*imgHdl)->context = ctx->context;
diff --git a/libheif/context.cc b/libheif/context.cc
index 037f84b6..8cd066cb 100644
--- a/libheif/context.cc
+++ b/libheif/context.cc
@@ -679,12 +679,15 @@ Error HeifContext::interpret_heif_file_images()
}
- // --- Are there any `rref` reference types that we do not process
+ // --- Are there any `rref` reference types that we do not process.
+ // This only makes the affected item undecodable; other items in the file
+ // can still be decoded, so we do not abort the whole load.
auto rrefBox = m_heif_file->get_property_for_item<Box_rref>(pair.first);
if (rrefBox) {
if (Error err = rrefBox->reference_types_supported_error()) {
- return err;
+ image->set_item_error(err);
+ continue;
}
}
diff --git a/libheif/image-items/image_item.cc b/libheif/image-items/image_item.cc
index e9cdb585..083b9dff 100644
--- a/libheif/image-items/image_item.cc
+++ b/libheif/image-items/image_item.cc
@@ -881,6 +881,10 @@ Result<std::shared_ptr<HeifPixelImage>> ImageItem::decode_image(const heif_decod
"'iref' has cyclic references"};
}
+ if (m_item_error) {
+ return m_item_error;
+ }
+
std::lock_guard<std::mutex> lock(m_decode_mutex);
// --- check whether image size (according to 'ispe') exceeds maximum
diff --git a/libheif/image-items/image_item.h b/libheif/image-items/image_item.h
index 4d8ff51e..550088b8 100644
--- a/libheif/image-items/image_item.h
+++ b/libheif/image-items/image_item.h
@@ -76,7 +76,12 @@ public:
bool is_property_essential(const std::shared_ptr<Box>& property) const;
- virtual Error get_item_error() const { return Error::Ok; }
+ virtual Error get_item_error() const { return m_item_error; }
+
+ // Mark this item as undecodable. The file still loads and other items remain
+ // usable, but decoding this item (or listing it as a non-error image) will
+ // surface this error.
+ void set_item_error(const Error& err) { m_item_error = err; }
virtual heif_compression_format get_compression_format() const { return heif_compression_undefined; }
@@ -446,6 +451,8 @@ private:
HeifContext* m_heif_context;
std::vector<std::shared_ptr<Box>> m_properties;
+ Error m_item_error; // if set, this item cannot be decoded (e.g. unsupported required reference types)
+
heif_item_id m_id = 0;
uint32_t m_width = 0, m_height = 0; // after all transformations have been applied
bool m_is_primary = false;