Skip to content

[css-typed-om] Possible features for CSSColorValue #1040

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

Closed
tabatkins opened this issue May 14, 2021 · 4 comments
Closed

[css-typed-om] Possible features for CSSColorValue #1040

tabatkins opened this issue May 14, 2021 · 4 comments

Comments

@tabatkins
Copy link
Member

In #1014 (comment), Lea gave the following list of features potentially missing from Typed OM's color classes, that would be useful in a dedicated color class:

  • Provide conversion between color spaces
  • Provide control over when (and how) gamut mapping occurs when converting. For many use cases you need lossless conversion so you can roundtrip, for others you need an in-gamut color.
  • A way to check whether the color is in gamut of the current color space or another color space
  • Parsing and serialization
  • Relative and absolute color manipulation by tweaking coordinates in arbitrary color spaces, ideally without having to manually convert to these spaces and back.
  • To be future-proof and extensible, it needs to be as color space agnostic as possible. It needs to be able to work with HDR and white gamut color spaces. It should not privilege sRGB or any other color space or model through special syntax, nor use generic "RGB" keywords to represent a specific RGB space (e.g. sRGB).
  • Interpolation and color mixing are needed in a large number of use cases (visualizations, palette generation, gradients etc)
  • Compositing & blending
  • Contrast calculation
  • Color difference calculation (DeltaE) to be able to compare similarity between colors, ideally multiple algorithms to allow authors to make tradeoffs between efficiency and accuracy, or an API that allows extensibility (especially since many new color spaces come with their own DeltaE algorithms, e.g. Jzazbz or ICtCp).
  • Extensible: Authors need to be able to register new color spaces or new color models over existing spaces. At the very least in the same way that they can add @color-profile rules in CSS, but ideally as long as they can provide conversion code to and from XYZ (or any other connection space) they shouldn't need an ICC profile. In CSS an ICC profile is the only way to register a new space because an @-rule cannot provide code, but JS doesn't have this limitation.
@tabatkins
Copy link
Member Author

Provide conversion between color spaces

✔ Already provided by TypedOM.

Provide control over when (and how) gamut mapping occurs when converting. For many use cases you need lossless conversion so you can roundtrip, for others you need an in-gamut color.

Definitely doable. Right now the to() function is just meant to invoke the algos in Color 4; it's not super clear, but I think it automatically gamut-maps (as written in https://drafts.csswg.org/css-color-4/#lab-to-predefined). Adding an option to tell it not to map sounds completely reasonable.

A way to check whether the color is in gamut of the current color space or another color space

Absolutely reasonable to add, I think.

Parsing and serialization

✔ Already in.

Relative and absolute color manipulation by tweaking coordinates in arbitrary color spaces, ideally without having to manually convert to these spaces and back.

✔ Already in, tho you do need to convert explicitly to the space you want to work in.

In #1034 I asked for examples of where you would want to do a tweak in one space and then convert back, but I haven't gotten a response yet - Chris provided several useful examples of wanting to convert to another color space, but they're all doing something with a pair of colors that you need to put into a shared color space (which one or neither of them might be in). None of his examples showed off having a color start in one space, get tweaked in another space, then put back into the original space.

As I said in #1034, we can definitely offer such a functionality if it's needed, and I sketched out a simple method for achieving it. I just haven't heard justification for needing it yet.

To be future-proof and extensible, it needs to be as color space agnostic as possible. It needs to be able to work with HDR and white gamut color spaces. It should not privilege sRGB or any other color space or model through special syntax, nor use generic "RGB" keywords to represent a specific RGB space (e.g. sRGB).

~Partially. Any color space CSS supports can be used (and any color space we want to support on the Web, we'll want to support in CSS, so it'll show up here), and now that I've made some tweaks to the .colorSpace and .to() methods, the API is pretty agnostic to them. The only real difference is whether they have predefined names for their channels exposed (all the CSS color spaces with built-in functions) or if you have to access the channels by index (all the color() values).

None of the color spaces are otherwise privileged thru syntax, tho "rgb" does specifically refer to the CSS rgb() function, and thus the sRGB space. Given the existence of CSS colors and the rgb() function, tho, anything that didn't let you refer to "colors like what rgb() does" seems like it would be author-hostile, and using any name other than what the rgb() function itself uses feels like the same, especially if the other spaces all get to use their CSS function name. I think I'm happy to actively oppose this particular requirement, and would probably push back against it in a bespoke Color api for the web, too.

Interpolation and color mixing are needed in a large number of use cases (visualizations, palette generation, gradients etc)

The Color 5 functions will be supported in Typed OM as soon as I'm reasonably certain they're stable in the Color spec, and just like the math functions on CSSNumericValues that let you say num1.add(num2) instead of new CSSMathSum(num1, num2), I think convenience methods on CSSColorValue that let you mix/interpolate/etc colors makes sense.

Contrast calculation

Absolutely reasonable to add, I think.

Color difference calculation (DeltaE) to be able to compare similarity between colors, ideally multiple algorithms to allow authors to make tradeoffs between efficiency and accuracy, or an API that allows extensibility (especially since many new color spaces come with their own DeltaE algorithms, e.g. Jzazbz or ICtCp).

Also completely reasonable to me. Exactly what algos we expose can be debated, but having at least some is completely reasonable, since it's something I know I've used (by hand, painfully) when working with color in the past.

Extensible: Authors need to be able to register new color spaces or new color models over existing spaces. At the very least in the same way that they can add @color-profile rules in CSS, but ideally as long as they can provide conversion code to and from XYZ (or any other connection space) they shouldn't need an ICC profile. In CSS an ICC profile is the only way to register a new space because an @-rule cannot provide code, but JS doesn't have this limitation.

Agreed and tracked in a generic fashion in #1038, tho the right design might end up being piecemeal specialized extensibility points.

@svgeesus
Copy link
Contributor

Provide conversion between color spaces

In rather more detail - it should provide conversion between any pair of colors, regardless of what colorspace each was specified in, provided that each colorspace has a colorimetric definition (so, table-of-measurements based colorspaces are excluded).

That conversion should be automatic given the start and end points, without needing to specify a sequence of operations or additional data. For example when converting from color(display-p3 n n n) to color(prophoto-rgb n n n) the conversion must perform correct linearization before conversion to a linear-light exchange space like XYZ, must automatically compensate (Bradford chromatic adaptation) for the different white points of those two spaces, and perform the correct gamma-encoding on the linear-light result.

(I'm saying "like XYZ" because Canvas HDR plans to use linear-light Rec.2100 as the intermediate space, which should give the same result as XYZ provided there is no need for chromatic adaptation. Which with their limited choice of four colorspaces, there isn't - all are D65)

The conversion should not needlessly apply steps that can be eliminated (for example, adapting from D65 to D50 and then immediately adapting back to D65 - very similar result but cumulative errors build up and can be problematic)

However, being able to optionally specify additional detail (use CAT16 chromatic adaptation instead of linear Bradford, for example) might be useful. But I think on balance that should be carefully justified, most of the time the defaults should be fine if well chosen.

The matrix coordinates for conversions should be carefully tested such that long chains of conversions accumulate minimal errors.

All conversions should use the same standardized values for white points, because using subtly different ones at different parts of the chain has been found to cause noticeable error.

Both to avoid cumulative error and also to accommodate HDR (the way that Canvas plans to), and to accommodate WCG for situations (WebGPU) where everything is in one colorspace and so WCG is accomplished with out-of gamut values, there must be no clipping or gamut mapping of out of range values during intermediate operations. Clipping or gamut mapping should be explicitly requested, performed as late as possible (and both options should be supported).

Gamut mapping using LCH chroma reduction with constant lightness is suggested as the optimal general purpose algorithm. As we are already excluding calibrated CMYK, there is no need to accommodate black point matching in gamut mapping. (HDR tonemapping should be treated separately).

The case for allowing a custom gamut mapping operation should be considered. There is a lot of research work in this area, mostly concluding that different algorithms or color spaces are useful in some but not all cases, i.e. "it depends". So locking into a single choice would be unwise.

There should be a mechanism for adding new (colorimetrically defined) colorspaces and getting auto conversion into and out of them. I'm thinking of OKLab, ICtCp for example here. Both adding by later standardization, and also adding with user code.

@svgeesus
Copy link
Contributor

None of his examples showed off having a color start in one space, get tweaked in another space, then put back into the original space.

Adjusting the LCH Lightness of a color (which is not in LCH or Lab):

color.set("lch.l", a => a * 1.2);

@svgeesus
Copy link
Contributor

svgeesus commented Mar 7, 2024

This issue from May 2021 was resolved at the meeting on 21 July 2021 (minutes) and both Typed OM and Color API have been updated to match.

@svgeesus svgeesus closed this as completed Mar 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants