You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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, 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.
When converting hsl() to rgb() and saturation is +Infinity or -Infinity: [...]
when l === 0, r, g, b, 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
Let's skip hwb() -> rgb() because it becomes more complicated when more than one channel value is infinite.
For example (lab() -> color(xyz)), when a === 0, z tends towards +Infinity when l tends towards +Infinity, but z tends towards -Infinity when b also tends towards +Infinity. Should z be 0 when l and b are +Infinity? Should some "precedence" between channel values be defined (eg. l over a and b)?
Note that channel values do not always tend linearly towards an infinite value:
rgb(from hsl(0 -99 calc(infinity)) r g b) would resolve to color(srgb calc(infinity) calc(infinity) calc(infinity))
rgb(from hsl(0 -101 calc(infinity)) r g b) would resolve to color(srgb calc(infinity) calc(-infinity) calc(-infinity))
Am I missing something?
The text was updated successfully, but these errors were encountered:
I agree that coercing values to infinity is going to cause no end of problems with color math; most color spaces are not designed to cope with such extreme values.
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.
For color spaces are clamped, yes. Most are not, including color(srgb ...) and oklab() and so on.
I just re-opened #8629 because the WG discussion apparently consisted of @tabatkins asserting that it was fine (for rgba()) and thus fine everywhere else.
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.Specifically...
color(srgb-linear) -> color(xyz-d65)
color(xyz-d50) -> color(xyz-d65)
color(xyz-d65) -> color(srgb-linear)
x
andy
are the same infinitex
/y
andz
are infinitecolor(xyz-d50) -> lab()
x
andy
are the same infinitey
andz
are the same infinitecolor(xyz-d65) -> color(xyz-d50)
x
andy
are infinitey
andz
are infinitex
andz
are the same infinitecolor(xyz-d65) -> oklab()
oklab() -> color(xyz-d65)
rgb() -> hsl()
hsl() -> rgb()
s
is infinite andl
is 0/100l
is infinitehwb() -> rgb()
w
is infiniteb
is -Infinitylab() -> color(xyz-d50)
l
is infinite anda
is the opposite infinitel
andb
are the same infinitelch() -> lab()
oklch() -> oklab()
c
is infinite andh
is 0This CodePen allows to play with conversion functions, which have comments for
NaN
cases.In
[email protected]
,NaN
seems to be replaced bynone
, which seems incorrect: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, 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()
andhwb() -> rgb()
, but it should presumably be done for all conversions producingNaN
.When converting
hsl()
torgb()
andsaturation
is+Infinity
or-Infinity
: [...]l === 0
,r
,g
,b
, are0
l < 0
, same as whenl > 0
but with inverted infinite signsl > 0
:h
r
g
b
330 < h < 30
+Infinity
-Infinity
-Infinity
h === 30
+Infinity
l
-Infinity
30 < h < 90
+Infinity
+Infinity
-Infinity
h === 90
l
+Infinity
-Infinity
90 < h < 150
-Infinity
+Infinity
-Infinity
h === 150
-Infinity
+Infinity
l
150 < h < 210
-Infinity
+Infinity
+Infinity
h === 210
-Infinity
l
+Infinity
210 < h < 270
-Infinity
-Infinity
+Infinity
h === 270
l
-Infinity
+Infinity
270 < h < 330
+Infinity
-Infinity
+Infinity
h === 330
+Infinity
-Infinity
l
When converting
hsl()
torgb()
andl === +Infinity
:-100 <= saturation <= 100
,r
,g
,b
, are+Infinity
saturation < -100
, same assaturation > 100
but with inverted infinite signssaturation > 100
,r
,g
,b
, are+Infinity
/-Infinity
depending onsaturation
andh
h
h
interval values depend onsaturation
r
/g
/b
has a different signWhen converting
hsl()
torgb()
andl === -Infinity
:-100 <= saturation <= 100
,r
,g
,b
, are-Infinity
saturation < -100
orsaturation > 100
, same as whenlightness === +Infinity
but with different intervalsLet's skip
hwb() -> rgb()
because it becomes more complicated when more than one channel value is infinite.For example (
lab() -> color(xyz)
), whena === 0
,z
tends towards+Infinity
whenl
tends towards+Infinity
, butz
tends towards-Infinity
whenb
also tends towards+Infinity
. Shouldz
be0
whenl
andb
are+Infinity
? Should some "precedence" between channel values be defined (eg.l
overa
andb
)?Note that channel values do not always tend linearly towards an infinite value:
rgb(from hsl(0 -99 calc(infinity)) r g b)
would resolve tocolor(srgb calc(infinity) calc(infinity) calc(infinity))
rgb(from hsl(0 -101 calc(infinity)) r g b)
would resolve tocolor(srgb calc(infinity) calc(-infinity) calc(-infinity))
Am I missing something?
The text was updated successfully, but these errors were encountered: