diff --git a/libheif/plugins/encoder_kvazaar.cc b/libheif/plugins/encoder_kvazaar.cc index a32886b926..9db79a6c2d 100644 --- a/libheif/plugins/encoder_kvazaar.cc +++ b/libheif/plugins/encoder_kvazaar.cc @@ -348,14 +348,17 @@ static void append_chunk_data(kvz_data_chunk* data, std::vector& out) } -static void copy_plane(kvz_pixel* out_p, uint32_t out_stride, const uint8_t* in_p, uint32_t in_stride, int w, int h, int padded_width, int padded_height) +static void copy_plane(kvz_pixel* out_p, uint32_t out_stride, const uint8_t* in_p, uint32_t in_stride, int w, int h, int padded_width, int padded_height, + int bit_depth) { + int bpp = (bit_depth > 8) ? 2 : 1; + for (int y = 0; y < padded_height; y++) { int sy = std::min(y, h - 1); // source y - memcpy(out_p + y * out_stride, in_p + sy * in_stride, w); + memcpy(out_p + y * out_stride, in_p + sy * in_stride, w * bpp); if (padded_width > w) { - memset(out_p + y * out_stride + w, *(in_p + sy * in_stride + w - 1), padded_width - w); + memset(out_p + y * out_stride + w, *(in_p + sy * in_stride + w - 1), (padded_width - w) * bpp); } } } @@ -372,9 +375,22 @@ static struct heif_error kvazaar_encode_image(void* encoder_raw, const struct he struct encoder_struct_kvazaar* encoder = (struct encoder_struct_kvazaar*) encoder_raw; int bit_depth = heif_image_get_bits_per_pixel_range(image, heif_channel_Y); + int bit_depth_chroma = 0; bool isGreyscale = (heif_image_get_colorspace(image) == heif_colorspace_monochrome); heif_chroma chroma = heif_image_get_chroma_format(image); + if (!isGreyscale) { + bit_depth_chroma = heif_image_get_bits_per_pixel_range(image, heif_channel_Cb); + if (bit_depth != bit_depth_chroma) { + struct heif_error err = { + heif_error_Encoder_plugin_error, + heif_suberror_Unsupported_bit_depth, + "Luma bit depth must equal the chroma bit depth" + }; + return err; + } + } + // Kvazaar uses a hard-coded bit depth (https://github.com/ultravideo/kvazaar/issues/399). // Check whether this matches to the image bit depth. // TODO: we should check the bit depth supported by the encoder (like query_input_colorspace2()) and output a warning @@ -588,22 +604,22 @@ static struct heif_error kvazaar_encode_image(void* encoder_raw, const struct he int stride; const uint8_t* data = heif_image_get_plane_readonly(image, heif_channel_Y, &stride); - copy_plane(pic->y, pic->stride, data, stride, input_width, input_height, encoded_width, encoded_height); + copy_plane(pic->y, pic->stride, data, stride, input_width, input_height, encoded_width, encoded_height, bit_depth); } else { int stride; const uint8_t* data; data = heif_image_get_plane_readonly(image, heif_channel_Y, &stride); - copy_plane(pic->y, pic->stride, data, stride, input_width, input_height, encoded_width, encoded_height); + copy_plane(pic->y, pic->stride, data, stride, input_width, input_height, encoded_width, encoded_height, bit_depth); data = heif_image_get_plane_readonly(image, heif_channel_Cb, &stride); copy_plane(pic->u, pic->stride >> chroma_stride_shift, data, stride, input_chroma_width, input_chroma_height, - encoded_width >> chroma_stride_shift, encoded_height >> chroma_height_shift); + encoded_width >> chroma_stride_shift, encoded_height >> chroma_height_shift, bit_depth_chroma); data = heif_image_get_plane_readonly(image, heif_channel_Cr, &stride); copy_plane(pic->v, pic->stride >> chroma_stride_shift, data, stride, input_chroma_width, input_chroma_height, - encoded_width >> chroma_stride_shift, encoded_height >> chroma_height_shift); + encoded_width >> chroma_stride_shift, encoded_height >> chroma_height_shift, bit_depth_chroma); } auto uencoder = make_guard(api->encoder_open(config), [api](kvz_encoder* e) { api->encoder_close(e); });