Skip to content

Commit

Permalink
encode AVIF images with <16 pixels size as 16x16 with cropping (#311)
Browse files Browse the repository at this point in the history
  • Loading branch information
farindk committed Sep 21, 2020
1 parent 421c50f commit b22820a
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 87 deletions.
15 changes: 15 additions & 0 deletions libheif/heif_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2042,6 +2042,21 @@ Error HeifContext::Image::encode_image_as_av1(std::shared_ptr<HeifPixelImage> im
height = image->get_height();
m_heif_context->m_heif_file->add_ispe_property(m_id, width, height);


if (encoder->plugin->plugin_api_version >= 3) {
uint32_t encoded_width, encoded_height;

encoder->plugin->query_encoded_size(encoder->encoder,
m_width, m_height,
&encoded_width,
&encoded_height);
if (m_width != encoded_width ||
m_height != encoded_height) {
m_heif_context->m_heif_file->add_clap_property(m_id, m_width, m_height,
encoded_width, encoded_height);;
}
}

return Error::Ok;
}

Expand Down
46 changes: 38 additions & 8 deletions libheif/heif_encoder_aom.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct encoder_struct_aom
bool data_read = false;
};

static const char* kError_out_of_memory = "Out of memory";

static const char* kParam_min_q = "min-q";
static const char* kParam_max_q = "max-q";
Expand Down Expand Up @@ -472,6 +473,14 @@ void aom_query_input_colorspace2(void* encoder_raw, heif_colorspace* colorspace,
}


void aom_query_encoded_size(void* encoder, uint32_t input_width, uint32_t input_height,
uint32_t* encoded_width, uint32_t* encoded_height)
{
*encoded_width = std::max(input_width, 16U);
*encoded_height = std::max(input_height, 16U);
}


// TODO: encode as still frame (seq header)
static int encode_frame(aom_codec_ctx_t* codec, aom_image_t* img)
{
Expand All @@ -496,6 +505,26 @@ struct heif_error aom_encode_image(void* encoder_raw, const struct heif_image* i
{
struct encoder_struct_aom* encoder = (struct encoder_struct_aom*) encoder_raw;

// --- round image size to minimum size

uint32_t rounded_width, rounded_height;
aom_query_encoded_size(encoder,
image->image->get_width(),
image->image->get_height(),
&rounded_width,
&rounded_height);

bool success = image->image->extend_to_size(rounded_width, rounded_height);
if (!success) {
struct heif_error err = {
heif_error_Memory_allocation_error,
heif_suberror_Unspecified,
kError_out_of_memory
};
return err;
}


const int source_width = heif_image_get_width(image, heif_channel_Y);
const int source_height = heif_image_get_height(image, heif_channel_Y);

Expand Down Expand Up @@ -543,13 +572,13 @@ struct heif_error aom_encode_image(void* encoder_raw, const struct heif_image* i
const int stride = input_image.stride[plane];

if (chroma == heif_chroma_monochrome && plane != 0) {
if (bpp_y==8) {
if (bpp_y == 8) {
memset(buf, 128, source_height * stride);
}
else {
uint16_t* buf16 = (uint16_t*)buf;
uint16_t half_range = (uint16_t)(1<<(bpp_y-1));
for (int i=0;i<source_height * stride/2;i++) {
uint16_t* buf16 = (uint16_t*) buf;
uint16_t half_range = (uint16_t) (1 << (bpp_y - 1));
for (int i = 0; i < source_height * stride / 2; i++) {
buf16[i] = half_range;
}
}
Expand All @@ -573,8 +602,8 @@ struct heif_error aom_encode_image(void* encoder_raw, const struct heif_image* i
if (chroma != heif_chroma_444) { w = (w + 1) / 2; }
if (chroma == heif_chroma_420) { h = (h + 1) / 2; }

assert(w == heif_image_get_width(image, (heif_channel)plane));
assert(h == heif_image_get_height(image, (heif_channel)plane));
assert(w == heif_image_get_width(image, (heif_channel) plane));
assert(h == heif_image_get_height(image, (heif_channel) plane));
}

if (bpp_y > 8) {
Expand Down Expand Up @@ -752,7 +781,7 @@ struct heif_error aom_get_compressed_data(void* encoder_raw, uint8_t** data, int

static const struct heif_encoder_plugin encoder_plugin_aom
{
/* plugin_api_version */ 2,
/* plugin_api_version */ 3,
/* compression_format */ heif_compression_AV1,
/* id_name */ "aom",
/* priority */ AOM_PLUGIN_PRIORITY,
Expand All @@ -779,7 +808,8 @@ static const struct heif_encoder_plugin encoder_plugin_aom
/* query_input_colorspace */ aom_query_input_colorspace,
/* encode_image */ aom_encode_image,
/* get_compressed_data */ aom_get_compressed_data,
/* query_input_colorspace (v2) */ aom_query_input_colorspace2
/* query_input_colorspace (v2) */ aom_query_input_colorspace2,
/* query_encoded_size (v3) */ aom_query_encoded_size
};

const struct heif_encoder_plugin* get_encoder_plugin_aom()
Expand Down
40 changes: 35 additions & 5 deletions libheif/heif_encoder_rav1e.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ struct encoder_struct_rav1e
bool data_read = false;
};

static const char* kError_out_of_memory = "Out of memory";

static const char* kParam_min_q = "min-q";
static const char* kParam_threads = "threads";
Expand Down Expand Up @@ -475,11 +476,39 @@ void rav1e_query_input_colorspace2(void* encoder_raw, heif_colorspace* colorspac
}


void rav1e_query_encoded_size(void* encoder, uint32_t input_width, uint32_t input_height,
uint32_t* encoded_width, uint32_t* encoded_height)
{
*encoded_width = std::max(input_width, 16U);
*encoded_height = std::max(input_height, 16U);
}


struct heif_error rav1e_encode_image(void* encoder_raw, const struct heif_image* image,
heif_image_input_class input_class)
{
auto* encoder = (struct encoder_struct_rav1e*) encoder_raw;

// --- round image size to minimum size

uint32_t rounded_width, rounded_height;
rav1e_query_encoded_size(encoder,
image->image->get_width(),
image->image->get_height(),
&rounded_width,
&rounded_height);

bool success = image->image->extend_to_size(rounded_width, rounded_height);
if (!success) {
struct heif_error err = {
heif_error_Memory_allocation_error,
heif_suberror_Unspecified,
kError_out_of_memory
};
return err;
}


const heif_chroma chroma = heif_image_get_chroma_format(image);

uint8_t yShift = 0;
Expand Down Expand Up @@ -539,9 +568,9 @@ struct heif_error rav1e_encode_image(void* encoder_raw, const struct heif_image*
(input_class == heif_image_input_class_normal ||
input_class == heif_image_input_class_thumbnail)) {
if (rav1e_config_set_color_description(rav1eConfig.get(),
(RaMatrixCoefficients)nclx->get_matrix_coefficients(),
(RaColorPrimaries)nclx->get_colour_primaries(),
(RaTransferCharacteristics)nclx->get_transfer_characteristics()) == -1) {
(RaMatrixCoefficients) nclx->get_matrix_coefficients(),
(RaColorPrimaries) nclx->get_colour_primaries(),
(RaTransferCharacteristics) nclx->get_transfer_characteristics()) == -1) {
return heif_error_codec_library_error;
}
}
Expand Down Expand Up @@ -662,7 +691,7 @@ struct heif_error rav1e_get_compressed_data(void* encoder_raw, uint8_t** data, i

static const struct heif_encoder_plugin encoder_plugin_rav1e
{
/* plugin_api_version */ 2,
/* plugin_api_version */ 3,
/* compression_format */ heif_compression_AV1,
/* id_name */ "rav1e",
/* priority */ RAV1E_PLUGIN_PRIORITY,
Expand All @@ -689,7 +718,8 @@ static const struct heif_encoder_plugin encoder_plugin_rav1e
/* query_input_colorspace */ rav1e_query_input_colorspace,
/* encode_image */ rav1e_encode_image,
/* get_compressed_data */ rav1e_get_compressed_data,
/* query_input_colorspace (v2) */ rav1e_query_input_colorspace2
/* query_input_colorspace (v2) */ rav1e_query_input_colorspace2,
/* query_encoded_size (v3) */ rav1e_query_encoded_size
};

const struct heif_encoder_plugin* get_encoder_plugin_rav1e()
Expand Down
15 changes: 12 additions & 3 deletions libheif/heif_encoder_x265.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ extern "C" {
}


const char* kError_unsupported_bit_depth = "Bit depth not supported by x265";
const char* kError_unsupported_image_size = "Images smaller than 16 pixels are not supported";
static const char* kError_unsupported_bit_depth = "Bit depth not supported by x265";
static const char* kError_unsupported_image_size = "Images smaller than 16 pixels are not supported";
static const char* kError_out_of_memory = "Out of memory";


enum parameter_type
Expand Down Expand Up @@ -862,7 +863,15 @@ static struct heif_error x265_encode_image(void* encoder_raw, const struct heif_
param->sourceWidth = rounded_size(param->sourceWidth);
param->sourceHeight = rounded_size(param->sourceHeight);

image->image->extend_to_aligned_border();
bool success = image->image->extend_to_size(param->sourceWidth, param->sourceHeight);
if (!success) {
struct heif_error err = {
heif_error_Memory_allocation_error,
heif_suberror_Unspecified,
kError_out_of_memory
};
return err;
}

x265_picture* pic = api->picture_alloc();
api->picture_init(param, pic);
Expand Down
Loading

0 comments on commit b22820a

Please sign in to comment.