Default color space should be set to BT.709, otherwise save incorrect colors.
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)
Correct
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?~
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;
However, using
--matrix_coefficients 1
--colour_primaries 1
--transfer_characteristic 1
--full_range_flag 1
does not produce any observable color changes.
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).
Maybe you could tell me which programs can correctly read the color information.
windows 11 Photos app
PictureFlect
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.
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.
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
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
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.
It seems like a good approach. Thanks again for your help
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 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.
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.