Repository navigation
YCbCr images >14 bpp can no longer be converted to RGB (regression in 1.21.0, e9b3f68d)Â #1881
Description
Summary
Since 1.21.0, any YCbCr image with more than 14 bits per pixel fails to decode to
RGB with Unsupported feature: Unsupported color conversion. Decoding to YUV
output still works â only the conversion to RGB is affected, which is the path
every viewer, thumbnailer and heif-dec ... .png uses.
Two files in libheif's own test corpus reproduce it:
tests/data/uncompressed_comp_Y16U16V16_422.heiftests/data/uncompressed_mix_Y16U16V16_422.heif
Neither carries an nclx box, so matrix_coefficients is the default
(unspecified / BT.601) â these are ordinary 16-bit YCbCr 4:2:2 images, nothing
exotic.
Reproduction
$ heif-dec tests/data/uncompressed_comp_Y16U16V16_422.heif out.png
File contains 1 image
Could not decode image: Unsupported feature: Unsupported color conversion
$ heif-dec tests/data/uncompressed_comp_Y16U16V16_422.heif out.y4m
File contains 1 image
Written to out.y4m # YUV output is fine
heif-info reports the image as colorspace: YCbCr, 4:2:2, bit depth: 16,
color profile: no.
Affected versions
Bad: 1.21.0, 1.21.1, 1.21.2, 1.22.0, 1.22.1, 1.22.2, 1.23.0, 1.23.1, and current
master (1a3583b).
Good: 1.20.2 and earlier.
Cause
git bisect between v1.20.2 and v1.21.2 lands on:
e9b3f68d4eeae3ddbbca65e56c7355a96d4bf850
"limit color conversion function 14 bpp (#1572)"
The entire change is four lines in libheif/color-conversion/yuv2rgb.cc, in
Op_YCbCr_to_RGB<Pixel>::state_after_conversion:
if (input_state.bits_per_pixel > 14) {
return {};
}Returning an empty state list removes this operation from the conversion graph,
so the pipeline can find no route from YCbCr to RGB and fails.
The commit landed alongside 86f09c7d ("add (incomplete) implementation of
YCgCo-R color transformation"), both from issue #1572. YCgCo-R needs bit-depth
headroom â Cg and Co each require an extra bit â so a cap is understandable
for that transform. But the check is unconditional: it does not look at
matrix_coefficients, so it also rejects plain BT.601/BT.709 YCbCr at 15 and 16
bpp, which needs no headroom and worked fine before.
Why it went unnoticed for three releases
The test suite never converts a >14 bpp YCbCr image to RGB. tests/uncompressed_decode.cc
checks either 8-bit RGB output or native YCbCr output, and the two 16-bit 4:2:2
fixtures above are not referenced by any test that exercises the RGB path.
Suggested fix
Restrict the cap to the transforms that actually need the headroom, e.g.
// YCgCo-R needs 2 bits of headroom; other matrices do not
int matrix = input_state.nclx.get_matrix_coefficients();
if ((matrix == 8 || matrix == 16 || matrix == 17) &&
input_state.bits_per_pixel > 14) {
return {};
}and add a regression test that decodes one of the 16-bit 4:2:2 fixtures to RGB.
One caveat: I have confirmed that these files decoded to RGB successfully in
1.20.2 and fail from 1.21.0 on, but I have not audited the conversion arithmetic
for numerical correctness at 15/16 bpp. If the limit turns out to be needed more
broadly than YCgCo-R, it would still be better to surface it as an explicit,
documented limitation than as a generic "unsupported color conversion" failure.
Activity
restrict the 14 bpp YCbCr to RGB conversion limit to YCgCo-Re (#1881)
add regression tests for RGB conversion of 16 bit YCbCr images (#1881)
farindk commentedon Aug 31, 2026
Thanks. Fixed with the above commit.