Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 65 additions & 13 deletions libheif/image-items/grid.cc
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ Result<std::shared_ptr<HeifPixelImage>> ImageItem_Grid::decode_full_grid_image(c

int progress_counter = 0;
bool cancelled = false;
std::shared_ptr<std::vector<Error> > warnings(new std::vector<Error>());

for (uint32_t y = 0; y < grid.get_rows() && !cancelled; y++) {
uint32_t x0 = 0;
Expand All @@ -300,11 +301,30 @@ Result<std::shared_ptr<HeifPixelImage>> ImageItem_Grid::decode_full_grid_image(c

std::shared_ptr<const ImageItem> tileImg = get_context()->get_image(tileID, true);
if (!tileImg) {
if (!options.strict_decoding && reference_idx != 0) {
// Skip missing tiles (unless it's the first one).
warnings->push_back(Error{
heif_error_Invalid_input,
heif_suberror_Missing_grid_images,
});
reference_idx++;
x0 += tile_width;
continue;
}

return Error{heif_error_Invalid_input,
heif_suberror_Missing_grid_images,
"Nonexistent grid image referenced"};
}
if (auto error = tileImg->get_item_error()) {
if (!options.strict_decoding && reference_idx != 0) {
// Skip missing tiles (unless it's the first one).
warnings->push_back(error);
reference_idx++;
x0 += tile_width;
continue;
}

return error;
}

Expand Down Expand Up @@ -347,7 +367,7 @@ Result<std::shared_ptr<HeifPixelImage>> ImageItem_Grid::decode_full_grid_image(c
}
}

err = decode_and_paste_tile_image(tileID, x0, y0, img, options, progress_counter);
err = decode_and_paste_tile_image(tileID, x0, y0, img, options, progress_counter, warnings);
if (err) {
return err;
}
Expand Down Expand Up @@ -395,7 +415,7 @@ Result<std::shared_ptr<HeifPixelImage>> ImageItem_Grid::decode_full_grid_image(c
errs.push_back(std::async(std::launch::async,
&ImageItem_Grid::decode_and_paste_tile_image, this,
data.tileID, data.x_origin, data.y_origin, std::ref(img), options,
std::ref(progress_counter)));
std::ref(progress_counter), warnings));
}

// check for decoding errors in remaining tiles
Expand All @@ -419,24 +439,65 @@ Result<std::shared_ptr<HeifPixelImage>> ImageItem_Grid::decode_full_grid_image(c
return Error{heif_error_Canceled, heif_suberror_Unspecified, "Decoding the image was canceled"};
}

if (img) {
img->add_warnings(*warnings.get());
}

return img;
}

static Error progress_and_return_ok(const heif_decoding_options& options, int& progress_counter) {
if (options.on_progress) {
#if ENABLE_PARALLEL_TILE_DECODING
static std::mutex progressMutex;
std::lock_guard<std::mutex> lock(progressMutex);
#endif

options.on_progress(heif_progress_step_total, ++progress_counter, options.progress_user_data);
}
return Error::Ok;
}

Error ImageItem_Grid::decode_and_paste_tile_image(heif_item_id tileID, uint32_t x0, uint32_t y0,
std::shared_ptr<HeifPixelImage>& inout_image,
const heif_decoding_options& options,
int& progress_counter) const
int& progress_counter,
std::shared_ptr<std::vector<Error> > warnings) const
{
std::shared_ptr<HeifPixelImage> tile_img;
#if ENABLE_PARALLEL_TILE_DECODING
static std::mutex warningsMutex;
#endif

auto tileItem = get_context()->get_image(tileID, true);
if (!tileItem && !options.strict_decoding) {
// We ignore missing images.
#if ENABLE_PARALLEL_TILE_DECODING
std::lock_guard<std::mutex> lock(warningsMutex);
#endif
warnings->push_back(Error{
heif_error_Invalid_input,
heif_suberror_Missing_grid_images,
});
return progress_and_return_ok(options, progress_counter);
}

assert(tileItem);
if (auto error = tileItem->get_item_error()) {
return error;
}

auto decodeResult = tileItem->decode_image(options, false, 0, 0);
if (!decodeResult) {
if (!options.strict_decoding) {
// We ignore broken tiles.
#if ENABLE_PARALLEL_TILE_DECODING
std::lock_guard<std::mutex> lock(warningsMutex);
#endif
warnings->push_back(decodeResult.error());
return progress_and_return_ok(options, progress_counter);
}

return decodeResult.error();
}

Expand Down Expand Up @@ -489,16 +550,7 @@ Error ImageItem_Grid::decode_and_paste_tile_image(heif_item_id tileID, uint32_t

inout_image->copy_image_to(tile_img, x0, y0);

if (options.on_progress) {
#if ENABLE_PARALLEL_TILE_DECODING
static std::mutex progressMutex;
std::lock_guard<std::mutex> lock(progressMutex);
#endif

options.on_progress(heif_progress_step_total, ++progress_counter, options.progress_user_data);
}

return Error::Ok;
return progress_and_return_ok(options, progress_counter);
}


Expand Down
3 changes: 2 additions & 1 deletion libheif/image-items/grid.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,8 @@ class ImageItem_Grid : public ImageItem

Error decode_and_paste_tile_image(heif_item_id tileID, uint32_t x0, uint32_t y0,
std::shared_ptr<HeifPixelImage>& inout_image,
const heif_decoding_options& options, int& progress_counter) const;
const heif_decoding_options& options, int& progress_counter,
std::shared_ptr<std::vector<Error> > warnings) const;
};


Expand Down
4 changes: 4 additions & 0 deletions libheif/image-items/image_item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,10 @@ Result<std::shared_ptr<HeifPixelImage>> ImageItem::decode_image(const heif_decod
}

auto img = *decodingResult;
if (!img) {
// Can happen if missing tiled image is decoded in non-strict mode.
return Error(heif_error_Decoder_plugin_error, heif_suberror_Unspecified);
}

std::shared_ptr<HeifFile> file = m_heif_context->get_heif_file();

Expand Down
Loading