Skip to content
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] Expose Linear-light sRGB as CSS syntax? #6087

Closed
samweinig opened this issue Mar 8, 2021 · 16 comments
Closed

[css-color-4] Expose Linear-light sRGB as CSS syntax? #6087

samweinig opened this issue Mar 8, 2021 · 16 comments
Assignees
Labels
css-color-4 Current Work

Comments

@samweinig
Copy link

samweinig commented Mar 8, 2021

Edit 11 Oct 2021 by @svgeesus : much of this issue is now solved, see here for the remaining question. Issue title updated.


CSS Color 4 currently defines the following "RGB-ish" (meaning, using rgb channels, a transfer function to linear, and linear transform to XYZ) color spaces: 'srgb', 'display-p3', 'a98-rgb', 'prophoto-rgb', 'rec2020'.

In some use cases, it can be useful to have variants of these that are "linear" (meaning, the transfer function is unapplied), "extended" (meaning they are not bounded from 0.0 - 1.0, but rather can extended to Inf in either the positive or negative direction) or "linear and extended" (meaning a combination of the both).

While we certainly could specify the full matrix of all combinations of color spaces with these characteristics, for instance:

srgb
linear-srgb
extended-srgb
linear-extended-srgb

display-p3
linear-display-p3
extended-display-p3
linear-extended-display-p3

(etc, etc...)

An alternate formulation might be to offer CSS functions to transform the color spaces, offering linearize(), extended() functions, so the above could be described as:

srgb -> srgb
linear-srgb -> linearize(srgb)
extended-srgb -> extended(srgb)
linear-extended-srgb -> linearize(extended(srgb)) or extended(linearize(srgb))

display-p3 -> display-p3
linear-display-p3 -> linearize(display-p3)
extended-display-p3 -> extended(display-p3)
linear-extended-display-p3 -> linearize(extended(display-p3)) or extended(linearize(display-p3))

(etc, etc...)

As existing precedent, CoreGraphics, the library used on Apple's platforms for graphics, exposes functions to transform these RGB-ish colorspaces to their "linear", "extended", and "linear and extended" variants via the following functions:

/* Create a linearized copy of the color space if the color space is matrix based.
   Return NULL if otherwise */
CG_EXTERN CGColorSpaceRef  __nullable CGColorSpaceCreateLinearized(CGColorSpaceRef space)
CG_AVAILABLE_STARTING(11.0, 14.0);

/* Create a copy of the color space which uses extended range [-Inf, +Inf] if the color space is
   matrix based. Return NULL if otherwise */
CG_EXTERN CGColorSpaceRef  __nullable CGColorSpaceCreateExtended(CGColorSpaceRef space)
CG_AVAILABLE_STARTING(11.0, 14.0);

/* Create a linearized copy of the color space which uses extended range [-Inf, +Inf]
   if the color space is matrix based. Return NULL if otherwise */
CG_EXTERN CGColorSpaceRef  __nullable CGColorSpaceCreateExtendedLinearized(CGColorSpaceRef space)
CG_AVAILABLE_STARTING(11.0, 14.0);
@svgeesus svgeesus self-assigned this Mar 8, 2021
@svgeesus svgeesus added the css-color-4 Current Work label Mar 8, 2021
@svgeesus
Copy link
Contributor

svgeesus commented Mar 8, 2021

I'm aware of this requirement, Canvas for example wants to have this as they reference Color 4 for predefined colorspaces.

SVG also needed a stable reference for linear-light sRGB because this is what SVG Filters use by default (and the rest of SVG can also optionally use this). Which is why linear-light sRGB is in the list of defined and exported terms.

What wasn't clear to me though was whether to

  1. Expose this to CSS syntax, so you could use something like color(srgb-linear 0.2 0.5 0.9), or
  2. Expose the defined terms for other specifications to link to, but not make them available from CS syntax

In terms of extended vs. not, I think that is a separate issue and I am in process of changing all the transfer functions (EOTFs) to cover the full range, for non-linear-light ("gamma encoded", although that term is problematic spaces. It simply involves extending any linear portion near the origin, for the same distance in the negative; and then mirroring the curved portion.

The sample code has that change, I need to check all of them have been done. The transfer function part of the predefined colorspaces has not been done yet, but I will do so.

Specifications which reference these spaces and require clamped values are unaffected, because the clamping means they don't exercise that part of the EOTF; and everyone else gets it "for free" and it just works.

Linear-light versions get extended for free, because the EOTF is a straight line and extended it is still a straight line.

So I don't think there is a need to expose special -extended versions in CSS. Just make the regular ones extended.

On naming: I see the Canvas and WebGPU folks using things like srgb-linear while @samweinig used linear-srgb as an example. I have a slight preference for putting the colorspace first so that they group together in indexes of terms.

@svgeesus
Copy link
Contributor

svgeesus commented Mar 8, 2021

linear-extended-srgb -> linearize(extended(srgb)) or extended(linearize(srgb))

Note btw that the second of those does not produce the expected result. If sRGB values that are clamped to [0..1] are linearized, then extended, the results are still in [0..1].

@weinig
Copy link
Contributor

weinig commented Mar 24, 2021

linear-extended-srgb -> linearize(extended(srgb)) or extended(linearize(srgb))

Note btw that the second of those does not produce the expected result. If sRGB values that are clamped to [0..1] are linearized, then extended, the results are still in [0..1].

I meant that pseudo syntax to be transformations of the type, not transformations of a value, but yes, if doing that to a value, they would have different results.

@svgeesus
Copy link
Contributor

@weinig my key question is

So I don't think there is a need to expose special -extended versions in CSS. Just make the regular ones extended.

So the proposal would be to expose explicit *-linear versions to CSS syntax, but to make both the linear and the gamma-encoded versions extended by default and if you don't want extended, don't specify negative values.

Thoughts?

@weinig
Copy link
Contributor

weinig commented Mar 29, 2021

I am always a bit weary of compatibility when changing existing behavior, which this would be since we currently clamp, but sometimes that is the right call, as it is pretty unlikely people are using values greater than 1 or less than 0.

The more I think about it, the more reasonable that proposal seems to me, but I would be interested in hearing other voices on the matter.

(From an implementation perspective, this is very straightforward (it actually would allow us to remove some complexity if we could remove our bounded variants of the matrix-style RGB-ish colors (your, srgb, display-p3, a98rgb, prophoto, etc.)).

@LeaVerou
Copy link
Member

LeaVerou commented Apr 4, 2021

What about an extra linear keyword, that could go either before, or after the color space name? linear srgb is far easier to read than srgb-linear for example, and authors won't have to remember whether it precedes or follows.

@svgeesus
Copy link
Contributor

The sample code has that change, I need to check all of them have been done. The transfer function part of the predefined colorspaces has not been done yet, but I will do so.

That is all done now; all the transfer functions are defined over the extended range.

@svgeesus
Copy link
Contributor

svgeesus commented Sep 3, 2021

a) Linear-light versions

Currently, the term linear-light sRGB is defined in CSS Color 4, primarily to allow reference from other specifications such as SVG filters or Canvas. However, it isn't exposed as a color() colorspace. Should it be?

b) Extended versions

Currently, all the predefined RGB colorspaces are defined over the extended range by default. Also, color interpolation says not to clamp intermediate results that are extended. as @weinig says, taht removes some needless complexity from the implementation as well. Is that sufficient?

@Smilebags
Copy link

However, it isn't exposed as a color() colorspace. Should it be?

Just chiming in to say I think it would be nice to have this as an option, definitely.

@kainino0x
Copy link
Contributor

kainino0x commented Sep 25, 2021

That is all done now; all the transfer functions are defined over the extended range.

For reference, the commit that did this was 0503cf1.
(It was a bit challenging to find in the blame because of small merge-commit issue that happened shortly after it.)


May I ask (perhaps this is not quite the right issue for it): Are these colorspaces now meant to be defined over the extended range? I ask because there is still the following wording, e.g. for srgb:

The srgb [SRGB] color space accepts three numeric parameters, representing the red, green, and blue channels of the color, with each having a valid range of [0, 1].

Perhaps this is meant to only apply to the color() function and not to the actual definition of the colorspace that we are using in WebGPU (which seems unambiguously defined over the full range).

@svgeesus
Copy link
Contributor

As I said earlier:

Extended versions

Currently, all the predefined RGB colorspaces are defined over the extended range by default.

However, we do have some Web-compat issues which restrict the legacy, sRGB-only forms somewhat.

I will check and see if that "valid range" statement can be reworded.

@svgeesus
Copy link
Contributor

There is some better wording in Specifying profiled colors: the color(https://drafts.csswg.org/css-color-4/#color-function) function:

For custom color spaces, specified component values less than 0 or 0%, or greater than 1 or 100% are not invalid; they are clamped to the valid range at computed value time. This is because ICC profiles typically do not accept out of range input values.

For predefined color spaces, specified component values less than 0 or 0%, or greater than 1 or 100% are not invalid; these out of gamut colors are gamut mapped to the valid range at computed value time, with a relative colorimetric intent.

Which contradicts the

with each having a valid range of [0, 1].

in the definition of sRGB, display-p3 etc. And these are all in the color() function so unafected by legacy deadweight. It looks like those could simply be reworded.

@svgeesus
Copy link
Contributor

svgeesus commented Oct 11, 2021

Extended is now the default, so re-titling the issue to reflect the remaining open part.

Expose Linear-light sRGB as CSS syntax?

Currently, the term linear-light sRGB is defined in CSS Color 4, primarily to allow reference from other specifications such as SVG filters or Canvas. However, it isn't exposed as a color() colorspace. Should it be?

color: color(srgb-linear 0.1 0.4 0.7);

The main reason to do so would be for the convenience of authors who are also using colors in WebGPU or WebGL, which are not color-managed and require all colors to be specified in a single colorspace. srgb-linear is supported there, but not in CSS.

Note that the minimum precision for srgb-linear would be high, likely half-float per component.

@svgeesus svgeesus changed the title [css-color-4] Consider adding "extended" and "linear" variants of the predefined RGB-ish color spaces [css-color-4] Expose Linear-light sRGB as CSS syntax? Oct 11, 2021
@svgeesus
Copy link
Contributor

For the use of srgb-linear, see Color spaces in Canvas High Dynamic Range.

Note: that document also uses rec2100-hlg and rec2100-pq which are in CSS Color HDR

@svgeesus
Copy link
Contributor

For use of srgb-linear in WebGPU for linear-light textures, see

A destination color-space option on copyExternalImageToTexture (soon to be added) would provide a place for users to control the upload: instead of srgb, they could specify srgb-linear, which is the same color space but linearly encoded.
gpuweb/gpuweb#1715

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-color-4] Expose Linear-light sRGB as CSS syntax?, and agreed to the following:

  • RESOLVED: Add srgb-linear color space
The full IRC log of that discussion <fantasai> Topic: [css-color-4] Expose Linear-light sRGB as CSS syntax?
<fantasai> github: https://github.com//issues/6087
<fantasai> chris_: Linear-light sRGB is sRGB without gamma function
<fantasai> chris_: already extended beyond 0 and 1
<fantasai> chris_: some hardware uses this to do HDR
<fantasai> chris_: used in WebGPU and Canvas
<fantasai> chris_: also SVG filters do all their work in this mode
<fantasai> chris_: We export the term for re-use, but don't expose it to authors
<Rossen_> q?
<fantasai> chris_: so question is do we want to do that
<fantasai> smfr: WebKit supports adding this
<fantasai> chris_: does anyone object?
<fantasai> chris_: Just notice that it has a much higher precision function than sRGB
<fantasai> chris_: so you will need a half-float to hold these values
<fantasai> RESOLVED: Add srgb-linear color space

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-color-4 Current Work
Projects
No open projects
Development

No branches or pull requests

7 participants