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-typed-om] CSSColorValue section needs WG review #1039

Closed
LeaVerou opened this issue May 14, 2021 · 10 comments
Closed

[css-typed-om] CSSColorValue section needs WG review #1039

LeaVerou opened this issue May 14, 2021 · 10 comments

Comments

@LeaVerou
Copy link
Member

This entire section was committed in Dec 2020 under an "editorial" commit message.
Given that it adds an entire new API, it is most certainly not editorial.
It may have been by accident, but it has since stayed in the spec and never got the WG review that such a substantive edit entails. It is now being cited by a Canvas proposal and is being promoted by the editor as a Color model for the Web, something on which there is a significant lack of consensus.

We need to decide:
a) Is this the API shape we want for an API representing CSS syntax?
b) What is the scope of this? Is it in scope to use it as a generic color manipulation object for the Web Platform, or should that be a separate API?

CC: chairs (@atanassov, @astearns), editor (@tabatkins), interested WG members (@svgeesus, @plinss),
@fantasai who encouraged @svgeesus and I to add this to the agenda 😊

@svgeesus
Copy link
Contributor

CC @emilio @faceless2 @samweinig for additional informed input

@tabatkins
Copy link
Member

This entire section was committed in Dec 2020 under an "editorial" commit message.

Ahahaha, that was clearly a mistake; the commit message refers to the part of the commit aside from Color. I must have had it in my buffer when I worked on a different issue.

It may have been by accident, but it has since stayed in the spec and never got the WG review that such a substantive edit entails.

I definitely welcome review, but I'll note that this is relatively direct translation of CSS syntax into Typed OM, similar to Transform or math work; this should be a pretty uncontroversial addition in its current form. I don't think I needed to seek special review for adding the CSSMathMin/CSSMathMax/CSSMathClamp functions a bit ago, for example, since they didn't raise any interesting questions.

It is now being cited by a Canvas proposal and is being promoted by the editor as a Color model for the Web, something on which there is a significant lack of consensus.

The fact that there's some side controversy about whether or not the Web needs an additional Color class beyond what this API can offer is, well, a side issue. Nothing I've put into the spec has any relevance to that discussion; like I said, it's so far a straightforward translation of CSS into Typed OM, with just a few editorial decisions about value representation in a few bits (which aren't relevant to the Color-class topic).

Regarding the Canvas proposal, as I've said twice in the relevant issue thread, the question there is about better inputs to the canvas color attributes. Right now they accept only strings of CSS text. Accepting a Typed OM color object as input as well is a straightforward and reasonable thing to do, regardless of whatever else we might do with a Color class on the web; I don't see any possible way this could be controversial or even particularly require seeking special consensus from the CSSWG. If/when such a Color class is accepted, it'll be an obvious input as well.

If we were talking about output, this would be a more difficult question; whether to have it output a TypedOM value or wait for the Color class is a valid and reasonable question that we should definitely discuss. But that's not the topic at hand.


We need to decide:
a) Is this the API shape we want for an API representing CSS syntax?
b) What is the scope of this? Is it in scope to use it as a generic color manipulation object for the Web Platform, or should that be a separate API?

For (a) I think I did a pretty straightforward translation, tho feedback is always welcome. Y'all's feedback has already brought some nice changes, thanks for that.

For (b), that's an interesting question to discuss, but as I've repeatedly noted, it is not urgent in any way. Nothing is hinging on the results of this discussion.

@LeaVerou
Copy link
Member Author

I do not doubt it was committed by mistake, I mentioned that possibility in my first post. But, the reality is that it has remained in the spec and is now referenced by other proposals.

The fact that other substantive edits did not get wider WG review is not justification for other edits to also not get WG review. I disagree that the translation to Typed OM is "uncontroversial" and "straightforward". If it were, our feedback wouldn't have brought any changes because there would only be one possible API. The decision on (b) crucially affects whether this should have methods like e.g. color space conversion or any of the others in #1040.

Regarding the Canvas proposal, since CSSColorValue stringifies to a CSS color, they are already accepted as inputs so that is a red herring. If this is not meant to be a generic Color API for the Web, authors should not be encouraged to be constructing such objects themselves.

@LeaVerou
Copy link
Member Author

LeaVerou commented May 19, 2021

In preparation for today's call, a few notes about why I think CSSColorValue should not be used more broadly for color input and output on the Web Platform.

Missing functionality and algorithms

Although there is a lot of missing functionality, we should not focus on that.
Indeed, missing functionality can always be added (see #1040), though I do think that adding a bunch of color math methods and extensibility points to a Typed OM object is kinda weird.

First, the extensibility needed for a Color object is broader than the kind of extensibility afforded by CSS itself (e.g. in JS adding new color spaces can be done by providing conversion code -- CSS's @color-profile cannot provide that).

Most algorithms in the spec are also currently very underspecified. Sure, we can point to the CSS Color module for certain things, but a JS API brings up different challenges compared to a declarative CSS one. How does conversion happen? When does gamut mapping happen and how? Sure, these can be fleshed out, but since part of Tab's argument was that work on a Color API is "still far off" so we should use this because it's supposed to be good enough and is already here, it should be mentioned.

But beyond functionality and algorithms, even in terms of just API shape, there are certain things that cannot change without reducing the utility of CSSColorValue as part of the Typed OM, but they make it quite painful for authors if used as a general Color API.

Using CSSNumericValue objects instead of numbers

Even though the constructor accepts CSSNumberish, so both CSSNumericValue and regular doubles are accepted as input, the getters still have to return a CSSNumericValue object, which makes manipulations painful, verbose, and confusing.

Let's take the most simple color manipulation case: where we want to increase color's lightness by 20% and we don't even care about the color space of the result.

The "easy" case, is if the object has been constructed from doubles, or CSSUnitValue values:

let lchColor = color.to("lch");
color.l.value = color.l.value * 1.2;

Even in that case, every getter needs to have .value after it to get the actual number. It honestly brings back memories of working with the SVG DOM.

Also, being unaware of this and trying something like color.l + 10 will perform string concatenation, with results utterly baffling to authors.

If this was about hue, because these objects need to reflect the actual CSS syntax it means authors that want to handle hues need to first convert whatever CSSUnitValue object they get into a number of degrees (since most algorithms expect that).

But, like I said, this is the "easy" case. It's verbose, but at least workable. It gets a lot more complicated if any of the numbers can be CSSMathValue, or in the common case where we simply don't know and need to handle all possibilities. After looking at both the CSSNumericValue superclass and the CSSMathValue subclass, I ...actually don't know how to perform a color manipulation even as simple as increasing LCH lightness, or even reading the current one. Maybe by recursively calling the math methods to try and get a resolved value? And what happens when a resolved value is not possible? This means that every single color manipulation method on this API needs to take that into account, and every snippet of author code needs to also account for this. It cannot be guaranteed that any code that accepts colors and wishes to perform some math on them can actually produce a result! Even if right now every possible calculation can be resolved to numbers, there is no guarantee about the future, and we don't want to limit CSS in that way.

All this complexity is required to represent CSS constructs (which is the goal of Typed OM), because in CSS you can have e.g. lch(calc(1turn + 5deg) calc(10vw / 100px) 10) and it needs to be preserved for the purposes of representing CSS syntax. However, it does not need to be preserved for a Color API. That would mean every API method, and every bit of author code that needs to handle colors needs to branch for this. A separate Color API can just accept CSSColorValue objects in its constructor and throw if their values cannot be resolved, then anything from then on operates on plain ol' numbers.

Abstract superclass + subclasses architecture

Because this is Typed OM and needs to closely represent CSS syntax, there is a number of subclasses that each have a different API. sRGB colors can either be CSSRGB or CSSColor. In the first case their red coordinate is read via color.r.value, in the second case via color.channels[0].value. It's not even clear to me if they use the same ranges. Any code that needs to be able to handle any color value needs to do a lot of annoying conditional branching about what class they have.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-typed-om] CSSColorValue section needs WG review.

The full IRC log of that discussion <dael> Topic: [css-typed-om] CSSColorValue section needs WG review
<dael> github: https://github.com//issues/1039
<dael> leaverou: This was committed in Dec 2020 as editorial. Has stayed in spec and adds a new API. We thought needs wider review. Esp b/c referenced by other groups and prop as accepting inputs for color
<dael> leaverou: Back in Dec when posted w/o spec was an API for css syntax. At time had concerns but assured it was not a color object. Chris and I have been working on color object since July
<TabAtkins> q+
<dael> leaverou: Now saying it should be used as a color object. After review seems unsuitable. need to review if we want this as API for css syntax and what is the scope of the API; syntax or generic color manipulation
<dael> leaverou: For second one I have more strong opinions and arguments.
<dael> leaverou: Posted some thoughts in issue. Side dsicussion with plinss and chris_ which is fairly long and misleading title. It eveolved into what should this API do
<chris_> Lea's comment: https://github.com//issues/1039#issuecomment-844185998
<dael> leaverou: Using this as a color API for the web I would object. Not focusing on missing functionality, though there are issues. They can be fixed. Not sure a typedOM should be used. Exampe, color object should allow adding color spaces by adding color code
<dael> leaverou: css color needs to use numeric objects, not numbers, which makes api clumsy. As input accepts numbers but get output you have to use .value and convert angles
<dael> leaverou: Worse, not always concrete. Could be a css math value which is calculations
<dael> leaverou: Unclear to me when writing code snippit how I would do a simple color manipulation like lightness if you get back a css math value. What happens when you can't resolve into a number?
<dael> leaverou: If we use this object as general color object this complixity needs to be accounted for in author code
<chris_> q+ to say this CSS-internals stuff would be inapproriate for WebGPU WebGL, Canvas
<dael> leaverou: And because it's css format it needs complex. css rgb or css color object have different shapes. In order to read the color you use different methods. Atuthor code needs to branch
<dael> leaverou: Even as API it's awk and that can't change as typedOM object. It's trying to have an API do 2 things
<astearns> ack TabAtkins
<dael> TabAtkins: First thing, would love wider review. Review from leaverou and chris_ has lead to nice changes. More eyes is always great
<chris_> q2+
<dael> TabAtkins: For the rest, I think this was too much of an info dump to be done as a late agenda+ or a single issue on the call. I would love to do this as a structured F2F where people can review. I think people tuned out with the list and I want to handle invidivually
<dael> astearns: It is a lot of information. Are you interested in arguing for this should be a general color object?
<dael> TabAtkins: certainly
<lea> q?
<astearns> ack chris_
<Zakim> chris_, you wanted to say this CSS-internals stuff would be inapproriate for WebGPU WebGL, Canvas
<dael> astearns: We could have ahd a quick resolution if generally agreed, but yes would need point by point
<lea> q+
<dael> chris_: Agree with leaverou about web gpu and type things where this type of css internals don't want this. I don't think they realized an object can be complicated and how many of the details they don't care about as an input. Espe when extended to be an output
<dael> chris_: Also feel somewhat mislead b/c lot of discussions about what this is and consensus was this is not a color object and hold back. but then TabAtkins has been promoting this as the color object for the web and even if another was needed it would be complex and no one would impl. Being told to sit back and wait b/c we're not designing it and then whoops it is what we're designing doesn't feel like how it should be designed
<dael> chris_: I have a lot of specific concerns about things like color gamut handling which I guess is under general review
<dael> TabAtkins: I dispute that I have been disingeuous.
<dael> astearns: I would like us to center on technical issues and not on personal issues
<dael> chris_: You're right astearns
<astearns> ack lea
<dael> astearns: Let's just talk about the API itself
<fantasai> I think it's fair to say that it's inappropriate to commit an entire API under an editorial commit message and then pretend it was always in the spec without asking the CSSWG for review, though...
<dael> leaverou: When it comes to using css color values as input to other apis there doesn't need to be mention in spec. If they stringify they can accept color objects. This isn't about accepting as inputs, but about other uses
<chris_> q+
<dael> astearns: I apprciate you brought it to the agenda to get more eyes. I do agree this is a little much for a single issue. I'd like to see a lot of this broken out into particular issues that we can discuss separately and not re-work the whole deal
<astearns> ack fantasai
<dael> astearns: I would appreciate concerns with use on canvas apis to bring it up in those venues
<plinss> q+
<astearns> ack chris_
<dael> fantasai: If we have major concerns with API it should be marked in the draft so it's clear to anyone reading the intended scope and if there are major issues. Maybe if chris_ and lea and TabAtkins can work out a summary of the major points of concern or confusion it would help people reading understand what's in contention
<dael> chris_: You're right there are many intertwined issues. Crucial question is what are we designing. Are we designing a color object for the web or a thing specific to css parts of which can be used elsewhere. Without a clear sense of what we're designing it's hard to scope other technical comments
<dael> astearns: Can you open an issue specifically on that saying are we designing csscolorvalue as a color object for the web? And particular issues that crop up there will need to be spun out and thye may depend on the general answer.
<dael> chris_: Happy to do that
<astearns> ack plinss
<lea> plinss +1
<TabAtkins> q+
<dael> plinss: chris_ said a lot of what I want to say. I accep thtis is bigger and needs more discussion and eyes. I'm concerns if we push this to next F2F or a long term period that a lot of work will be done in a direction without us picking one and I don't want to get to where we're stuck
<chris_> plinss++
<fantasai> plinss++
<florian> plins++
<dael> plinss: I want to address the meta issue about purpose of these classes before more work gets done leading us down that path
<dael> astearns: Happy to convine a meeting specifically on this as well.
<astearns> ack TabAtkins
<chris_> The more up to date Canvas proposal for WCG and HDR is here https://github.com/w3c/ColorWeb-CG/blob/master/hdr_html_canvas_element.md
<plinss> q+
<dael> TabAtkins: Wanted to say the scope of current work people are building on is about an input to canvas apis. Accept css values as strings and want to accept as typedOM. Everything you can express in typedOM is possible by putting it in string form so any of those concerns have been present since canvas was introduced. Anything further about this being a general color object should be discussed, but not as pressing b/c no one is building on that in the sh[CUT]
<florian> s/plins++/plinss++/
<dael> TabAtkins: Let's have the larger discussion when we can prepare and have time for it. No reason to be afraid we're setting anything by not discussing b/c nothing you can do now that can't do in strings
<astearns> ack plinss
<dael> plinss: I want to agree with TabAtkins in part and rebut
<dael> plinss: typedom objects as inputs is non-controversial
<TabAtkins> Oooh, I wasn't aware of those impinging on this work. Sure.
<TabAtkins> (Our next f2f is sooner than 6 months ^_^)
<dael> plinss: Problem is what are we using as the output and that is more pressing. There's eyedroppers and color inputs that tag is reviewing and they output colors and we need to tell they how to input. Need shorter than 6 month answer
<dael> astearns: Please continue discussions. New issues will be opened and we'll come back

@astearns astearns removed the Agenda+ label May 19, 2021
@tabatkins
Copy link
Member

First, the extensibility needed for a Color object is broader than the kind of extensibility afforded by CSS itself (e.g. in JS adding new color spaces can be done by providing conversion code -- CSS's @color-profile cannot provide that).

Could you open an issue for this? I was under the impression that an ICC profile was sufficient for color space conversions; if we will indeed want more than that, we should explore the details. CSS probably wants access to this, then, so they could use such a space in color(), which would be an argument for a new Houdini API.

Most algorithms in the spec are also currently very underspecified.

If we assume (as I did when writing the spec) that the relevant CSS specs defining the types are "in scope" for understanding/implementing the related Typed OM types, then it's exactly as specified as Color 4 is (and, unless it's related to Typed OM-specific details, should have its specification live in Color 4, imo). Your questions about details of conversion and gamuts are, afaict, exactly as relevant for Color 4, aren't they? I don't think there's any convenient censoring of details that CSS can rely on that Typed OM accidentally exposes here.

(But I am going to add some more explicit links back to Color 4 here, based on y'all's feedback.)

let lchColor = color.to("lch");
color.l.value = color.l.value * 1.2;

This could be written in slightly shorter ways, fwiw. color.l = color.l.value * 1.2;, or color.l.value *= 1.2;.

But yeah, this is the major API hurdle that a JSColor wouldn't have to deal with.

If this was about hue, because these objects need to reflect the actual CSS syntax it means authors that want to handle hues need to first convert whatever CSSUnitValue object they get into a number of degrees (since most algorithms expect that).

I strongly suspect JSColor would present their raw-double angles as radians; all JS and web-platform APIs consistently do.

(The canonical unit for CSS angles is deg, tho, so computed-values or later, which get canonicalized, will give a CSSUnitValue with a "deg" unit.)

But, like I said, this is the "easy" case. It's verbose, but at least workable. It gets a lot more complicated if any of the numbers can be CSSMathValue,
[snip details]

I'm a little confused about what the concern is here.

You'll only get a complex function out of Typed OM if (a) the author wrote those in CSS and you're getting a specified value (since we don't simplify until computed-value time) or (b) you're looking at a computed-time value and it specifically uses a value in a math function that can't be converted into a canonical unit yet.

In neither of those situations can a JSColor API even represent the value at all. This isn't a matter of one API being more complicated than the other; the value itself is complicated, Typed OM can represent it, and a JSColor API wouldn't be able to. JSColor would just punt.

However, if you're not using a value that invokes these complicated things, then CSS is guaranteed to simplify it away by computed-value time, and TypedOM will present you with a plain CSSUnitValue object for all the channels. So, as long as JSColor is capable of representing the value, TypedOM will represent it in the exact same way (save for the .value bit).

And if we're talking about using this API to create and work with colors directly, then there's no chance those complex situations will occur either. An author would have to go out of their way to manually create the Typed OM objects representing those functions, and that's their own fault at that point. ^_^ So in this situation TypedOM and JSColor would be the same, too.

Because this is Typed OM and needs to closely represent CSS syntax, there is a number of subclasses that each have a different API. sRGB colors can either be CSSRGB or CSSColor. In the first case their red coordinate is read via color.r.value, in the second case via color.channels[0].value. It's not even clear to me if they use the same ranges. Any code that needs to be able to handle any color value needs to do a lot of annoying conditional branching about what class they have.

As far as I can tell, this is a concern for a JSColor too, isn't it? If you're working with color values that are in different spaces, they'll present their own APIs - .r/.g/.b vs .h/.s/.l, etc. If you want them all in the same space so you have a consistent API, you can convert them to a single space, and Typed OM values make that easy as well with .to().

(Contrast that with any existing CSS color handling, which'll returns strings in particular spaces and no easy way to request a particular space, so you do have to do any changes yourself.)

So is there actually any required branching with this sort of API?

@LeaVerou
Copy link
Member Author

LeaVerou commented May 20, 2021

Could you open an issue for this? I was under the impression that an ICC profile was sufficient for color space conversions; if we will indeed want more than that, we should explore the details. CSS probably wants access to this, then, so they could use such a space in color(), which would be an argument for a new Houdini API.

An ICC profile is sufficient, but not always necessary. For many conversions, it's far easier to just specify metadata about the color space and conversion code to/from XYZ, and that also makes them synchronous, whereas loading an ICC profile is asynchronous.
Most RGB spaces fall into this category, as well as pretty much the entire category of matrix-based color spaces.
For CMYK ones (and any other patch measurement based color spaces), the ICC profile is pretty much the only way.
FYI, all predefined color spaces are matrix-based.

If we assume (as I did when writing the spec) that the relevant CSS specs defining the types are "in scope" for understanding/implementing the related Typed OM types, then it's exactly as specified as Color 4 is (and, unless it's related to Typed OM-specific details, should have its specification live in Color 4, imo). Your questions about details of conversion and gamuts are, afaict, exactly as relevant for Color 4, aren't they? I don't think there's any convenient censoring of details that CSS can rely on that Typed OM accidentally exposes here.

But there is. Let's take gamut mapping as an example. CSS can do late gamut mapping only when a color is displayed and only ever needs to map to the gamut of the display device. When you can read coordinates, there needs to be more control about when or if to gamut map.
Granted, this may eventually become an issue for CSS as well, if we add functions to read individual components, but right now it's not.
To clarify, I do not think this functionality needs to be present in CSSColorValue, whose purpose is to represent the existing CSS syntax as objects. But it does need to be available on the Color API.

I strongly suspect JSColor would present their raw-double angles as radians; all JS and web-platform APIs consistently do.

I strongly suspect it would not. Presenting them as radians is inconsistent with both CSS colors (where unitless hues are in degrees) and everywhere else in the literature where a hue is specified. Nobody needs hues in radians. Remember, authors are above theoretical purity, also there are many types of consistency at play, which are often at odds with each other (in fact, we are about to add a new TAG design principle on this).

But, like I said, this is the "easy" case. It's verbose, but at least workable. It gets a lot more complicated if any of the numbers can be CSSMathValue,
[snip details]

I'm a little confused about what the concern is here.

You'll only get a complex function out of Typed OM if (a) the author wrote those in CSS and you're getting a specified value (since we don't simplify until computed-value time) or (b) you're looking at a computed-time value and it specifically uses a value in a math function that can't be converted into a canonical unit yet.

In neither of those situations can a JSColor API even represent the value at all. This isn't a matter of one API being more complicated than the other; the value itself is complicated, Typed OM can represent it, and a JSColor API wouldn't be able to. JSColor would just punt.

However, if you're not using a value that invokes these complicated things, then CSS is guaranteed to simplify it away by computed-value time, and TypedOM will present you with a plain CSSUnitValue object for all the channels. So, as long as JSColor is capable of representing the value, TypedOM will represent it in the exact same way (save for the .value bit).

And if we're talking about using this API to create and work with colors directly, then there's no chance those complex situations will occur either. An author would have to go out of their way to manually create the Typed OM objects representing those functions, and that's their own fault at that point. ^_^ So in this situation TypedOM and JSColor would be the same, too.

The thing is, because this possibility exists, other APIs (either native to the platform, or author-created ones) cannot declare that they do not accept such colors. They need to handle them somehow, potentially creating error conditions down the line that shouldn't be there. Similarly, methods of the API itself need to handle such values somehow, complicating it both conceptually for authors and practically for implementors. Whereas a Color object would always come with the guarantee of actual resolved values that can be worked on.

There could be some utility in a convenience method on CSSColorValue that resolves its expressions based on a given context and returns a resolved Color object.

As far as I can tell, this is a concern for a JSColor too, isn't it? If you're working with color values that are in different spaces, they'll present their own APIs - .r/.g/.b vs .h/.s/.l, etc. If you want them all in the same space so you have a consistent API, you can convert them to a single space, and Typed OM values make that easy as well with .to().

That is only one potential design, and IMO not the best one for a Color API (it works fine for Typed OM however).

So is there actually any required branching with this sort of API?

I'm not sure what you're asking here.

@tabatkins
Copy link
Member

An ICC profile is sufficient, but not always necessary. [snip]

Ah, makes sense. Bringing this back to the topic, tho, wouldn't CSS want access to this as well, implying we want a Houdini API to allow JS-backed color profiles? Then Typed OM would have access to such things.

(Typed OM colors could always be converted by hand with JS code, it just wouldn't hook into the .to() function unless we added Houdini color profiles to CSS.)

CSS can do late gamut mapping only when a color is displayed and only ever needs to map to the gamut of the display device. When you can read coordinates, there needs to be more control about when or if to gamut map.

I'm not sure I understand - you can read individual coordinates in CSS; that's what the color functions are. I suspect I'm missing something here - could you elaborate on what you mean?

I strongly suspect it would not. Presenting them as radians is inconsistent with both CSS colors (where unitless hues are in degrees) and everywhere else in the literature where a hue is specified. Nobody needs hues in radians. Remember, authors are above theoretical purity, also there are many types of consistency at play, which are often at odds with each other (in fact, we are about to add a new TAG design principle on this).

Right, but the fact that all angle-wrangling functions in JS use radians (and thus would require an annoying pair of conversions to use with a degree-based API) is something I think is pretty important.

(I definitely prefer using degrees myself, and in angle-heavy pages I've written, I defined my own sin/cos/etc functions that take degrees instead, just wrapping the built-ins with a bit of conversion code.)

In any case, not super relevant here, I'll drop this tangent. Typed OM gives you access to both, and CSS favors degrees anyway. ^_^

The thing is, because this possibility exists, other APIs (either native to the platform, or author-created ones) cannot declare that they do not accept such colors. [...]

Sure, platform APIs need to deal with that possibility, most likely by failing early when they can't resolve them down. But most (all?) platform APIs that want to work with color are going to want to take CSS strings as an option anyway, because they're ubiquitous and easy to obtain from other APIs, and so they'll need to deal with the exact same issues there.

However, your example seemed to be about the difficulty of userland code doing color manipulation having to deal with this complexity, and I think I demonstrated that's not actually an issue. Most of the time they won't see such complexity anyway, and the rare times they do, it's because someone grabbed a value that cannot be expressed in a JSColor in the first place; any place they could have obtained a JSColor, they'll get a similarly-simple Typed OM value.

That is only one potential design, and IMO not the best one for a Color API (it works fine for Typed OM however).

Interesting - what is a better API, in your opinion? What I described looks to be like what you're doing in Color.js, right?

(Possibly this is better discussed in a separate issue, since it might be an involved conversation.)

So is there actually any required branching with this sort of API?

If I read your previous comment correctly, you stated that, since a Typed OM color could be in any of the color spaces, and thus can have various types of channels and different accessor properties to those channels, authors would need to handle each of the color spaces individually whenever they write any color-manipulating code. (Similar to today's world where people have to handle several possible color functions that can be returned by CSS strings.) Is this right?

If that's an accurate read, then I don't think the conclusion is correct - if you're doing color manipulation, you can call .to() on the values to put them in a single chosen space and do all your work there. Does this make sense?

@Myndex
Copy link
Member

Myndex commented Sep 2, 2021

First, the extensibility needed for a Color object is broader than the kind of extensibility afforded by CSS itself (e.g. in JS adding new color spaces can be done by providing conversion code -- CSS's @color-profile cannot provide that).

Could you open an issue for this? I was under the impression that an ICC profile was sufficient for color space conversions; if we will indeed want more than that, we should explore the details. CSS probably wants access to this, then, so they could use such a space in color(), which would be an argument for a new Houdini API.

Hi @tabatkins and Hi @LeaVerou

just to chime in here a bit, possibly tangentially: We know ICC profiles don't "do" color space conversions, they just provide some information about a space so a color management engine can do so... but is that best?

Eye See Sea Spaces....

That said, ICC profiles for converting between two display spaces with the same white point is not a best practice; it is just a commonly available method. ICC profiles are certain important, the ICC system is what allowed desktop publishing to flourish.

BUT: ICC profile-based color management is processor intensive. Not bad perhaps for some still images or printable content. But nearly useless for dynamic and especially streaming content. We do not use them here in Hollywood and for good reason (After Effects notwithstanding). Instead we use LUTs, which are more direct and computationally less expensive.

LUT workflows are freely available, such as OpenColorIO, a project of Sony Imageworks.

I bring this up as working with ICC profiles is slow enough, even on very fast workstations (and I have lots of fast workstations) that engaging them with streaming content is literally a show stopper. The playback stops.

The ICC workflow is reasonably good for RGB -> CMYK transforms as a part of pre-press, but ICC workflows are not a magical bullet to cure all and convert all... and there are other alternatives/methods that are worth considering.

And in filmmaking we do use ICC profiles in lieu of LUTs for some Adobe products. But the main applications we use like Fusion and Nuke etc are all LUT based. OpenColorIO is a drop in for AfterEffects, and I stopped using Adobe's color manglement as soon as OCIO was available.

If we consider mobile devices, where power and processor are are at a premium, does such a system makes sense? Sure, I can see it being a part of a web standard — but it if is then so should OCIO, and some other default means, as in, sRGB should always be the default fallback. There are implications for accessibility where sRGB is somewhat ideal, and most devices can use sRGB with no color management at all.

  • Technically color management is "not needed" for sRGB web content, as it is a calibrated standard.
  • Watching television is not color managed. Television broadcasts are a calibrated standard but not a color managed delivery pipeline.
  • The human capacity for "color constancy" allows us to see content or objects that are not absolutely color accurate, so long as the colors are relative-correct against each other.

Display Spaces...

All that said, the important thing is getting content is whatever space the author worked in to display properly on the end user's display space. It is interesting seeing the new UHD/HDR technologies like Rec2020 and Rec2100. The important space is the display space. And if the user calibrates, then their monitor is one unique space that content author won't know. Only the user does.

For instance, when I surf the web with my NEC wide gamut monitor, technically I'm not looking at sRGB or any other, I am looking at "Andy's personal monitor colorspace" created with the calibration and loaded into the monitor's internal 14 but LUTs. It's not sRGB, it's specific to the calibration and calibration profile.

But my Safari browser assumes everything I see online is sRGB, and Safari and the MacOS color management takes what it assumes is sRGB and transforms it to display on my monitor.

But must mobile devices, and even many desktops, do not have full color management.

Aye, See the Gamut Map, See?

Lea mentioned a couple things, one that conversion can be done by other means, and two, gamut mapping.

There is no magical button, ICC profile, OCIO or whatever, that can squish a wide gamut image into a smaller space automagically and without compromises. In Hollywood when we convert/transfer a film or TV show to a different distribution medium, that process is overseen by a colorist who makes adjustments though out for best results. Yes, you can use the gamut mapping in a color management engine or LUT workflow — if results are important, color will need guidance and adjustment along the way.

And this is not even mentioning that color management in browsers is not exactly "fully supported" except perhaps for Safari on MacOS. I imagine that issue changing as CSS 4 becomes the rec and more browsers fully integrate CSS colors and assets beyond images.

In practice, this is less hard that one might think; if we are working in a D65 RGB space, and the destination (user's display) is also a D65 RGB space, it's not horribly difficult to make that transform, and no ICC profile is really needed. ICC profiles are not superior to other methods of gamut mapping. And in practice, if you are not clipping, then a larger space and the resultant need to map does not provide much benefit.

Bigger is not better

BUT I see that ProPhoto, a space so large that the primaries are not real, they are imaginary primaries that cannot exist in the physical world, and the white point is D50, because ProPhoto is not a display space it's a working space to allow working on images/art in RGB for elements that are destined for CMYK printing.

I am a little puzzled as to why it's in the CSS spec; it's main use is in pre-press work, not as a delivery/display profile.

ProPhoto is a huge profile that requires working in 16 bit, but it is literally impossible to create a monitor that fits that profile due to the size and the imaginary primaries. And an image in a prophoto profile is an example of the kind of image that needs to be "manually massaged" to bring it into a displayable or printable space.

TL;DR

  • There are alternatives to ICC profiles, and if all that is happening is going from RGB space A -> RGB space B display spaces, then ICC and the PCS (profile connection space) are unneeded bloat for web content.
  • The author's working space should "ideally" match the destination space & whitepoint
    • (except possibly being in a higher bit depth).
    • They should use the same LUT the destination will be using.
  • The basic spaces, like sRGB, should be accommodated without the use of any ICC profile.
  • sRGB is ubiquitous, and a web author should need nothing more than a tag in the head like:
    <meta: colorspace="sRGB" type="display" fallback="DisplayP3" >
    • sRGB, Rec709, Adobe1998, and DisplayP3 are close enough to each other including similar gamma/trc and similar gamut size that assets in these spaces can be converted easily and probably without a lot of manual gamut mapping.
  • The PCS is not really needed for RGB to RGB, especially with the same whitepoint.
  • Hopefully these comments were not too tangential.

Thank you

Andy

@svgeesus
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants