diff --git a/libheif/color-conversion/hdr_sdr.cc b/libheif/color-conversion/hdr_sdr.cc index 7a287ec3a8..b82260ce9c 100644 --- a/libheif/color-conversion/hdr_sdr.cc +++ b/libheif/color-conversion/hdr_sdr.cc @@ -182,8 +182,27 @@ Op_to_sdr_planes::convert_colorspace(const std::shared_ptr int in = p_in[y * stride_in + x]; p_out[y * stride_out + x] = (uint8_t) (in >> shift); // TODO: I think no rounding here, but am not sure. } - } - else { + } else if (input_bits < 8) { + int width = input->get_width(channel); + int height = input->get_height(channel); + if (!outimg->add_plane(channel, width, height, 8)) { + return nullptr; + } + + int shift = 8 - input_bits; + + int stride_in; + const uint8_t* p_in = input->get_plane(channel, &stride_in); + + int stride_out; + uint8_t* p_out = outimg->get_plane(channel, &stride_out); + + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) { + int in = p_in[y * stride_in + x]; + p_out[y * stride_out + x] = (uint8_t) (in << shift); // TODO: I think no rounding here, but am not sure. + } + } else { outimg->copy_new_plane_from(input, channel, channel); } } diff --git a/libheif/pixelimage.cc b/libheif/pixelimage.cc index 480b344a11..9fd69366d7 100644 --- a/libheif/pixelimage.cc +++ b/libheif/pixelimage.cc @@ -417,7 +417,7 @@ void HeifPixelImage::fill_new_plane(heif_channel dst_channel, uint16_t value, in int num_interleaved = num_interleaved_pixels_per_plane(m_chroma); - if (bpp == 8) { + if (bpp <= 8) { uint8_t* dst; int dst_stride = 0; dst = get_plane(dst_channel, &dst_stride); diff --git a/tests/conversion.cc b/tests/conversion.cc index 4c028c8029..678afd4dde 100644 --- a/tests/conversion.cc +++ b/tests/conversion.cc @@ -615,6 +615,7 @@ static void fill_plane(std::shared_ptr& img, heif_channel channe static void assert_plane(std::shared_ptr& img, heif_channel channel, const std::vector& pixels) { + INFO("channel: " << channel); int w = img->get_width(channel); int h = img->get_height(channel); @@ -622,7 +623,9 @@ static void assert_plane(std::shared_ptr& img, heif_channel chan uint8_t* p = img->get_plane(channel, &stride); for (int y = 0; y < h; y++) { + INFO("row: " << y); for (int x = 0; x < w; x++) { + INFO("column: " << x); REQUIRE((int)p[y * stride + x] == (int)pixels[y * w + x]); } } @@ -665,3 +668,37 @@ TEST_CASE("Bilinear upsampling", "[heif_image]") 50, 38, 13, 0 }); } + +TEST_CASE("RGB 5-6-5 to RGB") +{ + heif_color_conversion_options options = {}; + + std::shared_ptr img = std::make_shared(); + const int width = 3; + const int height = 2; + img->create(width, height, heif_colorspace_RGB, heif_chroma_444); + img->add_plane(heif_channel_R, width, height, 5); + REQUIRE(img->get_bits_per_pixel(heif_channel_R) == 5); + img->add_plane(heif_channel_G, width, height, 6); + REQUIRE(img->get_bits_per_pixel(heif_channel_G) == 6); + img->add_plane(heif_channel_B, width, height, 5); + REQUIRE(img->get_bits_per_pixel(heif_channel_B) == 5); + + uint8_t v = 1; + for (heif_channel plane: {heif_channel_R, heif_channel_G, heif_channel_B}) { + int dst_stride = 0; + uint8_t *dst = img->get_plane(plane, &dst_stride); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + dst[y * dst_stride + x] = v; + v += 1; + } + } + } + + std::shared_ptr out = convert_colorspace(img, heif_colorspace_RGB, heif_chroma_444, nullptr, 8, options); + + assert_plane(out, heif_channel_R, {8, 16, 24, 32, 40, 48}); + assert_plane(out, heif_channel_G, {28, 32, 36, 40, 44, 48}); + assert_plane(out, heif_channel_B, {104, 112, 120, 128, 136, 144}); +}