-
Notifications
You must be signed in to change notification settings - Fork 679
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-color-4] extend rgb() for HDR #3249
Comments
What does a negative value mean here? You aren't intending to imply the existence of a display that can suck light in as well as emitting it? |
You would think this would at least give a wider color gamut (WCG) (and indeed, I used to argue so) but in fact, no, it doesn't for several reasons. Firstly, the transfer curve is undefined outside the 0% to 100% range. But okay, this can be dealt with in various ways (and you suggest several). Secondly, having done so, there are still colors inside the Lab surface gamut - or even, inside the Rec.2020 gamut - which are unrepresentable in an extended but gamma-encoded sRGB colorspace. Basically the curve flattens off too much. OK so thirdly, one could use a linearized, extended sRGB space. But then, the advantage of sticking with sRGB for familiarity becomes even less and the precision required (16bit, or half float) is greater. Lastly, existing color management systems still tend to either clip to 0-100%, or are poorly tested beyond those limits. The correct way to encode a wider color gamut is to use a wider gamut colorspace (like P3, or 2020, or Lab) and existing color management systems will handle that just fine. That is the approach taken in CSS Color 4. The correct way to handle high dynamic range (HDR) is to use a transfer function designed to cope with the much larger dynamic range, such as PQ or HLG, plus enough bits per component to encode it (and usually, a WCG colorspace as well). |
Nothing of the sort. But once a colorspace is linearized (and thus, is additive), and assuming sufficient precision is available, it can be shown that any 3-component colorspace can be transformed into another one by a simple matrix multiplication. If the destination colorspace has a smaller gamut, then some values may be greater than 100% or less than 0%. So to summarize the issue - extending below 0% and above 100% seems like it might work, and can work in a theoretical context with linearized (non gamma corrected) colorspaces and high precision; but is not a good way forward and is better handled in other ways. Primarily, by using a wider color gamut (like the P3 gamut used on many Apple, Samsung, Dell and HP devices and by digital cinema projectors; or the Rec.2020 system used by broadcast television and movie studios). |
Saying that this is "not a good way forward" seems highly subjective, and a bit odd since this is already how Chrome, Microsoft Windows, Apple and many games actually implement HDR. Any system that deals with inputs in many color spaces is going to be using some representation that can contain all of them internally, and using extended sRGB with half-floats, either in linear or non-linear form is exactly that. Having implemented both color management and HDR in chrome, I find it much easier to work with extended sRGB than lots of different color spaces. Extended sRGB is also entirely backwards compatible, which makes it easy to mix legacy and HDR content. Pointing out that additional precision is needed seems redundant when I already suggested that floating-point values should be allowed. Additional precision is required to implement HDR, regardless of what color space is chosen, so that point seems moot. How would you guys suggest that a color like rgb(688.17, 688.17, 688.17) (which is 10x brighter than rgb(255,255,255) in my proposed scheme) should be written? |
This proposal -- extending the sRGB color space to cover the range -infty to infty in a way that is well-defined and as-un-surprising-as-possible -- is consistent with what canvas is aiming to do to support both Wide Color Gamut (WCG) and and High Dynamic Range (HDR). I'm not sure if the canvas docs have been updated to this effect, but that is the plan (which had wide buy-in last time it was discussed in person). Note that this is also consistent with CoreGraphics' kCGColorSpaceExtendedSRGB |
@svgeesus can this issue be re-considered given @ccameron-chromium comment above and usage in various platforms (inc. Windows and Apple APIs) as @profezzorn pointed out? |
Sure, I am re-opening it. I'm aware that canvas will use a half-float linear sRGB space and certainly, CSS could use that too; but for clarity and backwards compatibility, not mixed up with the existing rgb() or hex syntax which indicates a gamma-corrected space. |
IIUC canvas will not use linear sRGB space. Rather, it will use the extended-sRGB transfer function. This is much better for adoption and compatibility, and has less surprise. With a linear-transfer-function space for canvas, adding WCG or HDR support requires a full application. With extended-sRGB-transfer-function space, WCG and HDR can be added with no side-effects. |
The proposals for extending Canvas to a half-float, extended-sRGB wide color gamut are:
Note that these currently add WCG and extended bit depth (half float) but do not add HDR support. |
These canvas proposals seem to be stagnating, with un-answered review comments. |
Updating this ol issue to account for recent changes:
Closing (again) as accepted. |
We should extend rgb() and rgba() to accept values outside of 0-255, and values outside of 0-100%. This would allow you to specify colors outside of the sRGB gamut using extended sRGB.
In order to get sufficient precision for some colors, we should also allow floating-point values, with the assumption that the decimals may be ignored on some platforms.
It's worth noting that it's not easy to extend hsl() in the same way, since the definition of hsl() automatically keeps all values within the RGB cube.
Here is a description of how extended sRGB works:
Extended sRGB
So what does it mean to specify rgb(510, 510, -100) ? While 510 is twice as much as 255, it doesn’t actually mean “twice as much red” or “twice as much blue”. To understand we first look at the sRGB transfer function:
Normally, sRGB only uses x values between 0 and 1, but it’s easy to see that the function can handle any value greater than zero. Negative values is a little trickier, but we can get around that by mirroring the srgb function into the negative range. This gives us the extended sRGB (xsRGB) function:
Now we can easily compute that xsRGB2Linear(511/255) = 4.97, or nearly 5x brighter than the value 255.
For -100, the RGB the transfer function gives us:
xsRGB2Linear(-100/255) = -xsRGB2Linear(100/255) = -0.1274
The text was updated successfully, but these errors were encountered: