1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
use *;
/// The enumeration of supported color spaces.
///
/// # RGB
///
/// This crate supports several RGB color spaces, each in its gamma-corrected
/// and its linear form. From smallest to largest gamut, they are:
///
/// * [sRGB](https://en.wikipedia.org/wiki/SRGB), which has long served as the
/// default color space for the web.
/// * [Display P3](https://en.wikipedia.org/wiki/DCI-P3), which is
/// well-positioned to become sRGB's successor.
/// * [Rec. 2020](https://en.wikipedia.org/wiki/Rec._2020), which is the
/// standard color space for ultra-high-definition (UDH) video and, when it
/// comes to display hardware, currently aspirational.
///
/// For all three color spaces as well as all three linear versions, in-gamut
/// coordinates range from 0 to 1, inclusive.
///
/// # The Oklab Variations
///
/// This crate supports the
/// [Oklab/Oklch](https://bottosson.github.io/posts/oklab/) and
/// [Oklrab/Oklrch](https://bottosson.github.io/posts/colorpicker/#intermission---a-new-lightness-estimate-for-oklab)
/// color spaces. All four are variations of the same perceptually uniform color
/// space, which, like CIELAB, uses one coordinate for lightness and two
/// coordinates for "colorness."
///
/// Oklab and Oklch reflect the original design. They improve on CIELAB by using
/// the D65 standard illuminant (not the print-oriented D50), which is also used
/// by sRGB and Display P3. They further improve on CIELAB by avoiding visible
/// distortions around the blues. However, they also regress, as their lightness
/// L is visibly biased towards dark tones. Oklrab and Oklrch, which were
/// introduced nine months after Oklab/Oklch, feature a revised lightness Lr
/// that closely resembles CIELAB's uniform lightness.
///
/// Oklab/Oklrab use Cartesian coordinates a, b for colorness—with the a axis
/// varying red/green and the b axis varying blue/yellow. Because they use
/// Cartesian coordinates, computing color difference in Oklab/Oklrab is
/// straight-forward: It simply is the Euclidian distance. In contrast,
/// Oklch/Oklrch use polar coordinates C/h—with C expressing chroma and h or
/// also hº expressing hue. That makes both color spaces well-suited to
/// synthesizing and modifying colors.
///
/// Compared to the most other conversions between color spaces, conversions
/// between the four Oklab variations are mathematically simpler and may not
/// involve all coordinates. After all, there are four three-dimensional color
/// spaces but only six distinct quantities:
///
/// | Color space | Lightness | Colorness 1 | Colorness 2 |
/// | ----------- | :-------: | :---------: | :---------: |
/// | Oklab | L | a | b |
/// | Oklch | L | C | hº |
/// | Oklrab | Lr | a | b |
/// | Oklrch | Lr | C | hº |
///
/// Valid coordinates observe the following invariants:
///
/// * The (revised) lightness for all four color spaces is limited to `0..=1`.
/// * The a/b coordinates for Oklab/Oklrab have no set limits, but in practice
/// can be bounded `-0.4..=0.4`.
/// * The chroma for Oklch/Oklrch must be non-negative and in practice can be
/// bounded `0..=0.4`.
/// * The hue for Oklch/Oklrch may be not-a-number, which indicates a
/// powerless component, i.e., gray tone. In that case, the chroma must
/// necessarily be zero.
///
/// Fundamentally, Oklab and Oklch are the *same* color space, only using
/// different coordinate systems. Of course, that also is the case for Oklrab
/// and Oklrch. The chroma bond corresponds to a circle with radius 0.4 that is
/// centered at the origin. The a/b bounds correspond to a square with sides 0.8
/// that is also centered at the origin. The circle just fits into the square
/// and covers an area of π×0.4². Meanwhile, the square covers an area of
/// (2×0.4)², i.e., it is 4/π or 1.273 times larger. In other words, the a/b
/// bounds are somewhat looser than the chroma bound.
///
/// There may or may not be another, still outstanding issue with Oklrab, namely
/// that a and b need [to be scaled by a factor of around
/// 2.1](https://github.com/w3c/csswg-drafts/issues/6642#issuecomment-945714988).
///
/// There also is an extended Oklab, which behaves better for [imaginary
/// colors](https://github.com/w3c/csswg-drafts/issues/9449). As shown in the
/// [corresponding
/// notebook](https://colab.research.google.com/drive/1_uoLM95LJKTiI7MECG_PjBrd32v-3W3o),
/// the implementation compresses and shifts the LMS coordinates during
/// conversion.
///
/// # XYZ
///
/// [XYZ](https://en.wikipedia.org/wiki/CIE_1931_color_space) serves as
/// foundational color space. Notably, all conversions between unrelated color
/// spaces go through XYZ. Since sRGB, Display P3, and Oklab use the [D65
/// standard illuminant](https://en.wikipedia.org/wiki/Standard_illuminant),
/// this crate uses XYZ with D65 as its reference color space. But XYZ with the
/// D50 standard illuminant is available, too. Chromatic adaptation between the
/// two versions of XYZ uses the (linear) Bradford method.