diff --git a/libheif/api/libheif/heif.cc b/libheif/api/libheif/heif.cc index e7f77561a1..5a571a323e 100644 --- a/libheif/api/libheif/heif.cc +++ b/libheif/api/libheif/heif.cc @@ -583,7 +583,7 @@ heif_error heif_context_get_primary_image_handle(heif_context* ctx, heif_image_h return err.error_struct(ctx->context.get()); } - std::shared_ptr primary_image = ctx->context->get_primary_image(); + std::shared_ptr primary_image = ctx->context->get_primary_image(true); // It is a requirement of an HEIF file there is always a primary image. // If there is none, an error is generated when loading the file. @@ -613,7 +613,7 @@ struct heif_error heif_context_get_primary_image_ID(struct heif_context* ctx, he heif_suberror_Null_pointer_argument).error_struct(ctx->context.get()); } - std::shared_ptr primary = ctx->context->get_primary_image(); + std::shared_ptr primary = ctx->context->get_primary_image(true); if (!primary) { return Error(heif_error_Invalid_input, heif_suberror_No_or_invalid_primary_item).error_struct(ctx->context.get()); @@ -627,7 +627,7 @@ struct heif_error heif_context_get_primary_image_ID(struct heif_context* ctx, he int heif_context_is_top_level_image_ID(struct heif_context* ctx, heif_item_id id) { - const std::vector> images = ctx->context->get_top_level_images(); + const std::vector> images = ctx->context->get_top_level_images(true); for (const auto& img : images) { if (img->get_id() == id) { @@ -641,7 +641,7 @@ int heif_context_is_top_level_image_ID(struct heif_context* ctx, heif_item_id id int heif_context_get_number_of_top_level_images(heif_context* ctx) { - return (int) ctx->context->get_top_level_images().size(); + return (int) ctx->context->get_top_level_images(true).size(); } @@ -656,7 +656,7 @@ int heif_context_get_list_of_top_level_image_IDs(struct heif_context* ctx, // fill in ID values into output array - const std::vector> imgs = ctx->context->get_top_level_images(); + const std::vector> imgs = ctx->context->get_top_level_images(true); int n = (int) std::min(count, (int) imgs.size()); for (int i = 0; i < n; i++) { ID_array[i] = imgs[i]->get_id(); @@ -674,7 +674,7 @@ struct heif_error heif_context_get_image_handle(struct heif_context* ctx, return {heif_error_Usage_error, heif_suberror_Null_pointer_argument, ""}; } - auto image = ctx->context->get_image(id); + auto image = ctx->context->get_image(id, true); if (auto errImage = std::dynamic_pointer_cast(image)) { Error error = errImage->get_item_error(); diff --git a/libheif/context.cc b/libheif/context.cc index 55c60aa010..566d05f2b9 100644 --- a/libheif/context.cc +++ b/libheif/context.cc @@ -212,6 +212,56 @@ Error HeifContext::check_resolution(uint32_t width, uint32_t height) const { } +std::vector> HeifContext::get_top_level_images(bool return_error_images) +{ + if (return_error_images) { + return m_top_level_images; + } + else { + std::vector> filtered; + for (auto& item : m_top_level_images) { + if (!item->get_item_error()) { + filtered.push_back(item); + } + } + + return filtered; + } +} + + +std::shared_ptr HeifContext::get_image(heif_item_id id, bool return_error_images) +{ + auto iter = m_all_images.find(id); + if (iter == m_all_images.end()) { + return nullptr; + } + else { + if (iter->second->get_item_error() && !return_error_images) { + return nullptr; + } + else { + return iter->second; + } + } +} + + +std::shared_ptr HeifContext::get_primary_image(bool return_error_image) +{ + if (!return_error_image && m_primary_image->get_item_error()) + return nullptr; + else + return m_primary_image; +} + + +bool HeifContext::is_image(heif_item_id ID) const +{ + return m_all_images.find(ID) != m_all_images.end(); +} + + std::shared_ptr HeifContext::add_region_item(uint32_t reference_width, uint32_t reference_height) { std::shared_ptr box = m_heif_file->add_new_infe_box(fourcc("rgan")); @@ -346,7 +396,7 @@ Error HeifContext::interpret_heif_file() for (auto& pair : m_all_images) { auto& image = pair.second; - if (image->is_error_item()) { + if (image->get_item_error()) { continue; } @@ -657,7 +707,7 @@ Error HeifContext::interpret_heif_file() for (auto& pair : m_all_images) { auto& image = pair.second; - if (image->is_error_item()) { + if (image->get_item_error()) { continue; } @@ -693,7 +743,7 @@ Error HeifContext::interpret_heif_file() auto& image = pair.second; auto id = pair.first; - if (image->is_error_item()) { + if (image->get_item_error()) { continue; } @@ -1376,11 +1426,12 @@ Error HeifContext::add_tiled_image_tile(heif_item_id tild_id, uint32_t tile_x, u const int construction_method = 0; // 0=mdat 1=idat m_heif_file->append_iloc_data(tild_id, encodeResult.value.bitstream, construction_method); - auto imgItem = get_image(tild_id); + auto imgItem = get_image(tild_id, true); auto tildImg = std::dynamic_pointer_cast(imgItem); if (!tildImg) { return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "item ID for add_tiled_image_tile() is no 'tili' image."}; } + assert(!tildImg->get_item_error()); auto& header = tildImg->get_tild_header(); diff --git a/libheif/context.h b/libheif/context.h index 025e4de8d7..373f8e27cb 100644 --- a/libheif/context.h +++ b/libheif/context.h @@ -94,29 +94,20 @@ class HeifContext : public ErrorBuffer std::shared_ptr get_heif_file() const { return m_heif_file; } - std::vector> get_top_level_images() { return m_top_level_images; } + std::vector> get_top_level_images(bool return_error_images); void insert_new_image(heif_item_id id, std::shared_ptr img) { m_all_images.insert(std::make_pair(id, img)); } - std::shared_ptr get_image(heif_item_id id) - { - auto iter = m_all_images.find(id); - if (iter == m_all_images.end()) { - return nullptr; - } - else { - return iter->second; - } - } + std::shared_ptr get_image(heif_item_id id, bool return_error_images); - std::shared_ptr get_image(heif_item_id id) const + std::shared_ptr get_image(heif_item_id id, bool return_error_images) const { - return const_cast(this)->get_image(id); + return const_cast(this)->get_image(id, return_error_images); } - std::shared_ptr get_primary_image() { return m_primary_image; } + std::shared_ptr get_primary_image(bool return_error_image); bool is_image(heif_item_id ID) const; diff --git a/libheif/image-items/grid.cc b/libheif/image-items/grid.cc index 7b25f09e78..acf2da037d 100644 --- a/libheif/image-items/grid.cc +++ b/libheif/image-items/grid.cc @@ -279,12 +279,15 @@ Result> ImageItem_Grid::decode_full_grid_image(c heif_item_id tileID = image_references[reference_idx]; - std::shared_ptr tileImg = get_context()->get_image(tileID); + std::shared_ptr tileImg = get_context()->get_image(tileID, true); if (!tileImg) { return Error{heif_error_Invalid_input, heif_suberror_Missing_grid_images, "Nonexistent grid image referenced"}; } + if (auto error = tileImg->get_item_error()) { + return error; + } uint32_t src_width = tileImg->get_width(); uint32_t src_height = tileImg->get_height(); @@ -384,8 +387,11 @@ Error ImageItem_Grid::decode_and_paste_tile_image(heif_item_id tileID, uint32_t { std::shared_ptr tile_img; - auto tileItem = get_context()->get_image(tileID); + auto tileItem = get_context()->get_image(tileID, true); assert(tileItem); + if (auto error = tileItem->get_item_error()) { + return error; + } auto decodeResult = tileItem->decode_image(options, false, 0, 0); if (decodeResult.error) { @@ -443,7 +449,10 @@ Result> ImageItem_Grid::decode_grid_tile(const h assert(idx < m_grid_tile_ids.size()); heif_item_id tile_id = m_grid_tile_ids[idx]; - std::shared_ptr tile_item = get_context()->get_image(tile_id); + std::shared_ptr tile_item = get_context()->get_image(tile_id, true); + if (auto error = tile_item->get_item_error()) { + return error; + } return tile_item->decode_compressed_image(options, true, tx, ty); } @@ -457,15 +466,19 @@ heif_image_tiling ImageItem_Grid::get_heif_image_tiling() const tiling.num_columns = gridspec.get_columns(); tiling.num_rows = gridspec.get_rows(); - heif_item_id tile0_id = get_grid_tiles()[0]; - auto tile0 = get_context()->get_image(tile0_id); - tiling.tile_width = tile0->get_width(); - tiling.tile_height = tile0->get_height(); - tiling.image_width = gridspec.get_width(); tiling.image_height = gridspec.get_height(); tiling.number_of_extra_dimensions = 0; + heif_item_id tile0_id = get_grid_tiles()[0]; + auto tile0 = get_context()->get_image(tile0_id, true); + if (tile0->get_item_error()) { + return tiling; + } + + tiling.tile_width = tile0->get_width(); + tiling.tile_height = tile0->get_height(); + return tiling; } @@ -473,7 +486,10 @@ heif_image_tiling ImageItem_Grid::get_heif_image_tiling() const void ImageItem_Grid::get_tile_size(uint32_t& w, uint32_t& h) const { heif_item_id first_tile_id = get_grid_tiles()[0]; - auto tile = get_context()->get_image(first_tile_id); + auto tile = get_context()->get_image(first_tile_id, true); + if (tile->get_item_error()) { + w = h = 0; + } w = tile->get_width(); h = tile->get_height(); @@ -489,7 +505,7 @@ int ImageItem_Grid::get_luma_bits_per_pixel() const return -1; } - auto image = get_context()->get_image(child); + auto image = get_context()->get_image(child, true); if (!image) { return -1; } @@ -506,7 +522,7 @@ int ImageItem_Grid::get_chroma_bits_per_pixel() const return -1; } - auto image = get_context()->get_image(child); + auto image = get_context()->get_image(child, true); return image->get_chroma_bits_per_pixel(); } @@ -518,6 +534,10 @@ std::shared_ptr ImageItem_Grid::get_decoder() const return nullptr; } - auto image = get_context()->get_image(child); + auto image = get_context()->get_image(child, true); + if (image->get_item_error()) { + return nullptr; + } + return image->get_decoder(); } diff --git a/libheif/image-items/iden.cc b/libheif/image-items/iden.cc index f177a7e11d..41be785ad9 100644 --- a/libheif/image-items/iden.cc +++ b/libheif/image-items/iden.cc @@ -67,12 +67,15 @@ Result> ImageItem_iden::decode_compressed_image( "'iden' image referring to itself"); } - std::shared_ptr imgitem = get_context()->get_image(reference_image_id); + std::shared_ptr imgitem = get_context()->get_image(reference_image_id, true); if (!imgitem) { return Error(heif_error_Invalid_input, heif_suberror_Unspecified, "'iden' image references unavailable image"); } + if (auto error = imgitem->get_item_error()) { + return error; + } return imgitem->decode_compressed_image(options, decode_tile_only, tile_x0, tile_y0); } @@ -86,7 +89,7 @@ int ImageItem_iden::get_luma_bits_per_pixel() const return -1; } - auto image = get_context()->get_image(child); + auto image = get_context()->get_image(child, true); return image->get_luma_bits_per_pixel(); } @@ -99,6 +102,6 @@ int ImageItem_iden::get_chroma_bits_per_pixel() const return -1; } - auto image = get_context()->get_image(child); + auto image = get_context()->get_image(child, true); return image->get_chroma_bits_per_pixel(); } diff --git a/libheif/image-items/image_item.cc b/libheif/image-items/image_item.cc index a3149c2a68..5d20920fb7 100644 --- a/libheif/image-items/image_item.cc +++ b/libheif/image-items/image_item.cc @@ -59,12 +59,6 @@ ImageItem::ImageItem(HeifContext* context, heif_item_id id) } -bool HeifContext::is_image(heif_item_id ID) const -{ - return m_all_images.find(ID) != m_all_images.end(); -} - - std::shared_ptr ImageItem::get_file() const { return m_heif_context->get_heif_file(); diff --git a/libheif/image-items/image_item.h b/libheif/image-items/image_item.h index e1d90406eb..dc03200874 100644 --- a/libheif/image-items/image_item.h +++ b/libheif/image-items/image_item.h @@ -72,7 +72,7 @@ class ImageItem : public ErrorBuffer virtual bool is_ispe_essential() const { return false; } - virtual bool is_error_item() const { return false; } + virtual Error get_item_error() const { return Error::Ok; } // If the output format requires a specific nclx (like JPEG), return this. Otherwise, return NULL. virtual const heif_color_profile_nclx* get_forced_output_nclx() const { return nullptr; } @@ -435,9 +435,11 @@ class ImageItem_Error : public ImageItem return m_item_type; } - bool is_error_item() const override { return true; } + Error get_item_error() const override { return m_item_error; } - Error get_item_error() const { return m_item_error; } + [[nodiscard]] int get_luma_bits_per_pixel() const override { return -1; } + + [[nodiscard]] int get_chroma_bits_per_pixel() const override { return -1; } private: uint32_t m_item_type; diff --git a/libheif/image-items/overlay.cc b/libheif/image-items/overlay.cc index 8250941ed9..f31afbdc3e 100644 --- a/libheif/image-items/overlay.cc +++ b/libheif/image-items/overlay.cc @@ -319,10 +319,13 @@ Result> ImageItem_Overlay::decode_overlay_image( "Self-reference in 'iovl' image item."}; } - auto imgItem = get_context()->get_image(m_overlay_image_ids[i]); + auto imgItem = get_context()->get_image(m_overlay_image_ids[i], true); if (!imgItem) { return Error(heif_error_Invalid_input, heif_suberror_Nonexisting_item_referenced, "'iovl' image references a non-existing item."); } + if (auto error = imgItem->get_item_error()) { + return error; + } auto decodeResult = imgItem->decode_image(options, false, 0,0); if (decodeResult.error) { @@ -369,7 +372,7 @@ int ImageItem_Overlay::get_luma_bits_per_pixel() const return -1; } - auto image = get_context()->get_image(child); + auto image = get_context()->get_image(child, true); return image->get_luma_bits_per_pixel(); } @@ -382,6 +385,6 @@ int ImageItem_Overlay::get_chroma_bits_per_pixel() const return -1; } - auto image = get_context()->get_image(child); + auto image = get_context()->get_image(child, true); return image->get_chroma_bits_per_pixel(); }