Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encode Grid #1180

Merged
merged 7 commits into from
Jun 25, 2024
Merged
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
53 changes: 53 additions & 0 deletions libheif/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2314,6 +2314,59 @@ Error HeifContext::encode_image(const std::shared_ptr<HeifPixelImage>& pixel_ima
return error;
}

Error HeifContext::encode_grid(const std::vector<std::shared_ptr<HeifPixelImage>>& tiles,
uint16_t rows,
uint16_t columns,
struct heif_encoder* encoder,
const struct heif_encoding_options& options,
std::shared_ptr<Image>& out_grid_image)
{
// Create ImageGrid
ImageGrid grid;
grid.set_num_tiles(columns, rows);
int tile_width = tiles[0]->get_width(heif_channel_interleaved);
int tile_height = tiles[0]->get_height(heif_channel_interleaved);
grid.set_output_size(tile_width * columns, tile_height * rows);
std::vector<uint8_t> grid_data = grid.write();

// Encode Tiles
Error error;
std::vector<heif_item_id> tile_ids;
for (int i=0; i<rows*columns; i++) {
std::shared_ptr<Image> out_tile;
error = encode_image(tiles[i],
encoder,
options,
heif_image_input_class_normal,
out_tile);
heif_item_id tile_id = out_tile->get_id();
m_heif_file->get_infe_box(tile_id)->set_hidden_item(true); // only show the full grid
tile_ids.push_back(out_tile->get_id());
}

// Create Grid Item
heif_item_id grid_id = m_heif_file->add_new_image("grid");
out_grid_image = std::make_shared<Image>(this, grid_id);
m_all_images.insert(std::make_pair(grid_id, out_grid_image));
const int construction_method = 1; // 0=mdat 1=idat
m_heif_file->append_iloc_data(grid_id, grid_data, construction_method);

// Connect tiles to grid
m_heif_file->add_iref_reference(grid_id, fourcc("dimg"), tile_ids);

// Add ISPE property
int image_width = tile_width * columns;
int image_height = tile_height * rows;
m_heif_file->add_ispe_property(grid_id, image_width, image_height);

// Set Brands
m_heif_file->set_brand(encoder->plugin->compression_format,
out_grid_image->is_miaf_compatible());

return error;
}


/*
static uint32_t get_rotated_width(heif_orientation orientation, uint32_t w, uint32_t h)
{
Expand Down
7 changes: 7 additions & 0 deletions libheif/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,13 @@ class HeifContext : public ErrorBuffer
enum heif_image_input_class input_class,
std::shared_ptr<Image>& out_image);

Error encode_grid(const std::vector<std::shared_ptr<HeifPixelImage>>& tiles,
uint16_t rows,
uint16_t columns,
struct heif_encoder* encoder,
const struct heif_encoding_options& options,
std::shared_ptr<Image>& out_image);

Error encode_image_as_hevc(const std::shared_ptr<HeifPixelImage>& image,
struct heif_encoder* encoder,
const struct heif_encoding_options& options,
Expand Down
70 changes: 70 additions & 0 deletions libheif/heif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2707,6 +2707,76 @@ struct heif_error heif_context_encode_image(struct heif_context* ctx,
}


struct heif_error heif_context_encode_grid(struct heif_context* ctx,
struct heif_image** tiles,
uint16_t columns,
uint16_t rows,
struct heif_encoder* encoder,
const struct heif_encoding_options* input_options,
struct heif_image_handle** out_image_handle)
{
if (!encoder || !tiles) {
return Error(heif_error_Usage_error,
heif_suberror_Null_pointer_argument).error_struct(ctx->context.get());
}
else if (rows == 0 || columns == 0) {
return Error(heif_error_Usage_error,
heif_suberror_Invalid_parameter_value).error_struct(ctx->context.get());
}

// TODO: Don't repeat this code from heif_context_encode_image()
heif_encoding_options options;
heif_color_profile_nclx nclx;
set_default_options(options);
if (input_options) {
copy_options(options, *input_options);

if (options.output_nclx_profile == nullptr) {
auto input_nclx = tiles[0]->image->get_color_profile_nclx();
if (input_nclx) {
options.output_nclx_profile = &nclx;
nclx.version = 1;
nclx.color_primaries = (enum heif_color_primaries) input_nclx->get_colour_primaries();
nclx.transfer_characteristics = (enum heif_transfer_characteristics) input_nclx->get_transfer_characteristics();
nclx.matrix_coefficients = (enum heif_matrix_coefficients) input_nclx->get_matrix_coefficients();
nclx.full_range_flag = input_nclx->get_full_range_flag();
}
}
}

// Convert heif_images to a vector of HeifPixelImages
std::vector<std::shared_ptr<HeifPixelImage>> pixel_tiles;
for (int i=0; i<rows*columns; i++) {
pixel_tiles.push_back(tiles[i]->image);
}

// Encode Grid
Error error;
std::shared_ptr<HeifContext::Image> out_grid;
error = ctx->context->encode_grid(pixel_tiles,
rows, columns,
encoder,
options,
out_grid);
if (error != Error::Ok) {
return error.error_struct(ctx->context.get());
}

// Mark as primary image
if (ctx->context->is_primary_image_set() == false) {
ctx->context->set_primary_image(out_grid);
}

if (out_image_handle) {
*out_image_handle = new heif_image_handle;
(*out_image_handle)->image = out_grid;
(*out_image_handle)->context = ctx->context;
}

return heif_error_success;
}


struct heif_error heif_context_assign_thumbnail(struct heif_context* ctx,
const struct heif_image_handle* master_image,
const struct heif_image_handle* thumbnail_image)
Expand Down
21 changes: 21 additions & 0 deletions libheif/heif.h
Original file line number Diff line number Diff line change
Expand Up @@ -2037,6 +2037,27 @@ struct heif_error heif_context_encode_image(struct heif_context*,
const struct heif_encoding_options* options,
struct heif_image_handle** out_image_handle);

/**
* @brief Encodes an array of images into a grid.
*
* @param ctx The file context
* @param tiles User allocated array of images that will form the grid.
* @param rows The number of rows in the grid.
* @param columns The number of columns in the grid.
* @param encoder Defines the encoder to use. See heif_context_get_encoder_for_format()
* @param input_options Optional, may be nullptr.
* @param out_image_handle Returns a handle to the grid. The caller is responsible for freeing it.
* @return Returns an error if ctx, tiles, or encoder is nullptr. If rows or columns is 0.
*/
LIBHEIF_API
struct heif_error heif_context_encode_grid(struct heif_context* ctx,
struct heif_image** tiles,
uint16_t rows,
uint16_t columns,
struct heif_encoder* encoder,
const struct heif_encoding_options* input_options,
struct heif_image_handle** out_image_handle);

LIBHEIF_API
struct heif_error heif_context_set_primary_image(struct heif_context*,
struct heif_image_handle* image_handle);
Expand Down
Loading