- From: Guillaume via GitHub <sysbot+gh@w3.org>
- Date: Thu, 27 Jun 2024 17:13:27 +0000
- To: public-css-archive@w3.org
cdoublev has just created a new issue for https://github.com/w3c/csswg-drafts:
== [css-color-4] How to handle infinite values in color functions? ==
Unless otherwise specified, color channel values are not clamped, which applies to values produced by math functions, which can be infinite.
Infinite color channel values produce `NaN` in most conversion functions.
<details>
<summary>Specifically</summary>
- `color(xyz-d50) -> color(xyz-d65)`
- `color(xyz-d65) -> rgb-linear()`
- when `x` and `y` are the same infinite
- when `x`/`y` and `z` are infinite
- `color(xyz-d50) -> lab()`
- when one or more channels are the same infinite
- `color(xyz-d65) -> color(xyz-d50)`
- when `x` and `y` are infinite
- when `y` and `z` are infinite
- when `x` and `z` are the same infinite
- `color(xyz-d65) -> oklab()`
- `oklab() -> color(xyz-d65)`
- `rgb() -> hsl()`
- when one or more channel is infinite
- `hsl() -> rgb()`
- when `s` is infinite and `l` is 0/100
- when `l` is infinite
- `hwb() -> rgb()`
- when `w` is infinite
- when `b` is -Infinity
- `lab() -> color(xyz-d50)`
- when `l` is infinite and `a` is the opposite infinite
- when `l` and `b` are the same infinite
- `lch() -> lab()`
- `oklch() -> oklab()`
- when `c` is infinite and `h` is 0
- `rgb-linear() -> color(xyz-d65)`
- when one or more channels are infinite and one or more are the opposite infinite
This [CodePen](https://codepen.io/creativewave/pen/eYaKyVX) allows to play with conversion functions, which have comments for NaN cases.
</details>
In `colorjs.io@0.5.1`, `NaN` seems to be replaced by `none`, which seems incorrect:
```js
let color = new Color('hsl', [0, 0, Infinity])
color.to('srgb').toString(); // rgb(none none none)
```
Clarification on how to handle infinite values has already been asked in #8629, which was resolved with *no further change* because *if you put an infinite calculation into an rgba(), the behavior is well-defined: clamp to the allowed range*.
At least, this is not true for some channels of other color functions than `rgb()`, and for relative colors.
Following this [comment](https://github.com/w3c/csswg-drafts/issues/8629#issuecomment-1513228530), I tried to guess the color resulting from a color function specified with one infinite channel value. Since I am personally only interested by serialized values, I only did it for `hsl() -> rgb()` and `hwb() -> rgb()`, but it should presumably be done for all conversions producing `NaN`.
<details>
<summary>When converting <code>hsl()</code> to <code>rgb()</code> and <code>saturation</code> is <code>+Infinity</code> or <code>-Infinity</code>:</summary>
- when `l === 0`, red/green/blue are `0`
- when `l < 0`, same as when `l > 0` but with inverted infinite signs
- when `l > 0`:
| `h` | `r` | `g` | `b`
| --------------- | -------------- | -------------- | --------------
| `330 < h < 30` | `+Infinity` | `-Infinity` | `-Infinity`
| `h === 30` | `+Infinity` | depends on `l` | `-Infinity`
| `30 < h < 90` | `+Infinity` | `+Infinity` | `-Infinity`
| `h === 90` | depends on `l` | `+Infinity` | `-Infinity`
| `90 < h < 150` | `-Infinity` | `+Infinity` | `-Infinity`
| `h === 150` | `-Infinity` | `+Infinity` | depends on `l`
| `150 < h < 210` | `-Infinity` | `+Infinity` | `+Infinity`
| `h === 210` | `-Infinity` | depends on `l` | `+Infinity`
| `210 < h < 270` | `-Infinity` | `-Infinity` | `+Infinity`
| `h === 270` | depends on `l` | `-Infinity` | `+Infinity`
| `270 < h < 330` | `+Infinity` | `-Infinity` | `+Infinity`
| `h === 330` | `+Infinity` | `-Infinity` | depends on `l`
When converting `hsl()` to `rgb()` and `l === +Infinity`:
- when `-100 <= saturation <= 100`, r, g, b, are `+Infinity`
- when `saturation < -100`, same as `saturation > 100` but with inverted infinite signs
- when `saturation > 100`, r/g/b are `+Infinity`/`-Infinity` depending on `saturation` and `h`
- there are 6 intervals defined by `h`
- the exact `h` interval values depend on `saturation`
- for each sibling intervals, one of r/g/b has a different sign
When converting `hsl()` to `rgb()` and `l === -Infinity`:
- when `-100 <= saturation <= 100`, r/g/b are `-Infinity`
- when `saturation < -100` or `saturation > 100`, same as when `lightness === +Infinity` but with different intervals
</details>
Let's skip `hwb() -> rgb()` because it becomes more complicated when more than one infinite channel value.
For example, when `a === 0`, `x` tends towards `+Infinity` when `l` tends towards `+Infinity`, or towards `-Infinity` when `b` also tends towards `+Infinity`. Should `z` be `0`? Should some "precedence" between channel values be defined?
Note that channel values do not linearly tend towards an infinite value:
- `rgb(from hsl(0 -99 calc(infinity)) r g b)` would resolve to `rgb(calc(infinity) calc(infinity) calc(infinity))`
- `rgb(from hsl(0 -101 calc(infinity)) r g b)` would resolve to `rgb(calc(infinity) calc(-infinity) calc(-infinity))`
Am I missing something?
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/10507 using your GitHub account
--
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Thursday, 27 June 2024 17:13:28 UTC