Skip to content

Commit

Permalink
move 'grid' image tile access to codecs
Browse files Browse the repository at this point in the history
  • Loading branch information
farindk committed Aug 18, 2024
1 parent b35059c commit 02ebde0
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 90 deletions.
148 changes: 63 additions & 85 deletions libheif/api/libheif/heif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -938,65 +938,6 @@ struct heif_error heif_image_handle_get_tile_size(const struct heif_image_handle
}


// TODO: move this into the Context. But first, we also have to move heif_decode_image() into Context.
struct heif_error heif_image_handle_decode_image_tile(const struct heif_image_handle* handle,
struct heif_image** out_img,
enum heif_colorspace colorspace,
enum heif_chroma chroma,
const struct heif_decoding_options* options,
uint64_t x0, uint64_t y0, uint64_t z0)
{
if (!handle) {
return error_null_parameter;
}

std::shared_ptr<ImageItem_Grid> gridItem = std::dynamic_pointer_cast<ImageItem_Grid>(handle->image);
if (gridItem) {
if (z0 != 0) {
return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "z0 must be 0 for 2D images"};
}

if (x0 > 0xFFFFFFFF || y0 > 0xFFFFFFFF) {
return {heif_error_Usage_error, heif_suberror_Invalid_parameter_value, "x0/y0 currently must be 32 bit"};
}

heif_item_id first_tile_id = gridItem->get_grid_tiles()[0];
auto tile = handle->context->get_image(first_tile_id);

const ImageGrid& gridspec = gridItem->get_grid_spec();
uint32_t tile_x = static_cast<uint32_t>(x0) / tile->get_width();
uint32_t tile_y = static_cast<uint32_t>(y0) / tile->get_height();

heif_item_id tile_id = gridItem->get_grid_tiles()[tile_y * gridspec.get_columns() + tile_x];
heif_image_handle* tile_handle;
heif_context* ctx = heif_image_handle_get_context(handle);
heif_error err = heif_context_get_image_handle(ctx, tile_id, &tile_handle);
if (err.code) {
heif_image_handle_release(tile_handle);
heif_context_free(ctx);
err.message = nullptr; // have to delete the text pointer because the text may be deleted with the context (TODO)
return err;
}

heif_context_free(ctx);
err = heif_decode_image(tile_handle, out_img, colorspace, chroma, options);
if (err.code) {
heif_image_handle_release(tile_handle);
err.message = nullptr; // have to delete the text pointer because the text may be deleted with the context (TODO)
return err;
}

heif_image_handle_release(tile_handle);

return heif_error_success;
}

// --- fallback: decode the whole image

return heif_decode_image(handle, out_img, colorspace, chroma, options);
}


struct heif_error heif_context_add_pyramid_entity_group(struct heif_context* ctx,
uint16_t tile_width,
uint16_t tile_height,
Expand Down Expand Up @@ -1198,29 +1139,37 @@ void fill_default_decoding_options(heif_decoding_options& options)
}


static void copy_options(heif_decoding_options& options, const heif_decoding_options& input_options)
// overwrite the (possibly lower version) input options over the default options
static heif_decoding_options normalize_options(const heif_decoding_options* input_options)
{
switch (input_options.version) {
case 5:
options.color_conversion_options = input_options.color_conversion_options;
// fallthrough
case 4:
options.decoder_id = input_options.decoder_id;
// fallthrough
case 3:
options.strict_decoding = input_options.strict_decoding;
// fallthrough
case 2:
options.convert_hdr_to_8bit = input_options.convert_hdr_to_8bit;
// fallthrough
case 1:
options.ignore_transformations = input_options.ignore_transformations;
heif_decoding_options options{};
fill_default_decoding_options(options);

options.start_progress = input_options.start_progress;
options.on_progress = input_options.on_progress;
options.end_progress = input_options.end_progress;
options.progress_user_data = input_options.progress_user_data;
if (input_options) {
switch (input_options->version) {
case 5:
options.color_conversion_options = input_options->color_conversion_options;
// fallthrough
case 4:
options.decoder_id = input_options->decoder_id;
// fallthrough
case 3:
options.strict_decoding = input_options->strict_decoding;
// fallthrough
case 2:
options.convert_hdr_to_8bit = input_options->convert_hdr_to_8bit;
// fallthrough
case 1:
options.ignore_transformations = input_options->ignore_transformations;

options.start_progress = input_options->start_progress;
options.on_progress = input_options->on_progress;
options.end_progress = input_options->end_progress;
options.progress_user_data = input_options->progress_user_data;
}
}

return options;
}


Expand Down Expand Up @@ -1248,18 +1197,47 @@ struct heif_error heif_decode_image(const struct heif_image_handle* in_handle,
{
heif_item_id id = in_handle->image->get_id();

heif_decoding_options dec_options;
fill_default_decoding_options(dec_options);
heif_decoding_options dec_options = normalize_options(input_options);

if (input_options != nullptr) {
// overwrite the (possibly lower version) input options over the default options
copy_options(dec_options, *input_options);
Result<std::shared_ptr<HeifPixelImage>> decodingResult = in_handle->context->decode_image(id,
colorspace,
chroma,
dec_options,
false, 0,0);
if (decodingResult.error.error_code != heif_error_Ok) {
return decodingResult.error.error_struct(in_handle->image.get());
}

std::shared_ptr<HeifPixelImage> img = decodingResult.value;

*out_img = new heif_image();
(*out_img)->image = std::move(img);

return Error::Ok.error_struct(in_handle->image.get());
}


// TODO: move this into the Context. But first, we also have to move heif_decode_image() into Context.
struct heif_error heif_image_handle_decode_image_tile(const struct heif_image_handle* in_handle,
struct heif_image** out_img,
enum heif_colorspace colorspace,
enum heif_chroma chroma,
const struct heif_decoding_options* input_options,
uint64_t x0, uint64_t y0, uint64_t z0)
{
if (!in_handle) {
return error_null_parameter;
}

heif_item_id id = in_handle->image->get_id();

heif_decoding_options dec_options = normalize_options(input_options);

Result<std::shared_ptr<HeifPixelImage>> decodingResult = in_handle->context->decode_image(id,
colorspace,
chroma,
dec_options);
dec_options,
true, x0,y0);
if (decodingResult.error.error_code != heif_error_Ok) {
return decodingResult.error.error_struct(in_handle->image.get());
}
Expand Down
18 changes: 16 additions & 2 deletions libheif/codecs/grid.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ Error ImageGrid::parse(const std::vector<uint8_t>& data)
m_rows = static_cast<uint16_t>(data[2] + 1);
m_columns = static_cast<uint16_t>(data[3] + 1);

printf("rows:%d columns:%d\n", m_rows, m_columns);

if (field_size == 32) {
if (data.size() < 12) {
return Error(heif_error_Invalid_input,
Expand Down Expand Up @@ -214,8 +216,7 @@ Result<std::shared_ptr<HeifPixelImage>> ImageItem_Grid::decode_compressed_image(
bool decode_tile_only, uint32_t tile_x0, uint32_t tile_y0) const
{
if (decode_tile_only) {
// TODO
return Error{heif_error_Unsupported_feature, heif_suberror_Unspecified, "Tile access to grid images not implemented"};
return decode_grid_tile(options, tile_x0, tile_y0);
}
else {
return decode_full_grid_image(options);
Expand Down Expand Up @@ -558,6 +559,19 @@ Error ImageItem_Grid::decode_and_paste_tile_image(heif_item_id tileID, uint32_t
}


Result<std::shared_ptr<HeifPixelImage>> ImageItem_Grid::decode_grid_tile(const heif_decoding_options& options, uint32_t tx, uint32_t ty) const
{
uint32_t idx = ty * m_grid_spec.get_columns() + tx;

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);

return tile_item->decode_compressed_image(options, true, tx, ty);
}


heif_image_tiling ImageItem_Grid::get_heif_image_tiling() const
{
heif_image_tiling tiling{};
Expand Down
2 changes: 2 additions & 0 deletions libheif/codecs/grid.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ class ImageItem_Grid : public ImageItem

Result<std::shared_ptr<HeifPixelImage>> decode_full_grid_image(const heif_decoding_options& options) const;

Result<std::shared_ptr<HeifPixelImage>> decode_grid_tile(const heif_decoding_options& options, uint32_t tx, uint32_t ty) const;

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) const;
Expand Down
5 changes: 3 additions & 2 deletions libheif/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,8 @@ Error HeifContext::get_id_of_non_virtual_child_image(heif_item_id id, heif_item_
Result<std::shared_ptr<HeifPixelImage>> HeifContext::decode_image(heif_item_id ID,
heif_colorspace out_colorspace,
heif_chroma out_chroma,
const struct heif_decoding_options& options) const
const struct heif_decoding_options& options,
bool decode_only_tile, uint32_t tx, uint32_t ty) const
{
std::string image_type = m_heif_file->get_item_type(ID);

Expand All @@ -972,7 +973,7 @@ Result<std::shared_ptr<HeifPixelImage>> HeifContext::decode_image(heif_item_id I
}


auto decodingResult = imginfo->decode_image(out_colorspace, options, false,0,0);
auto decodingResult = imginfo->decode_image(out_colorspace, options, decode_only_tile, tx, ty);
if (decodingResult.error) {
return decodingResult.error;
}
Expand Down
3 changes: 2 additions & 1 deletion libheif/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ class HeifContext : public ErrorBuffer
Result<std::shared_ptr<HeifPixelImage>> decode_image(heif_item_id ID,
heif_colorspace out_colorspace,
heif_chroma out_chroma,
const struct heif_decoding_options& options) const;
const struct heif_decoding_options& options,
bool decode_only_tile, uint32_t tx, uint32_t ty) const;

std::string debug_dump_boxes() const;

Expand Down

0 comments on commit 02ebde0

Please sign in to comment.