Skip to content

Commit

Permalink
Merge pull request strukturag#1318 from strukturag/write-unci-tiles
Browse files Browse the repository at this point in the history
unci: write tiled images
  • Loading branch information
farindk authored Sep 23, 2024
2 parents acdc8d9 + dcd2399 commit 4230cf4
Show file tree
Hide file tree
Showing 18 changed files with 585 additions and 100 deletions.
8 changes: 4 additions & 4 deletions libheif/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,10 @@ endif ()
if (WITH_UNCOMPRESSED_CODEC)
target_compile_definitions(heif PUBLIC WITH_UNCOMPRESSED_CODEC=1)
target_sources(heif PRIVATE
codecs/uncompressed_box.h
codecs/uncompressed_box.cc
codecs/uncompressed_image.h
codecs/uncompressed_image.cc)
codecs/uncompressed/unc_boxes.h
codecs/uncompressed/unc_boxes.cc
codecs/uncompressed/unc_image.h
codecs/uncompressed/unc_image.cc)
endif ()

write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake COMPATIBILITY ExactVersion)
Expand Down
69 changes: 62 additions & 7 deletions libheif/api/libheif/heif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
#include <set>
#include <limits>

#if WITH_UNCOMPRESSED_CODEC
#include "codecs/uncompressed/unc_image.h"
#endif

#if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_STANDALONE_WASM__)
#include "heif_emscripten.h"
#endif
Expand Down Expand Up @@ -873,6 +877,13 @@ struct heif_image_tiling heif_image_handle_get_image_tiling(const struct heif_im
return tildItem->get_heif_image_tiling();
}

#if WITH_UNCOMPRESSED_CODEC
std::shared_ptr<ImageItem_uncompressed> unciItem = std::dynamic_pointer_cast<ImageItem_uncompressed>(handle->image);
if (unciItem) {
return unciItem->get_heif_image_tiling();
}
#endif

return tiling;
}

Expand Down Expand Up @@ -3461,14 +3472,58 @@ struct heif_error heif_context_add_tild_image(struct heif_context* ctx,
}


struct heif_error heif_context_add_tild_image_tile(struct heif_context* ctx,
struct heif_image_handle* tild_image,
uint32_t tile_x, uint32_t tile_y,
const struct heif_image* image,
struct heif_encoder* encoder)
struct heif_error heif_context_add_image_tile(struct heif_context* ctx,
struct heif_image_handle* tiled_image,
uint32_t tile_x, uint32_t tile_y,
const struct heif_image* image,
struct heif_encoder* encoder)
{
Error err = ctx->context->add_tild_image_tile(tild_image->image->get_id(), tile_x, tile_y, image->image, encoder);
return err.error_struct(ctx->context.get());
if (tiled_image->image->get_infe_type() == std::string{"tili"}) {
Error err = ctx->context->add_tild_image_tile(tiled_image->image->get_id(), tile_x, tile_y, image->image, encoder);
return err.error_struct(ctx->context.get());
}
#if WITH_UNCOMPRESSED_CODEC
else if (auto unci = std::dynamic_pointer_cast<ImageItem_uncompressed>(tiled_image->image)) {
Error err = unci->add_image_tile(tile_x, tile_y, image->image);
return err.error_struct(ctx->context.get());
}
#endif
else {
return {
heif_error_Usage_error,
heif_suberror_Unspecified,
"Cannot add tile to a non-tiled image"
};
}
}


struct heif_error heif_context_add_unci_image(struct heif_context* ctx,
const struct heif_unci_image_parameters* parameters,
const struct heif_encoding_options* encoding_options,
const heif_image* prototype,
struct heif_image_handle** out_unci_image_handle)
{
#if WITH_UNCOMPRESSED_CODEC
Result<std::shared_ptr<ImageItem_uncompressed>> unciImageResult;
unciImageResult = ctx->context->add_unci_item(parameters, encoding_options, prototype->image);

if (unciImageResult.error != Error::Ok) {
return unciImageResult.error.error_struct(ctx->context.get());
}

if (out_unci_image_handle) {
*out_unci_image_handle = new heif_image_handle;
(*out_unci_image_handle)->image = unciImageResult.value;
(*out_unci_image_handle)->context = ctx->context;
}

return heif_error_success;
#else
return {heif_error_Unsupported_feature,
heif_suberror_Unspecified,
"support for uncompressed images (ISO23001-17) has been disabled."};
#endif
}


Expand Down
53 changes: 38 additions & 15 deletions libheif/api/libheif/heif.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,16 @@ enum heif_channel_datatype
heif_channel_datatype_complex_number = 4
};

enum heif_metadata_compression
{
heif_metadata_compression_off = 0,
heif_metadata_compression_auto = 1,
heif_metadata_compression_unknown = 2, // only used when reading unknown method from input file
heif_metadata_compression_deflate = 3,
heif_metadata_compression_zlib = 4, // do not use for header data
heif_metadata_compression_brotli = 5
};

// ========================= library initialization ======================

struct heif_init_params
Expand Down Expand Up @@ -2458,12 +2468,35 @@ struct heif_error heif_context_add_tild_image(struct heif_context* ctx,
struct heif_image_handle** out_tild_image_handle);

LIBHEIF_API
struct heif_error heif_context_add_tild_image_tile(struct heif_context* ctx,
struct heif_image_handle* tild_image,
uint32_t tile_x, uint32_t tile_y,
const struct heif_image* image,
struct heif_encoder* encoder);
struct heif_error heif_context_add_image_tile(struct heif_context* ctx,
struct heif_image_handle* tild_image,
uint32_t tile_x, uint32_t tile_y,
const struct heif_image* image,
struct heif_encoder* encoder);

struct heif_unci_image_parameters {
int version;

// --- version 1

uint32_t image_width;
uint32_t image_height;

uint32_t tile_width;
uint32_t tile_height;

enum heif_metadata_compression compression; // TODO

// TODO: interleave type, padding
};


LIBHEIF_API
struct heif_error heif_context_add_unci_image(struct heif_context* ctx,
const struct heif_unci_image_parameters* parameters,
const struct heif_encoding_options* encoding_options,
const struct heif_image* prototype,
struct heif_image_handle** out_unci_image_handle);

// offsets[] should either be NULL (all offsets==0) or an array of size 2*nImages with x;y offset pairs.
// If background_rgba is NULL, the background is transparent.
Expand Down Expand Up @@ -2497,16 +2530,6 @@ struct heif_error heif_context_encode_thumbnail(struct heif_context*,
int bbox_size,
struct heif_image_handle** out_thumb_image_handle);

enum heif_metadata_compression
{
heif_metadata_compression_off = 0,
heif_metadata_compression_auto = 1,
heif_metadata_compression_unknown = 2, // only used when reading unknown method from input file
heif_metadata_compression_deflate = 3,
heif_metadata_compression_zlib = 4, // do not use for header data
heif_metadata_compression_brotli = 5
};

// Assign 'thumbnail_image' as the thumbnail image of 'master_image'.
LIBHEIF_API
struct heif_error heif_context_assign_thumbnail(struct heif_context*,
Expand Down
28 changes: 23 additions & 5 deletions libheif/box.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@


#if WITH_UNCOMPRESSED_CODEC
#include "codecs/uncompressed_box.h"
#include "codecs/uncompressed/unc_boxes.h"
#endif

#ifndef M_PI
Expand Down Expand Up @@ -1701,12 +1701,11 @@ Error Box_iloc::append_data(heif_item_id item_ID,


Error Box_iloc::replace_data(heif_item_id item_ID,
uint64_t offset,
uint64_t output_offset,
const std::vector<uint8_t>& data,
uint8_t construction_method)
{
assert(construction_method == 0); // TODO
assert(offset == 0); // TODO

// check whether this item ID already exists

Expand All @@ -1718,8 +1717,27 @@ Error Box_iloc::replace_data(heif_item_id item_ID,
}

assert(idx != m_items.size());
assert(m_items[idx].extents[0].data.size() >= data.size()); // TODO
memcpy(m_items[idx].extents[0].data.data(), data.data(), data.size());

uint64_t data_start = 0;
for (auto& extent : m_items[idx].extents) {
if (output_offset >= extent.data.size()) {
output_offset -= extent.data.size();
}
else {
uint64_t write_n = std::min(extent.data.size() - output_offset,
data.size() - data_start);
assert(write_n > 0);

memcpy(extent.data.data() + output_offset, data.data() + data_start, write_n);

data_start += write_n;
output_offset = 0;
}

if (data_start == data.size()) {
break;
}
}

return Error::Ok;
}
Expand Down
2 changes: 1 addition & 1 deletion libheif/box.h
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ class Box_iloc : public FullBox
uint8_t construction_method = 0);

Error replace_data(heif_item_id item_ID,
uint64_t offset,
uint64_t output_offset,
const std::vector<uint8_t>& data,
uint8_t construction_method);

Expand Down
2 changes: 1 addition & 1 deletion libheif/codecs/image_item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
#include <cstring>

#if WITH_UNCOMPRESSED_CODEC
#include <codecs/uncompressed_image.h>
#include "codecs/uncompressed/unc_image.h"
#endif


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@

#include "libheif/heif.h"
#include "security_limits.h"
#include "uncompressed.h"
#include "uncompressed_box.h"
#include "unc_types.h"
#include "unc_boxes.h"


/**
Expand Down Expand Up @@ -326,6 +326,7 @@ std::string Box_uncC::dump(Indent& indent) const
return sstr.str();
}


Error Box_uncC::write(StreamWriter& writer) const
{
size_t box_start = reserve_box_header_space(writer);
Expand Down Expand Up @@ -366,6 +367,41 @@ Error Box_uncC::write(StreamWriter& writer) const
}


uint64_t Box_uncC::compute_tile_data_size_bytes(uint32_t tile_width, uint32_t tile_height) const
{
if (m_profile != 0) {
switch (m_profile) {
case fourcc("rgba"):
return 4 * tile_width * tile_height;

case fourcc("rgb3"):
return 3 * tile_width * tile_height;

default:
assert(false);
return 0;
}
}

switch (m_interleave_type) {
case interleave_mode_component:
case interleave_mode_pixel: {
uint32_t bytes_per_pixel = 0;

for (const auto& comp : m_components) {
assert(comp.component_bit_depth % 8 == 0); // TODO: component sizes that are no multiples of bytes
bytes_per_pixel += comp.component_bit_depth / 8;
}

return bytes_per_pixel * tile_width * tile_height;
}
default:
assert(false);
return 0;
}
}


Error Box_cmpC::parse(BitstreamRange& range)
{
parse_full_box_header(range);
Expand All @@ -374,8 +410,8 @@ Error Box_cmpC::parse(BitstreamRange& range)
return unsupported_version_error("cmpC");
}

compression_type = range.read32();
compressed_unit_type = range.read8();
m_compression_type = range.read32();
m_compressed_unit_type = range.read8();
return range.get_error();
}

Expand All @@ -384,17 +420,17 @@ std::string Box_cmpC::dump(Indent& indent) const
{
std::ostringstream sstr;
sstr << Box::dump(indent);
sstr << indent << "compression_type: " << to_fourcc(compression_type) << "\n";
sstr << indent << "compressed_entity_type: " << (int)compressed_unit_type << "\n";
sstr << indent << "compression_type: " << to_fourcc(m_compression_type) << "\n";
sstr << indent << "compressed_entity_type: " << (int)m_compressed_unit_type << "\n";
return sstr.str();
}

Error Box_cmpC::write(StreamWriter& writer) const
{
size_t box_start = reserve_box_header_space(writer);

writer.write32(compression_type);
writer.write8(compressed_unit_type);
writer.write32(m_compression_type);
writer.write8(m_compressed_unit_type);

prepend_header(writer, box_start);

Expand Down
Loading

0 comments on commit 4230cf4

Please sign in to comment.