diff --git a/libheif/api/libheif/heif.cc b/libheif/api/libheif/heif.cc index 5a74e50c50..4ef92b1a7b 100644 --- a/libheif/api/libheif/heif.cc +++ b/libheif/api/libheif/heif.cc @@ -3574,8 +3574,8 @@ struct heif_error heif_context_add_image_tile(struct heif_context* ctx, const struct heif_image* image, struct heif_encoder* encoder) { - if (tiled_image->image->get_infe_type() == fourcc("tili")) { - Error err = ctx->context->add_tiled_image_tile(tiled_image->image->get_id(), tile_x, tile_y, image->image, encoder); + if (auto tili_image = std::dynamic_pointer_cast(tiled_image->image)) { + Error err = tili_image->add_image_tile(tile_x, tile_y, image->image, encoder); return err.error_struct(ctx->context.get()); } #if WITH_UNCOMPRESSED_CODEC diff --git a/libheif/context.cc b/libheif/context.cc index 6b7463d4f8..1278da4ab3 100644 --- a/libheif/context.cc +++ b/libheif/context.cc @@ -1243,90 +1243,6 @@ Error HeifContext::encode_image(const std::shared_ptr& pixel_ima return error; } -Error HeifContext::add_tiled_image_tile(heif_item_id tild_id, uint32_t tile_x, uint32_t tile_y, - const std::shared_ptr& image, - struct heif_encoder* encoder) -{ - auto item = ImageItem::alloc_for_compression_format(this, encoder->plugin->compression_format); - - heif_encoding_options* options = heif_encoding_options_alloc(); // TODO: should this be taken from heif_context_add_tiled_image() ? - - Result> colorConversionResult = item->convert_colorspace_for_encoding(image, encoder, *options); - if (colorConversionResult.error) { - return colorConversionResult.error; - } - - std::shared_ptr colorConvertedImage = colorConversionResult.value; - - Result encodeResult = item->encode_to_bitstream_and_boxes(colorConvertedImage, encoder, *options, heif_image_input_class_normal); // TODO (other than JPEG) - heif_encoding_options_free(options); - - if (encodeResult.error) { - return encodeResult.error; - } - - 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, true); - auto tildImg = std::dynamic_pointer_cast(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(); - - if (image->get_width() != header.get_parameters().tile_width || - image->get_height() != header.get_parameters().tile_height) { - - std::cout << "tx:" << tile_x << " ty:" << tile_y << "\n"; - std::cout << image->get_width() << " " << header.get_parameters().tile_width << " | " - << image->get_height() << " " << header.get_parameters().tile_height <<"\n"; - - return {heif_error_Usage_error, - heif_suberror_Unspecified, - "Tile image size does not match the specified tile size."}; - } - - uint64_t offset = tildImg->get_next_tild_position(); - size_t dataSize = encodeResult.value.bitstream.size(); - if (dataSize > 0xFFFFFFFF) { - return {heif_error_Encoding_error, heif_suberror_Unspecified, "Compressed tile size exceeds maximum tile size."}; - } - header.set_tild_tile_range(tile_x, tile_y, offset, static_cast(dataSize)); - tildImg->set_next_tild_position(offset + encodeResult.value.bitstream.size()); - - std::vector> existing_properties; - Error err = m_heif_file->get_properties(tild_id, existing_properties); - if (err) { - return err; - } - - for (auto& propertyBox : encodeResult.value.properties) { - if (propertyBox->get_short_type() == fourcc("ispe")) { - continue; - } - - // skip properties that exist already - - bool exists = std::any_of(existing_properties.begin(), - existing_properties.end(), - [&propertyBox](const std::shared_ptr& p) { return p->get_short_type() == propertyBox->get_short_type();}); - if (exists) { - continue; - } - - m_heif_file->add_property(tild_id, propertyBox, propertyBox->is_essential()); - } - - m_heif_file->set_brand(encoder->plugin->compression_format, - true); // TODO: out_grid_image->is_miaf_compatible()); - - return Error::Ok; -} - - void HeifContext::set_primary_image(const std::shared_ptr& image) { // update heif context diff --git a/libheif/context.h b/libheif/context.h index d9983e3e3c..422f5ad352 100644 --- a/libheif/context.h +++ b/libheif/context.h @@ -128,10 +128,6 @@ class HeifContext : public ErrorBuffer enum heif_image_input_class input_class, std::shared_ptr& out_image); - Error add_tiled_image_tile(heif_item_id tili_id, uint32_t tile_x, uint32_t tile_y, - const std::shared_ptr& image, - struct heif_encoder* encoder); - void set_primary_image(const std::shared_ptr& image); bool is_primary_image_set() const { return m_primary_image != nullptr; } diff --git a/libheif/image-items/tiled.cc b/libheif/image-items/tiled.cc index 25c41032df..f61a99e18b 100644 --- a/libheif/image-items/tiled.cc +++ b/libheif/image-items/tiled.cc @@ -569,6 +569,83 @@ ImageItem_Tiled::add_new_tiled_item(HeifContext* ctx, const heif_tiled_image_par } +Error ImageItem_Tiled::add_image_tile(uint32_t tile_x, uint32_t tile_y, + const std::shared_ptr& image, + struct heif_encoder* encoder) +{ + auto item = ImageItem::alloc_for_compression_format(get_context(), encoder->plugin->compression_format); + + heif_encoding_options* options = heif_encoding_options_alloc(); // TODO: should this be taken from heif_context_add_tiled_image() ? + + Result> colorConversionResult = item->convert_colorspace_for_encoding(image, encoder, *options); + if (colorConversionResult.error) { + return colorConversionResult.error; + } + + std::shared_ptr colorConvertedImage = colorConversionResult.value; + + Result encodeResult = item->encode_to_bitstream_and_boxes(colorConvertedImage, encoder, *options, heif_image_input_class_normal); // TODO (other than JPEG) + heif_encoding_options_free(options); + + if (encodeResult.error) { + return encodeResult.error; + } + + const int construction_method = 0; // 0=mdat 1=idat + get_file()->append_iloc_data(get_id(), encodeResult.value.bitstream, construction_method); + + auto& header = m_tild_header; + + if (image->get_width() != header.get_parameters().tile_width || + image->get_height() != header.get_parameters().tile_height) { + + std::cout << "tx:" << tile_x << " ty:" << tile_y << "\n"; + std::cout << image->get_width() << " " << header.get_parameters().tile_width << " | " + << image->get_height() << " " << header.get_parameters().tile_height <<"\n"; + + return {heif_error_Usage_error, + heif_suberror_Unspecified, + "Tile image size does not match the specified tile size."}; + } + + uint64_t offset = get_next_tild_position(); + size_t dataSize = encodeResult.value.bitstream.size(); + if (dataSize > 0xFFFFFFFF) { + return {heif_error_Encoding_error, heif_suberror_Unspecified, "Compressed tile size exceeds maximum tile size."}; + } + header.set_tild_tile_range(tile_x, tile_y, offset, static_cast(dataSize)); + set_next_tild_position(offset + encodeResult.value.bitstream.size()); + + std::vector> existing_properties; + Error err = get_file()->get_properties(get_id(), existing_properties); + if (err) { + return err; + } + + for (auto& propertyBox : encodeResult.value.properties) { + if (propertyBox->get_short_type() == fourcc("ispe")) { + continue; + } + + // skip properties that exist already + + bool exists = std::any_of(existing_properties.begin(), + existing_properties.end(), + [&propertyBox](const std::shared_ptr& p) { return p->get_short_type() == propertyBox->get_short_type();}); + if (exists) { + continue; + } + + get_file()->add_property(get_id(), propertyBox, propertyBox->is_essential()); + } + + get_file()->set_brand(encoder->plugin->compression_format, + true); // TODO: out_grid_image->is_miaf_compatible()); + + return Error::Ok; +} + + void ImageItem_Tiled::process_before_write() { // overwrite offsets diff --git a/libheif/image-items/tiled.h b/libheif/image-items/tiled.h index de6782638e..9af358b132 100644 --- a/libheif/image-items/tiled.h +++ b/libheif/image-items/tiled.h @@ -147,6 +147,11 @@ class ImageItem_Tiled : public ImageItem static Result> add_new_tiled_item(HeifContext* ctx, const heif_tiled_image_parameters* parameters, const heif_encoder* encoder); + Error add_image_tile(uint32_t tile_x, uint32_t tile_y, + const std::shared_ptr& image, + struct heif_encoder* encoder); + + Error on_load_file() override; void process_before_write() override;