Skip to content

Commit

Permalink
Merge pull request #1180 from dukesook/encode_grid_pr
Browse files Browse the repository at this point in the history
Encode Grid
  • Loading branch information
farindk authored Jun 25, 2024
2 parents 77e9adb + 1392198 commit 7d7caa6
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 0 deletions.
53 changes: 53 additions & 0 deletions libheif/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2315,6 +2315,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

0 comments on commit 7d7caa6

Please sign in to comment.