Commit db3b3e84 for libheif
commit db3b3e84c6fe09a0bbb566ff5196554a9d1e4b7e
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Tue Feb 24 15:21:06 2026 +0100
add unif brand support (globally unique IDs)
diff --git a/examples/heif_enc.cc b/examples/heif_enc.cc
index 3b000be7..533540d0 100644
--- a/examples/heif_enc.cc
+++ b/examples/heif_enc.cc
@@ -114,6 +114,7 @@ bool force_enc_jpeg2000 = false;
bool force_enc_htj2k = false;
bool use_tiling = false;
bool encode_sequence = false;
+bool option_unif = false;
bool use_video_handler = false;
std::string option_mime_item_type;
std::string option_mime_item_file;
@@ -200,6 +201,7 @@ const int OPTION_USE_HEVC_COMPRESSION = 1037;
const int OPTION_SET_OMAF_IMAGE_PROJECTION = 1038;
#endif
const int OPTION_ADD_COMPATIBLE_BRAND = 1039;
+const int OPTION_UNIF = 1040;
static option long_options[] = {
{(char* const) "help", no_argument, 0, 'h'},
@@ -272,6 +274,7 @@ static option long_options[] = {
{(char* const) "omaf-image-projection", required_argument, nullptr, OPTION_SET_OMAF_IMAGE_PROJECTION},
#endif
{(char* const) "add-compatible-brand", required_argument, nullptr, OPTION_ADD_COMPATIBLE_BRAND},
+ {(char* const) "unif", no_argument, nullptr, OPTION_UNIF},
{0, 0, 0, 0}
};
@@ -329,6 +332,7 @@ void show_help(const char* argv0)
<< " --mime-item-file FILE use the specified FILE as the data to put into the mime item (experimental)\n"
#endif
<< " --add-compatible-brand BRAND add a compatible brand to the output file (4 characters)\n"
+ << " --unif use unified ID namespace (adds 'unif' compatible brand)\n"
<< "\n"
<< "codecs:\n"
<< " -A, --avif encode as AVIF (not needed if output filename with .avif suffix is provided)\n"
@@ -1641,6 +1645,9 @@ int main(int argc, char** argv)
}
additional_compatible_brands.push_back(heif_fourcc_to_brand(optarg));
break;
+ case OPTION_UNIF:
+ option_unif = true;
+ break;
}
}
@@ -1744,6 +1751,10 @@ int main(int argc, char** argv)
return 1;
}
+ if (option_unif) {
+ heif_context_set_unif(context.get(), 1);
+ }
+
#define MAX_ENCODERS 10
const heif_encoder_descriptor* encoder_descriptors[MAX_ENCODERS];
diff --git a/libheif/CMakeLists.txt b/libheif/CMakeLists.txt
index 2d65a5b0..4d00325a 100644
--- a/libheif/CMakeLists.txt
+++ b/libheif/CMakeLists.txt
@@ -63,6 +63,8 @@ set(libheif_sources
region.h
brands.cc
brands.h
+ id_creator.cc
+ id_creator.h
text.cc
text.h
api_structs.h
diff --git a/libheif/api/libheif/heif_brands.h b/libheif/api/libheif/heif_brands.h
index 81263d35..68cd89f9 100644
--- a/libheif/api/libheif/heif_brands.h
+++ b/libheif/api/libheif/heif_brands.h
@@ -250,6 +250,15 @@ typedef uint32_t heif_brand2;
#define heif_brand2_avci heif_fourcc('a','v','c','i')
#define heif_brand2_avcs heif_fourcc('a','v','c','s')
+/**
+ * Unified ID namespace (`unif`) brand.
+ *
+ * All IDs (item, track, entity group) share a single global namespace.
+ *
+ * See ISO/IEC 14496-12.
+ */
+#define heif_brand2_unif heif_fourcc('u','n','i','f')
+
#define heif_brand2_iso8 heif_fourcc('i','s','o','8')
#define heif_brand2_isom heif_fourcc('i','s','o','m')
#define heif_brand2_mp41 heif_fourcc('m','p','4','1')
diff --git a/libheif/api/libheif/heif_encoding.cc b/libheif/api/libheif/heif_encoding.cc
index 3a0c13bb..609406ef 100644
--- a/libheif/api/libheif/heif_encoding.cc
+++ b/libheif/api/libheif/heif_encoding.cc
@@ -775,6 +775,12 @@ void heif_context_add_compatible_brand(heif_context* ctx,
}
+void heif_context_set_unif(heif_context* ctx, int flag)
+{
+ ctx->context->set_unif(flag != 0);
+}
+
+
// === DEPRECATED ===
// DEPRECATED: typo in function name
diff --git a/libheif/api/libheif/heif_encoding.h b/libheif/api/libheif/heif_encoding.h
index 2261340d..5c91c416 100644
--- a/libheif/api/libheif/heif_encoding.h
+++ b/libheif/api/libheif/heif_encoding.h
@@ -364,6 +364,19 @@ LIBHEIF_API
void heif_context_add_compatible_brand(heif_context* ctx,
heif_brand2 compatible_brand);
+/**
+ * Enable the unified ID namespace ('unif' brand).
+ *
+ * When enabled, item IDs, track IDs, and entity group IDs share a single
+ * global counter so no ID value is reused across categories. The 'unif'
+ * compatible brand is automatically added to the output file.
+ *
+ * @param ctx the encoding context
+ * @param flag non-zero to enable, zero to disable
+ */
+LIBHEIF_API
+void heif_context_set_unif(heif_context* ctx, int flag);
+
// --- deprecated functions ---
// DEPRECATED, typo in function name
diff --git a/libheif/api/libheif/heif_regions.cc b/libheif/api/libheif/heif_regions.cc
index 625c00af..b54b6952 100644
--- a/libheif/api/libheif/heif_regions.cc
+++ b/libheif/api/libheif/heif_regions.cc
@@ -512,7 +512,11 @@ heif_error heif_image_handle_add_region_item(heif_image_handle* image_handle,
uint32_t reference_width, uint32_t reference_height,
heif_region_item** out_region_item)
{
- std::shared_ptr<RegionItem> regionItem = image_handle->context->add_region_item(reference_width, reference_height);
+ auto regionItemResult = image_handle->context->add_region_item(reference_width, reference_height);
+ if (!regionItemResult) {
+ return regionItemResult.error_struct(image_handle->context.get());
+ }
+ std::shared_ptr<RegionItem> regionItem = *regionItemResult;
image_handle->image->add_region_item_id(regionItem->item_id);
if (out_region_item) {
diff --git a/libheif/api/libheif/heif_text.cc b/libheif/api/libheif/heif_text.cc
index f4f3e204..4b0d6c30 100644
--- a/libheif/api/libheif/heif_text.cc
+++ b/libheif/api/libheif/heif_text.cc
@@ -36,7 +36,11 @@ heif_error heif_image_handle_add_text_item(heif_image_handle *image_handle,
heif_text_item** out_text_item)
{
- std::shared_ptr<TextItem> textItem = image_handle->context->add_text_item(content_type, text);
+ auto textItemResult = image_handle->context->add_text_item(content_type, text);
+ if (!textItemResult) {
+ return textItemResult.error_struct(image_handle->context.get());
+ }
+ std::shared_ptr<TextItem> textItem = *textItemResult;
image_handle->image->add_text_item_id(textItem->get_item_id());
if (out_text_item) {
heif_text_item* item = new heif_text_item();
diff --git a/libheif/brands.cc b/libheif/brands.cc
index ab8acb67..9aeb039c 100644
--- a/libheif/brands.cc
+++ b/libheif/brands.cc
@@ -165,6 +165,12 @@ std::vector<heif_brand2> compute_compatible_brands(const HeifContext* ctx, heif_
}
}
+ // --- "unif" brand
+
+ if (ctx->get_unif()) {
+ compatible_brands.push_back(heif_brand2_unif);
+ }
+
return compatible_brands;
}
diff --git a/libheif/context.cc b/libheif/context.cc
index 3bc91f8c..e12c43be 100644
--- a/libheif/context.cc
+++ b/libheif/context.cc
@@ -167,6 +167,24 @@ void HeifContext::set_security_limits(const heif_security_limits* limits)
}
+void HeifContext::set_unif(bool flag)
+{
+ m_heif_file->get_id_creator().set_unif(flag);
+}
+
+
+bool HeifContext::get_unif() const
+{
+ return m_heif_file->get_id_creator().get_unif();
+}
+
+
+IDCreator& HeifContext::get_id_creator()
+{
+ return m_heif_file->get_id_creator();
+}
+
+
Error HeifContext::read(const std::shared_ptr<StreamReader>& reader)
{
m_heif_file = std::make_shared<HeifFile>();
@@ -273,9 +291,13 @@ bool HeifContext::is_image(heif_item_id ID) const
}
-std::shared_ptr<RegionItem> HeifContext::add_region_item(uint32_t reference_width, uint32_t reference_height)
+Result<std::shared_ptr<RegionItem>> HeifContext::add_region_item(uint32_t reference_width, uint32_t reference_height)
{
- std::shared_ptr<Box_infe> box = m_heif_file->add_new_infe_box(fourcc("rgan"));
+ auto boxResult = m_heif_file->add_new_infe_box(fourcc("rgan"));
+ if (!boxResult) {
+ return boxResult.error();
+ }
+ auto box = *boxResult;
box->set_hidden_item(true);
auto regionItem = std::make_shared<RegionItem>(box->get_item_ID(), reference_width, reference_height);
@@ -1702,7 +1724,11 @@ Error HeifContext::add_generic_metadata(const std::shared_ptr<ImageItem>& master
{
// create an infe box describing what kind of data we are storing (this also creates a new ID)
- auto metadata_infe_box = m_heif_file->add_new_infe_box(item_type);
+ auto infe_result = m_heif_file->add_new_infe_box(item_type);
+ if (!infe_result) {
+ return infe_result.error();
+ }
+ auto metadata_infe_box = *infe_result;
metadata_infe_box->set_hidden_item(true);
if (content_type != nullptr) {
metadata_infe_box->set_content_type(content_type);
@@ -1856,7 +1882,11 @@ Result<heif_item_id> HeifContext::add_pyramid_group(const std::vector<heif_item_
ids.push_back(layer_item->get_id());
}
- heif_item_id group_id = m_heif_file->get_unused_item_id();
+ auto groupIdResult = m_heif_file->get_id_creator().get_new_id(IDCreator::Namespace::entity_group);
+ if (!groupIdResult) {
+ return groupIdResult.error();
+ }
+ heif_item_id group_id = *groupIdResult;
pymd->set_group_id(group_id);
pymd->set_layers((uint16_t)tile_w, (uint16_t)tile_h, layers, ids);
@@ -2070,9 +2100,13 @@ Result<std::shared_ptr<class Track_Metadata>> HeifContext::add_uri_metadata_sequ
return trak;
}
-std::shared_ptr<TextItem> HeifContext::add_text_item(const char* content_type, const char* text)
+Result<std::shared_ptr<TextItem>> HeifContext::add_text_item(const char* content_type, const char* text)
{
- std::shared_ptr<Box_infe> box = m_heif_file->add_new_infe_box(fourcc("mime"));
+ auto boxResult = m_heif_file->add_new_infe_box(fourcc("mime"));
+ if (!boxResult) {
+ return boxResult.error();
+ }
+ auto box = *boxResult;
box->set_hidden_item(true);
box->set_content_type(std::string(content_type));
auto textItem = std::make_shared<TextItem>(box->get_item_ID(), text);
diff --git a/libheif/context.h b/libheif/context.h
index 45554459..de1bb859 100644
--- a/libheif/context.h
+++ b/libheif/context.h
@@ -88,6 +88,12 @@ public:
std::shared_ptr<HeifFile> get_heif_file() const { return m_heif_file; }
+ void set_unif(bool flag);
+
+ bool get_unif() const;
+
+ IDCreator& get_id_creator();
+
// === image items ===
std::vector<std::shared_ptr<ImageItem>> get_top_level_images(bool return_error_images);
@@ -176,7 +182,7 @@ public:
m_region_items.push_back(std::move(region_item));
}
- std::shared_ptr<RegionItem> add_region_item(uint32_t reference_width, uint32_t reference_height);
+ Result<std::shared_ptr<RegionItem>> add_region_item(uint32_t reference_width, uint32_t reference_height);
std::shared_ptr<RegionItem> get_region_item(heif_item_id id) const
{
@@ -222,7 +228,7 @@ public:
m_text_items.push_back(std::move(text_item));
}
- std::shared_ptr<TextItem> add_text_item(const char* content_type, const char* text);
+ Result<std::shared_ptr<TextItem>> add_text_item(const char* content_type, const char* text);
std::shared_ptr<TextItem> get_text_item(heif_item_id id) const
{
diff --git a/libheif/file.cc b/libheif/file.cc
index 32aa902e..a652ae6a 100644
--- a/libheif/file.cc
+++ b/libheif/file.cc
@@ -852,35 +852,31 @@ Result<std::vector<uint8_t>> HeifFile::get_item_data(heif_item_id ID, heif_metad
}
-// TODO: we should use a acquire() / release() approach here so that we can get multiple IDs before actually creating infe boxes
-heif_item_id HeifFile::get_unused_item_id() const
+Result<heif_item_id> HeifFile::get_unused_item_id()
{
- heif_item_id max_id = 0;
-
- // TODO: replace with better algorithm and data-structure
-
- for (const auto& infe : m_infe_boxes) {
- max_id = std::max(max_id, infe.second->get_item_ID());
- }
-
- assert(max_id != 0xFFFFFFFF);
-
- return max_id + 1;
+ return m_id_creator.get_new_id(IDCreator::Namespace::item);
}
-heif_item_id HeifFile::add_new_image(uint32_t item_type)
+Result<heif_item_id> HeifFile::add_new_image(uint32_t item_type)
{
- auto box = add_new_infe_box(item_type);
- return box->get_item_ID();
+ auto result = add_new_infe_box(item_type);
+ if (!result) {
+ return result.error();
+ }
+ return (*result)->get_item_ID();
}
-std::shared_ptr<Box_infe> HeifFile::add_new_infe_box(uint32_t item_type)
+Result<std::shared_ptr<Box_infe>> HeifFile::add_new_infe_box(uint32_t item_type)
{
init_for_image();
- heif_item_id id = get_unused_item_id();
+ auto idResult = get_unused_item_id();
+ if (!idResult) {
+ return idResult.error();
+ }
+ heif_item_id id = *idResult;
auto infe = std::make_shared<Box_infe>();
infe->set_item_ID(id);
@@ -992,7 +988,11 @@ Result<heif_item_id> HeifFile::add_infe(uint32_t item_type, const uint8_t* data,
{
// create an infe box describing what kind of data we are storing (this also creates a new ID)
- auto infe_box = add_new_infe_box(item_type);
+ auto infe_result = add_new_infe_box(item_type);
+ if (!infe_result) {
+ return infe_result.error();
+ }
+ auto infe_box = *infe_result;
infe_box->set_hidden_item(true);
heif_item_id metadata_id = infe_box->get_item_ID();
@@ -1013,7 +1013,11 @@ Result<heif_item_id> HeifFile::add_infe_mime(const char* content_type, heif_meta
{
// create an infe box describing what kind of data we are storing (this also creates a new ID)
- auto infe_box = add_new_infe_box(fourcc("mime"));
+ auto infe_result = add_new_infe_box(fourcc("mime"));
+ if (!infe_result) {
+ return infe_result.error();
+ }
+ auto infe_box = *infe_result;
infe_box->set_hidden_item(true);
infe_box->set_content_type(content_type);
@@ -1029,7 +1033,11 @@ Result<heif_item_id> HeifFile::add_precompressed_infe_mime(const char* content_t
{
// create an infe box describing what kind of data we are storing (this also creates a new ID)
- auto infe_box = add_new_infe_box(fourcc("mime"));
+ auto infe_result = add_new_infe_box(fourcc("mime"));
+ if (!infe_result) {
+ return infe_result.error();
+ }
+ auto infe_box = *infe_result;
infe_box->set_hidden_item(true);
infe_box->set_content_type(content_type);
@@ -1045,7 +1053,11 @@ Result<heif_item_id> HeifFile::add_infe_uri(const char* item_uri_type, const uin
{
// create an infe box describing what kind of data we are storing (this also creates a new ID)
- auto infe_box = add_new_infe_box(fourcc("uri "));
+ auto infe_result = add_new_infe_box(fourcc("uri "));
+ if (!infe_result) {
+ return infe_result.error();
+ }
+ auto infe_box = *infe_result;
infe_box->set_hidden_item(true);
infe_box->set_item_uri_type(item_uri_type);
diff --git a/libheif/file.h b/libheif/file.h
index df025717..c9360ec9 100644
--- a/libheif/file.h
+++ b/libheif/file.h
@@ -22,6 +22,7 @@
#define LIBHEIF_FILE_H
#include "box.h"
+#include "id_creator.h"
#include "nclx.h"
#include "image-items/avif.h"
#include "image-items/hevc.h"
@@ -183,11 +184,15 @@ public:
// --- writing ---
- heif_item_id get_unused_item_id() const;
+ IDCreator& get_id_creator() { return m_id_creator; }
- heif_item_id add_new_image(uint32_t item_type);
+ const IDCreator& get_id_creator() const { return m_id_creator; }
- std::shared_ptr<Box_infe> add_new_infe_box(uint32_t item_type);
+ Result<heif_item_id> get_unused_item_id();
+
+ Result<heif_item_id> add_new_image(uint32_t item_type);
+
+ Result<std::shared_ptr<Box_infe>> add_new_infe_box(uint32_t item_type);
void add_ispe_property(heif_item_id id, uint32_t width, uint32_t height, bool essential);
@@ -285,6 +290,7 @@ private:
std::shared_ptr<Box_mvhd> m_mvhd_box;
const heif_security_limits* m_limits = nullptr;
+ IDCreator m_id_creator;
Error parse_heif_file();
diff --git a/libheif/id_creator.cc b/libheif/id_creator.cc
new file mode 100644
index 00000000..dc71d4d7
--- /dev/null
+++ b/libheif/id_creator.cc
@@ -0,0 +1,54 @@
+/*
+ * HEIF codec.
+ * Copyright (c) 2026 Dirk Farin <dirk.farin@gmail.com>
+ *
+ * This file is part of libheif.
+ *
+ * libheif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * libheif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libheif. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "id_creator.h"
+
+Result<uint32_t> IDCreator::get_new_id(Namespace ns)
+{
+ if (m_unif) {
+ if (m_next_id_global == 0) {
+ return Error(heif_error_Usage_error,
+ heif_suberror_Unspecified,
+ "ID namespace overflow");
+ }
+ return m_next_id_global++;
+ }
+
+ uint32_t* counter;
+ switch (ns) {
+ case Namespace::item:
+ counter = &m_next_id_item;
+ break;
+ case Namespace::track:
+ counter = &m_next_id_track;
+ break;
+ case Namespace::entity_group:
+ counter = &m_next_id_entity_group;
+ break;
+ }
+
+ if (*counter == 0) {
+ return Error(heif_error_Usage_error,
+ heif_suberror_Unspecified,
+ "ID namespace overflow");
+ }
+
+ return (*counter)++;
+}
diff --git a/libheif/id_creator.h b/libheif/id_creator.h
new file mode 100644
index 00000000..fff8c97e
--- /dev/null
+++ b/libheif/id_creator.h
@@ -0,0 +1,50 @@
+/*
+ * HEIF codec.
+ * Copyright (c) 2026 Dirk Farin <dirk.farin@gmail.com>
+ *
+ * This file is part of libheif.
+ *
+ * libheif is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * libheif is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libheif. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIBHEIF_ID_CREATOR_H
+#define LIBHEIF_ID_CREATOR_H
+
+#include "error.h"
+#include <cstdint>
+
+class IDCreator
+{
+public:
+ enum class Namespace { item, track, entity_group };
+
+ void set_unif(bool flag) { m_unif = flag; }
+
+ bool get_unif() const { return m_unif; }
+
+ // Returns a new unique ID for the given namespace.
+ // In non-unif mode: separate counters per namespace.
+ // In unif mode: single global counter shared across all namespaces.
+ // Returns error on overflow (counter would exceed 0xFFFFFFFF).
+ Result<uint32_t> get_new_id(Namespace ns);
+
+private:
+ bool m_unif = false;
+ uint32_t m_next_id_item = 1;
+ uint32_t m_next_id_track = 1;
+ uint32_t m_next_id_entity_group = 1;
+ uint32_t m_next_id_global = 1; // used in unif mode
+};
+
+#endif
diff --git a/libheif/image-items/grid.cc b/libheif/image-items/grid.cc
index 3eb94cb4..cfd6d83a 100644
--- a/libheif/image-items/grid.cc
+++ b/libheif/image-items/grid.cc
@@ -711,7 +711,11 @@ Result<std::shared_ptr<ImageItem_Grid>> ImageItem_Grid::add_new_grid_item(HeifCo
// Create Grid Item
std::shared_ptr<HeifFile> file = ctx->get_heif_file();
- heif_item_id grid_id = file->add_new_image(fourcc("grid"));
+ auto grid_id_result = file->add_new_image(fourcc("grid"));
+ if (!grid_id_result) {
+ return grid_id_result.error();
+ }
+ heif_item_id grid_id = *grid_id_result;
grid_image = std::make_shared<ImageItem_Grid>(ctx, grid_id);
grid_image->set_encoding_options(encoding_options);
grid_image->set_grid_spec(grid);
@@ -842,7 +846,11 @@ Result<std::shared_ptr<ImageItem_Grid>> ImageItem_Grid::add_and_encode_full_grid
// Create Grid Item
- heif_item_id grid_id = file->add_new_image(fourcc("grid"));
+ auto grid_id_result = file->add_new_image(fourcc("grid"));
+ if (!grid_id_result) {
+ return grid_id_result.error();
+ }
+ heif_item_id grid_id = *grid_id_result;
griditem = std::make_shared<ImageItem_Grid>(ctx, grid_id);
ctx->insert_image_item(grid_id, griditem);
const int construction_method = 1; // 0=mdat 1=idat
diff --git a/libheif/image-items/image_item.cc b/libheif/image-items/image_item.cc
index bb22a2a8..232b6c20 100644
--- a/libheif/image-items/image_item.cc
+++ b/libheif/image-items/image_item.cc
@@ -387,7 +387,11 @@ Error ImageItem::encode_to_item(HeifContext* ctx,
Encoder::CodedImageData& codedImage = *codingResult;
- auto infe_box = ctx->get_heif_file()->add_new_infe_box(get_infe_type());
+ auto infe_result = ctx->get_heif_file()->add_new_infe_box(get_infe_type());
+ if (!infe_result) {
+ return infe_result.error();
+ }
+ auto infe_box = *infe_result;
heif_item_id image_id = infe_box->get_item_ID();
set_id(image_id);
diff --git a/libheif/image-items/overlay.cc b/libheif/image-items/overlay.cc
index 168eb0a8..c45a0ceb 100644
--- a/libheif/image-items/overlay.cc
+++ b/libheif/image-items/overlay.cc
@@ -445,7 +445,11 @@ Result<std::shared_ptr<ImageItem_Overlay>> ImageItem_Overlay::add_new_overlay_it
// Create IOVL Item
- heif_item_id iovl_id = file->add_new_image(fourcc("iovl"));
+ auto iovl_id_result = file->add_new_image(fourcc("iovl"));
+ if (!iovl_id_result) {
+ return iovl_id_result.error();
+ }
+ heif_item_id iovl_id = *iovl_id_result;
std::shared_ptr<ImageItem_Overlay> iovl_image = std::make_shared<ImageItem_Overlay>(ctx, iovl_id);
ctx->insert_image_item(iovl_id, iovl_image);
const int construction_method = 1; // 0=mdat 1=idat
diff --git a/libheif/image-items/tiled.cc b/libheif/image-items/tiled.cc
index dce157cc..25feaaf2 100644
--- a/libheif/image-items/tiled.cc
+++ b/libheif/image-items/tiled.cc
@@ -605,7 +605,11 @@ ImageItem_Tiled::add_new_tiled_item(HeifContext* ctx, const heif_tiled_image_par
auto file = ctx->get_heif_file();
- heif_item_id tild_id = ctx->get_heif_file()->add_new_image(fourcc("tili"));
+ auto tild_id_result = ctx->get_heif_file()->add_new_image(fourcc("tili"));
+ if (!tild_id_result) {
+ return tild_id_result.error();
+ }
+ heif_item_id tild_id = *tild_id_result;
auto tild_image = std::make_shared<ImageItem_Tiled>(ctx, tild_id);
tild_image->set_resolution(parameters->image_width, parameters->image_height);
ctx->insert_image_item(tild_id, tild_image);
diff --git a/libheif/image-items/unc_image.cc b/libheif/image-items/unc_image.cc
index 5151e00b..e482e6b1 100644
--- a/libheif/image-items/unc_image.cc
+++ b/libheif/image-items/unc_image.cc
@@ -128,7 +128,11 @@ Result<std::shared_ptr<ImageItem_uncompressed>> ImageItem_uncompressed::add_unci
auto file = ctx->get_heif_file();
- heif_item_id unci_id = ctx->get_heif_file()->add_new_image(fourcc("unci"));
+ auto unci_id_result = ctx->get_heif_file()->add_new_image(fourcc("unci"));
+ if (!unci_id_result) {
+ return unci_id_result.error();
+ }
+ heif_item_id unci_id = *unci_id_result;
auto unci_image = std::make_shared<ImageItem_uncompressed>(ctx, unci_id);
unci_image->set_resolution(parameters->image_width, parameters->image_height);
unci_image->m_unc_encoder = std::move(*uncEncoder);
diff --git a/libheif/sequences/track.cc b/libheif/sequences/track.cc
index acb916fa..fdd8f2aa 100644
--- a/libheif/sequences/track.cc
+++ b/libheif/sequences/track.cc
@@ -524,15 +524,10 @@ Track::Track(HeifContext* ctx, uint32_t track_id, const TrackOptions* options, u
// --- find next free track ID
if (track_id == 0) {
- track_id = 1; // minimum track ID
-
- for (const auto& track : m_moov->get_child_boxes<Box_trak>()) {
- auto tkhd = track->get_child_box<Box_tkhd>();
-
- if (tkhd->get_track_id() >= track_id) {
- track_id = tkhd->get_track_id() + 1;
- }
- }
+ auto idResult = ctx->get_id_creator().get_new_id(IDCreator::Namespace::track);
+ // Track constructor cannot return errors; assert on overflow (extremely unlikely).
+ assert(idResult);
+ track_id = *idResult;
auto mvhd = m_moov->get_child_box<Box_mvhd>();
mvhd->set_next_track_id(track_id + 1);