Skip to content

Commit

Permalink
more checks for ImageItem_Error
Browse files Browse the repository at this point in the history
  • Loading branch information
farindk committed Oct 11, 2024
1 parent dc6c377 commit 49d0cb6
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 51 deletions.
12 changes: 6 additions & 6 deletions libheif/api/libheif/heif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<ImageItem> primary_image = ctx->context->get_primary_image();
std::shared_ptr<ImageItem> 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.
Expand Down Expand Up @@ -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<ImageItem> primary = ctx->context->get_primary_image();
std::shared_ptr<ImageItem> 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());
Expand All @@ -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<std::shared_ptr<ImageItem>> images = ctx->context->get_top_level_images();
const std::vector<std::shared_ptr<ImageItem>> images = ctx->context->get_top_level_images(true);

for (const auto& img : images) {
if (img->get_id() == id) {
Expand All @@ -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();
}


Expand All @@ -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<std::shared_ptr<ImageItem>> imgs = ctx->context->get_top_level_images();
const std::vector<std::shared_ptr<ImageItem>> 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();
Expand All @@ -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<ImageItem_Error>(image)) {
Error error = errImage->get_item_error();
Expand Down
59 changes: 55 additions & 4 deletions libheif/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,56 @@ Error HeifContext::check_resolution(uint32_t width, uint32_t height) const {
}


std::vector<std::shared_ptr<ImageItem>> HeifContext::get_top_level_images(bool return_error_images)
{
if (return_error_images) {
return m_top_level_images;
}
else {
std::vector<std::shared_ptr<ImageItem>> filtered;
for (auto& item : m_top_level_images) {
if (!item->get_item_error()) {
filtered.push_back(item);
}
}

return filtered;
}
}


std::shared_ptr<ImageItem> 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<ImageItem> 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<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"));
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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<ImageItem_Tiled>(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();

Expand Down
19 changes: 5 additions & 14 deletions libheif/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,29 +94,20 @@ class HeifContext : public ErrorBuffer

std::shared_ptr<HeifFile> get_heif_file() const { return m_heif_file; }

std::vector<std::shared_ptr<ImageItem>> get_top_level_images() { return m_top_level_images; }
std::vector<std::shared_ptr<ImageItem>> get_top_level_images(bool return_error_images);

void insert_new_image(heif_item_id id, std::shared_ptr<ImageItem> img) {
m_all_images.insert(std::make_pair(id, img));
}

std::shared_ptr<ImageItem> 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<ImageItem> get_image(heif_item_id id, bool return_error_images);

std::shared_ptr<const ImageItem> get_image(heif_item_id id) const
std::shared_ptr<const ImageItem> get_image(heif_item_id id, bool return_error_images) const
{
return const_cast<HeifContext*>(this)->get_image(id);
return const_cast<HeifContext*>(this)->get_image(id, return_error_images);
}

std::shared_ptr<ImageItem> get_primary_image() { return m_primary_image; }
std::shared_ptr<ImageItem> get_primary_image(bool return_error_image);

bool is_image(heif_item_id ID) const;

Expand Down
44 changes: 32 additions & 12 deletions libheif/image-items/grid.cc
Original file line number Diff line number Diff line change
Expand Up @@ -279,12 +279,15 @@ Result<std::shared_ptr<HeifPixelImage>> ImageItem_Grid::decode_full_grid_image(c

heif_item_id tileID = image_references[reference_idx];

std::shared_ptr<const ImageItem> tileImg = get_context()->get_image(tileID);
std::shared_ptr<const ImageItem> 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();
Expand Down Expand Up @@ -384,8 +387,11 @@ Error ImageItem_Grid::decode_and_paste_tile_image(heif_item_id tileID, uint32_t
{
std::shared_ptr<HeifPixelImage> 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) {
Expand Down Expand Up @@ -443,7 +449,10 @@ Result<std::shared_ptr<HeifPixelImage>> 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<const ImageItem> tile_item = get_context()->get_image(tile_id);
std::shared_ptr<const ImageItem> 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);
}
Expand All @@ -457,23 +466,30 @@ 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;
}


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();
Expand All @@ -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;
}
Expand All @@ -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();
}

Expand All @@ -518,6 +534,10 @@ std::shared_ptr<Decoder> 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();
}
9 changes: 6 additions & 3 deletions libheif/image-items/iden.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,15 @@ Result<std::shared_ptr<HeifPixelImage>> ImageItem_iden::decode_compressed_image(
"'iden' image referring to itself");
}

std::shared_ptr<const ImageItem> imgitem = get_context()->get_image(reference_image_id);
std::shared_ptr<const ImageItem> 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);
}
Expand All @@ -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();
}

Expand All @@ -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();
}
6 changes: 0 additions & 6 deletions libheif/image-items/image_item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<HeifFile> ImageItem::get_file() const
{
return m_heif_context->get_heif_file();
Expand Down
8 changes: 5 additions & 3 deletions libheif/image-items/image_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 6 additions & 3 deletions libheif/image-items/overlay.cc
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,13 @@ Result<std::shared_ptr<HeifPixelImage>> 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) {
Expand Down Expand Up @@ -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();
}

Expand All @@ -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();
}

0 comments on commit 49d0cb6

Please sign in to comment.