libheif icon indicating copy to clipboard operation
libheif copied to clipboard

Default color space should be set to BT.709, otherwise save incorrect colors.

Open XPRAMT opened this issue 5 months ago • 14 comments

When no color space is specified, libheif uses BT.601 as the default color space instead of BT.709, which causes most programs that rely on libheif to save images with incorrect colors.

Error (libheif default) Image

Correct Image

XPRAMT avatar Jul 14 '25 09:07 XPRAMT

We use these defaults

profile->color_primaries = heif_color_primaries_ITU_R_BT_709_5; // 1
profile->transfer_characteristics = heif_transfer_characteristic_IEC_61966_2_1; // 13
profile->matrix_coefficients = heif_matrix_coefficients_ITU_R_BT_601_6; // 6
profile->full_range_flag = true;

because in the past this gave the best compatibility, especially for images converted from JPEG.

~I think that it is not defined what the color profile should be when there are no values transmitted in the HEIF. If I missed that, could you please point me to the specification of the defaults?~

farindk avatar Jul 14 '25 09:07 farindk

For sRGB images, the current profile results in noticeable color shifts (when opened in Photoshop).

profile->color_primaries = heif_color_primaries_ITU_R_BT_709_5; // 1
profile->transfer_characteristics = heif_transfer_characteristic_IEC_61966_2_1; // 13
profile->matrix_coefficients = heif_matrix_coefficients_ITU_R_BT_601_6; // 6
profile->full_range_flag = true;

Image

However, using

--matrix_coefficients 1
--colour_primaries 1
--transfer_characteristic 1
--full_range_flag 1

does not produce any observable color changes.

Image

XPRAMT avatar Jul 14 '25 10:07 XPRAMT

Given your last comment, it sounds to me that this is actually a Photoshop bug and Photoshop does not correctly read the default nclx combination that libheif uses (1 / 13 / 6).

farindk avatar Jul 14 '25 10:07 farindk

Maybe you could tell me which programs can correctly read the color information.

windows 11 Photos app Image

PictureFlect Image

XPRAMT avatar Jul 14 '25 10:07 XPRAMT

Maybe they all use the same Windows API for that? Could you attach the input JPEG file? I will then try on other systems, like macOS.

farindk avatar Jul 14 '25 10:07 farindk

A test.zip

XPRAMT avatar Jul 14 '25 10:07 XPRAMT

Thank you. I tried your images on macOS Preview. They all look similar. The same for Linux (but that is obvious since it also uses libheif).

Thus, I still think that this is a flaw in the Windows implementation.

Of course, I could change the default color profile to (1 / 1 / 1) in libheif to work around that, but it means that during the conversion of JPEG to HEIC, it will always do a (lossy) color space conversion. The idea of the current default values was to match the JPEG default, so that no color conversion is needed.

farindk avatar Jul 14 '25 10:07 farindk

You're right — I tested on Android and the colors are correct. It seems to be a Windows-specific issue, possibly related to this component https://apps.microsoft.com/detail/9pmmsr1cgpwg

Thanks for your help today

XPRAMT avatar Jul 14 '25 11:07 XPRAMT

I looked into the relevant information, and these parameters might provide more consistent color display across different systems.

--matrix_coefficients 1
--colour_primaries 1
--transfer_characteristic 13
--full_range_flag 1

XPRAMT avatar Jul 14 '25 11:07 XPRAMT

Maybe one solution would be to have a colorprofile-preset option that is easier for the user to set than the four technical parameters. Something like colorprofile-preset=jpeg for the current default or colorprofile-preset=compatible to try covering as many systems as possible.

farindk avatar Jul 14 '25 12:07 farindk

It seems like a good approach. Thanks again for your help

XPRAMT avatar Jul 14 '25 12:07 XPRAMT

If we're open to revisiting this, then maybe if the input is supplied as YUV, use 601 as a default, if it's RGB, use 709, and if it's 10-bit anything, use 2020nc. On the assumption that if they're passing in raw YUV yet not bothering to check the matrix, there's a good chance it's a low-level direct conversion from JPEG. But if it's already been round-tripped to RGB, then it's already lossy, might as well go with widely compatible. For every other source of RGB data, 709 is slightly higher quality and apparently more compatible.

I don't know how easy it would be to wait for that information before defining the colorspace, though.

Very disappointed that it's 2025 and readers are still ignoring this, but that's life.

silverbacknet avatar Jul 15 '25 12:07 silverbacknet

@silverbacknet Good idea. It might be that it is a bit non-predictable for the user, but if we introduce a colorprofile-preset=auto for this, it should be fine.

farindk avatar Jul 15 '25 13:07 farindk

With the above PR, you should be able to use --color-profile=compatible on heif-enc to get a profile setting that works everywhere. Otherwise, --color-profile=auto might be the best setting. I cannot change the default value (custom) for backwards compatibility.

farindk avatar Jul 19 '25 13:07 farindk