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
Copy file name to clipboardExpand all lines: css-color-4/Overview.bs
+65-48Lines changed: 65 additions & 48 deletions
Original file line number
Diff line number
Diff line change
@@ -5467,63 +5467,80 @@ CSS Gamut Mapping to an RGB Destination</h3>
5467
5467
<h4 id="binsearch">
5468
5468
Sample Pseudocode for the Binary Search Gamut Mapping Algorithm with Local MINDE</h4>
5469
5469
5470
-
<div algorithm="to CSS gamut map a color">
5471
-
To <dfn export>CSS gamut map</dfn> a color |origin|
5472
-
in color space |origin color space|
5473
-
to be in gamut of a destination color space |destination|:
5470
+
<div algorithm="to CSS gamut map a color">
5471
+
To <dfn export>CSS gamut map</dfn> a color |origin|
5472
+
in color space |origin color space|
5473
+
to be in gamut of a destination color space |destination|:
5474
5474
5475
+
<ol>
5476
+
<!-- check if we need gamut mapping at all -->
5477
+
<li>if |destination| has no gamut limits (XYZ-D65, XYZ-D50, Lab, LCH, Oklab, Oklch) convert |origin| to |destination| and return it as the gamut mapped color
5478
+
<!-- we do, so convert to Oklch -->
5479
+
<li>let |origin_Oklch| be |origin| converted
5480
+
from |origin color space| to the Oklch color space</li>
5481
+
<!-- constrain to SDR lightness range, which gamut maps to black or white -->
5482
+
<li>if the Lightness of |origin_Oklch| is greater than or equal to 100%,
5483
+
convert `oklab(1 0 0 / origin.alpha)` to |destination| and return it as the gamut mapped color</li>
5484
+
<li>if the Lightness of |origin_Oklch| is less than than or equal to 0%,
5485
+
convert `oklab(0 0 0 / origin.alpha)` to |destination| and return it as the gamut mapped color</li>
5486
+
<li>let inGamut(|color|) be a function which returns true if, when passed a color,
5487
+
that color is inside the gamut of |destination|.
5488
+
For HSL and HWB, it returns true if the color is inside the gamut of sRGB.
5489
+
</li>
5490
+
<!-- are we already in gamut? -->
5491
+
<li>if inGamut(|origin_Oklch|) is true, convert |origin_Oklch| to |destination| and return it as the gamut mapped color</li>
5492
+
<!-- now start to gamut map -->
5493
+
<li>otherwise, let delta(|one|, |two|) be a function which returns the deltaEOK of color |one| compared to color |two|</li>
5494
+
<li>let |JND| be 0.02</li>
5495
+
<li>let |epsilon| be 0.0001</li>
5496
+
<!-- we already excluded spaces with no gamut limits in the first step, so this is fine -->
5497
+
<li>let clip(|color|) be a function which converts |color| to |destination|,
5498
+
clamps each component to the bounds of the reference range for that component
5499
+
and returns the result</li>
5500
+
5501
+
<!-- is clipped already indistinguishable from origin, and in gamut? -->
5502
+
<li>set |current| to |origin_Oklch|</li>
5503
+
<li>set |clipped| to clip(|current|)</li>
5504
+
<li>set |E| to delta(|clipped|, |current|)</li>
5505
+
<li>if |E| < |JND|
5475
5506
<ol>
5476
-
<li>if |destination| has no gamut limits (XYZ-D65, XYZ-D50, Lab, LCH, Oklab, Oklch) convert |origin| to |destination| and return it as the gamut mapped color
5477
-
<li>let |origin_Oklch| be |origin| converted
5478
-
from |origin color space| to the Oklch color space</li>
5479
-
<li>if the Lightness of |origin_Oklch| is greater than or equal to 100%,
5480
-
return { 1 1 1 origin.alpha } in |destination|</li>
5481
-
<li>if the Lightness of |origin_Oklch| is less than than or equal to 0%,
5482
-
return { 0 0 0 origin.alpha } in |destination|</li>
5483
-
<li>let inGamut(|color|) be a function which returns true if, when passed a color,
5484
-
that color is inside the gamut of |destination|.
5485
-
For HSL and HWB, it returns true if the color is inside the gamut of sRGB.
5486
-
</li>
5487
-
<li>if inGamut(|origin_Oklch|) is true, convert |origin_Oklch| to |destination| and return it as the gamut mapped color</li>
5488
-
<li>otherwise, let delta(|one|, |two|) be a function which returns the deltaEOK of color |one| compared to color |two|</li>
5489
-
<li>let |JND| be 0.02</li>
5490
-
<li>let |epsilon| be 0.0001</li>
5491
-
<!-- we already excluded spaces with no gamut limits in the first step, so this is fine -->
5492
-
<li>let clip(|color|) be a function which converts |color| to |destination|,
5493
-
converts all negative components to zero,
5494
-
converts all components greater that one to one,
5495
-
and returns the result
5496
-
</li>
5497
-
<li>set |min| to zero</li>
5498
-
<li>set |max| to the Oklch chroma of |origin_Oklch|</li>
5499
-
<li> let |min_inGamut| be a boolean that represents when |min| is still in gamut, and set it to true
5500
-
<li>while (|max| - |min| is greater than |epsilon|) repeat the following steps
5507
+
<li>return |clipped| as the gamut mapped color</li>
5508
+
</ol>
5509
+
</li>
5510
+
5511
+
<!-- reduce chroma -->
5512
+
<li>set |min| to zero</li>
5513
+
<li>set |max| to the Oklch chroma of |origin_Oklch|</li>
5514
+
<li> let |min_inGamut| be a boolean that represents when |min| is still in gamut, and set it to true
5515
+
<li>while (|max| - |min| is greater than |epsilon|) repeat the following steps
5516
+
<ol>
5517
+
<li>set |chroma| to (|min| + |max|) /2</li>
5518
+
<li>set the chroma component of |current| to |chroma|</li>
5519
+
<li>if |min_inGamut| is true and also if inGamut(|current|) is true, set |min| to |chroma| and continue to repeat these steps</li>
5520
+
<li>otherwise, if inGamut(|current|) is false carry out these steps:
5501
5521
<ol>
5502
-
<li>set |chroma| to (|min| + |max|) /2</li>
5503
-
<li>set |current| to |origin_Oklch| and then set the chroma component to |chroma|</li>
5504
-
<li>if |min_inGamut| is true and also if inGamut(|current|) is true, set |min| to |chroma| and continue to repeat these steps</li>
5505
-
<li>otherwise, if inGamut(|current|) is false carry out these steps:
5522
+
<li>set |clipped| to clip(|current|)</li>
5523
+
<li>set |E| to delta(|clipped|, |current|)</li>
5524
+
<li>if |E| < |JND|
5525
+
<ol>
5526
+
<li>if (|JND| - |E| < |epsilon|) return |clipped| as the gamut mapped color</li>
5527
+
<li>otherwise,
5506
5528
<ol>
5507
-
<li>set |clipped| to clip(|current|)</li>
5508
-
<li>set |E| to delta(|clipped|, |current|)</li>
5509
-
<li>if |E| < |JND|
5510
-
<ol>
5511
-
<li>if (|JND| - |E| < |epsilon|) return |clipped| as the gamut mapped color</li>
5512
-
<li>otherwise,
5513
-
<ol>
5514
-
<li>set |min_inGamut| to false</li>
5515
-
<li>set |min| to |chroma|</li>
5516
-
</ol>
5517
-
</li>
5518
-
</ol>
5519
-
</li>
5520
-
<li>otherwise, set |max| to |chroma| and continue to repeat these steps</li>
5529
+
<li>set |min_inGamut| to false</li>
5530
+
<li>set |min| to |chroma|</li>
5521
5531
</ol>
5532
+
</li>
5533
+
</ol>
5522
5534
</li>
5535
+
<li>otherwise, set |max| to |chroma| and continue to repeat these steps</li>
5523
5536
</ol>
5524
5537
</li>
5525
-
<li>return |clipped| as the gamut mapped color</li>
5526
5538
</ol>
5539
+
</li>
5540
+
<li>return |clipped| as the gamut mapped color</li>
0 commit comments