@thi.ng/color 5.6.2 → 5.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +1 -1
  3. package/alpha.js +6 -10
  4. package/analog.js +35 -67
  5. package/api/constants.js +128 -156
  6. package/api/gradients.js +0 -1
  7. package/api/names.js +154 -151
  8. package/api/ranges.js +0 -1
  9. package/api/system.js +21 -26
  10. package/api.js +27 -32
  11. package/clamp.js +18 -29
  12. package/closest-hue.js +6 -12
  13. package/color-range.js +159 -228
  14. package/color.js +29 -28
  15. package/contrast.js +7 -17
  16. package/convert.js +19 -40
  17. package/cosine-gradients.js +177 -229
  18. package/css/css.js +27 -53
  19. package/css/parse-css.js +94 -160
  20. package/defcolor.js +97 -108
  21. package/distance.js +96 -187
  22. package/gradients.js +29 -37
  23. package/hcy/hcy-rgb.js +20 -13
  24. package/hcy/hcy.js +9 -11
  25. package/hsi/hsi-rgb.js +32 -30
  26. package/hsi/hsi.js +9 -11
  27. package/hsl/hsl-css.js +9 -10
  28. package/hsl/hsl-hsv.js +12 -9
  29. package/hsl/hsl-rgb.js +14 -6
  30. package/hsl/hsl.js +14 -16
  31. package/hsv/hsv-css.js +4 -1
  32. package/hsv/hsv-hsl.js +11 -8
  33. package/hsv/hsv-rgb.js +14 -6
  34. package/hsv/hsv.js +14 -16
  35. package/hue.js +12 -12
  36. package/int/int-css.js +10 -6
  37. package/int/int-int.js +6 -10
  38. package/int/int-rgb.js +16 -5
  39. package/int/int-srgb.js +22 -4
  40. package/int/int.js +136 -142
  41. package/internal/css.js +16 -12
  42. package/internal/dispatch.js +6 -2
  43. package/internal/ensure.js +18 -16
  44. package/internal/matrix-ops.js +39 -41
  45. package/internal/scale.js +4 -2
  46. package/invert.js +46 -39
  47. package/is-black.js +12 -5
  48. package/is-gamut.js +8 -13
  49. package/is-gray.js +12 -5
  50. package/is-white.js +14 -7
  51. package/lab/lab-css.js +4 -9
  52. package/lab/lab-lab.js +6 -2
  53. package/lab/lab-lch.js +18 -10
  54. package/lab/lab-rgb.js +6 -14
  55. package/lab/lab-xyz.js +16 -20
  56. package/lab/lab50.js +18 -15
  57. package/lab/lab65.js +18 -15
  58. package/lch/lch-css.js +4 -9
  59. package/lch/lch.js +18 -23
  60. package/lighten.js +13 -17
  61. package/linear.js +6 -16
  62. package/luminance-rgb.js +14 -22
  63. package/luminance.js +16 -14
  64. package/max-chroma.js +1340 -227
  65. package/mix.js +34 -82
  66. package/oklab/oklab-css.js +4 -9
  67. package/oklab/oklab-rgb.js +17 -23
  68. package/oklab/oklab-xyz.js +22 -9
  69. package/oklab/oklab.js +19 -22
  70. package/oklch/oklab-oklch.js +10 -11
  71. package/oklch/oklch-css.js +4 -9
  72. package/oklch/oklch-oklab.js +9 -9
  73. package/oklch/oklch.js +14 -20
  74. package/package.json +19 -17
  75. package/rgb/hue-rgb.js +14 -11
  76. package/rgb/kelvin-rgba.js +23 -22
  77. package/rgb/rgb-css.js +4 -1
  78. package/rgb/rgb-hcv.js +14 -15
  79. package/rgb/rgb-hcy.js +10 -14
  80. package/rgb/rgb-hsi.js +13 -8
  81. package/rgb/rgb-hsl.js +8 -5
  82. package/rgb/rgb-hsv.js +7 -4
  83. package/rgb/rgb-lab.js +6 -18
  84. package/rgb/rgb-oklab.js +13 -19
  85. package/rgb/rgb-srgb.js +18 -8
  86. package/rgb/rgb-xyz.js +6 -19
  87. package/rgb/rgb-ycc.js +12 -17
  88. package/rgb/rgb.js +25 -22
  89. package/rotate.js +25 -38
  90. package/sort.js +24 -72
  91. package/srgb/srgb-css.js +9 -9
  92. package/srgb/srgb-int.js +6 -10
  93. package/srgb/srgb-rgb.js +18 -8
  94. package/srgb/srgb.js +16 -13
  95. package/strategies.js +42 -112
  96. package/swatches.js +28 -5
  97. package/tint.js +27 -53
  98. package/transform.js +274 -149
  99. package/variations.js +10 -9
  100. package/xyy/xyy-xyz.js +12 -11
  101. package/xyy/xyy.js +16 -13
  102. package/xyz/wavelength-xyz.js +14 -28
  103. package/xyz/xyz-lab.js +17 -26
  104. package/xyz/xyz-oklab.js +4 -1
  105. package/xyz/xyz-rgb.js +6 -18
  106. package/xyz/xyz-xyy.js +13 -12
  107. package/xyz/xyz-xyz.js +6 -2
  108. package/xyz/xyz50.js +20 -17
  109. package/xyz/xyz65.js +20 -17
  110. package/ycc/ycc-rgb.js +14 -19
  111. package/ycc/ycc.js +12 -9
package/distance.js CHANGED
@@ -6,205 +6,114 @@ import { labD50 } from "./lab/lab50.js";
6
6
  import { labD65 } from "./lab/lab65.js";
7
7
  import { luminanceRgb, luminanceSrgb } from "./luminance-rgb.js";
8
8
  const { abs, cos, hypot, sin, sqrt } = Math;
9
- /**
10
- * Higher order function. Returns {@link ColorDistance} function for given color
11
- * channel ID.
12
- *
13
- * @param id -
14
- */
15
- export const distChannel = (id) => (a, b) => abs(a[id] - b[id]);
16
- /**
17
- * Computes distance between two HSV colors, i.e. the eucledian distance between
18
- * points in a cyclinder.
19
- *
20
- * @param a -
21
- * @param b -
22
- */
23
- export const distHsv = (a, b) => {
24
- const aa = cossin(a[0] * TAU, a[1]);
25
- const bb = cossin(b[0] * TAU, b[1]);
26
- return hypot(aa[0] - bb[0], aa[1] - bb[1], a[2] - b[2]);
9
+ const distChannel = (id) => (a, b) => abs(a[id] - b[id]);
10
+ const distHsv = (a, b) => {
11
+ const aa = cossin(a[0] * TAU, a[1]);
12
+ const bb = cossin(b[0] * TAU, b[1]);
13
+ return hypot(aa[0] - bb[0], aa[1] - bb[1], a[2] - b[2]);
27
14
  };
28
- /**
29
- * Similar to {@link distHsv}, but computes distance between two LCH colors
30
- * (with different channel order), i.e. the eucledian distance between points in
31
- * a cyclinder (using Law of Cosines).
32
- *
33
- * @remarks
34
- * Reference:
35
- * - https://math.stackexchange.com/a/3612602
36
- * - https://en.wikipedia.org/wiki/Law_of_cosines
37
- *
38
- * @param a
39
- * @param b
40
- */
41
- export const distLch = ({ 0: la, 1: ca, 2: ha }, { 0: lb, 1: cb, 2: hb }) => Math.sqrt(ca * ca +
42
- cb * cb -
43
- 2 * ca * cb * Math.cos((ha - hb) * TAU) +
44
- (la - lb) ** 2);
45
- /**
46
- * Computes difference in saturation between two HSV colors.
47
- *
48
- * @param a -
49
- * @param b -
50
- */
51
- export const distHsvSat = distChannel(1);
52
- /**
53
- * Computes difference in brightness between two HSV or two HSL colors.
54
- *
55
- * @param a -
56
- * @param b -
57
- */
58
- export const distHsvLuma = distChannel(2);
59
- /**
60
- * Computes eucledian distance between two colors. Only the first 3 color
61
- * channels will be considered.
62
- *
63
- * @param a -
64
- * @param b -
65
- */
66
- export const distEucledian3 = dist3;
67
- export const distEucledian4 = dist4;
68
- /**
69
- * Computes difference in luminance between two RGB colors.
70
- *
71
- * @param a -
72
- * @param b -
73
- */
74
- export const distRgbLuma = (a, b) => abs(luminanceRgb(a) - luminanceRgb(b));
75
- export const distSrgbLuma = (a, b) => abs(luminanceSrgb(a) - luminanceSrgb(b));
76
- /**
77
- * Computes red difference between two RGB colors.
78
- *
79
- * @param a -
80
- * @param b -
81
- */
82
- export const distRgbRed = distChannel(0);
83
- /**
84
- * Computes green difference between two RGB colors.
85
- *
86
- * @param a -
87
- * @param b -
88
- */
89
- export const distRgbGreen = distChannel(1);
90
- /**
91
- * Computes blue difference between two RGB colors.
92
- *
93
- * @param a -
94
- * @param b -
95
- */
96
- export const distRgbBlue = distChannel(1);
15
+ const distLch = ({ 0: la, 1: ca, 2: ha }, { 0: lb, 1: cb, 2: hb }) => Math.sqrt(
16
+ ca * ca + cb * cb - 2 * ca * cb * Math.cos((ha - hb) * TAU) + (la - lb) ** 2
17
+ );
18
+ const distHsvSat = distChannel(1);
19
+ const distHsvLuma = distChannel(2);
20
+ const distEucledian3 = dist3;
21
+ const distEucledian4 = dist4;
22
+ const distRgbLuma = (a, b) => abs(luminanceRgb(a) - luminanceRgb(b));
23
+ const distSrgbLuma = (a, b) => abs(luminanceSrgb(a) - luminanceSrgb(b));
24
+ const distRgbRed = distChannel(0);
25
+ const distRgbGreen = distChannel(1);
26
+ const distRgbBlue = distChannel(1);
97
27
  const H6 = 6 * DEG2RAD;
98
28
  const H25 = 25 * DEG2RAD;
99
29
  const H63 = 63 * DEG2RAD;
100
30
  const H275 = 275 * DEG2RAD;
101
- /**
102
- * Higher order function to compute the CIEDE2000 color difference between 2
103
- * colors in CIELAB space. Takes a vector of LCH weight coefficients to adjust
104
- * importance of luminance, chroma and hue differences. By default all are 1.
105
- * Returns a {@link ColorDistance} function which converts (if needed) input
106
- * colors to {@link LabD50} and then computes the metric.
107
- *
108
- * @remarks
109
- * References:
110
- * - https://en.wikipedia.org/wiki/Color_difference#CIEDE2000
111
- * - http://www2.ece.rochester.edu/~gsharma/ciede2000/ciede2000noteCRNA.pdf
112
- *
113
- * @param a - Lab color
114
- * @param b - Lab color
115
- */
116
- export const distCIEDE2000 = (weights = ONE3) => (a, b) => {
117
- let { 0: l1, 1: a1, 2: b1 } = labD50(a);
118
- let { 0: l2, 1: a2, 2: b2 } = labD50(b);
119
- l1 *= 100;
120
- a1 *= 100;
121
- b1 *= 100;
122
- l2 *= 100;
123
- a2 *= 100;
124
- b2 *= 100;
125
- const c1ab = hypot(a1, b1);
126
- const c2ab = hypot(a2, b2);
127
- const cab = (c1ab + c2ab) * 0.5;
128
- const g = 1 + 0.5 * (1 - c7Coeff(cab));
129
- a1 *= g;
130
- a2 *= g;
131
- const c1 = hypot(a1, b1);
132
- const c2 = hypot(a2, b2);
133
- const cmean = (c1 + c2) * 0.5;
134
- const { deltaH, H } = computeDeltaH(a1, b1, a2, b2, c1, c2);
135
- const T = 1 -
136
- 0.17 * cos(H - SIXTH_PI) +
137
- 0.24 * cos(2 * H) +
138
- 0.32 * cos(3 * H + H6) -
139
- 0.2 * cos(4 * H - H63);
140
- const Rt = -2 *
141
- c7Coeff(cmean) *
142
- sin(THIRD_PI * Math.exp(-(((H - H275) / H25) ** 2)));
143
- const L50 = ((l1 + l2) * 0.5 - 50) ** 2;
144
- const Sl = 1 + (0.015 * L50) / sqrt(20 + L50);
145
- const Sc = 1 + 0.045 * cmean;
146
- const Sh = 1 + 0.015 * cmean * T;
147
- const termL = (l2 - l1) / (weights[0] * Sl);
148
- const termC = (c2 - c1) / (weights[1] * Sc);
149
- const termH = deltaH / (weights[2] * Sh);
150
- return sqrt(termL ** 2 + termC ** 2 + termH ** 2 + Rt * termC * termH);
31
+ const distCIEDE2000 = (weights = ONE3) => (a, b) => {
32
+ let { 0: l1, 1: a1, 2: b1 } = labD50(a);
33
+ let { 0: l2, 1: a2, 2: b2 } = labD50(b);
34
+ l1 *= 100;
35
+ a1 *= 100;
36
+ b1 *= 100;
37
+ l2 *= 100;
38
+ a2 *= 100;
39
+ b2 *= 100;
40
+ const c1ab = hypot(a1, b1);
41
+ const c2ab = hypot(a2, b2);
42
+ const cab = (c1ab + c2ab) * 0.5;
43
+ const g = 1 + 0.5 * (1 - c7Coeff(cab));
44
+ a1 *= g;
45
+ a2 *= g;
46
+ const c1 = hypot(a1, b1);
47
+ const c2 = hypot(a2, b2);
48
+ const cmean = (c1 + c2) * 0.5;
49
+ const { deltaH, H } = computeDeltaH(a1, b1, a2, b2, c1, c2);
50
+ const T = 1 - 0.17 * cos(H - SIXTH_PI) + 0.24 * cos(2 * H) + 0.32 * cos(3 * H + H6) - 0.2 * cos(4 * H - H63);
51
+ const Rt = -2 * c7Coeff(cmean) * sin(THIRD_PI * Math.exp(-(((H - H275) / H25) ** 2)));
52
+ const L50 = ((l1 + l2) * 0.5 - 50) ** 2;
53
+ const Sl = 1 + 0.015 * L50 / sqrt(20 + L50);
54
+ const Sc = 1 + 0.045 * cmean;
55
+ const Sh = 1 + 0.015 * cmean * T;
56
+ const termL = (l2 - l1) / (weights[0] * Sl);
57
+ const termC = (c2 - c1) / (weights[1] * Sc);
58
+ const termH = deltaH / (weights[2] * Sh);
59
+ return sqrt(termL ** 2 + termC ** 2 + termH ** 2 + Rt * termC * termH);
151
60
  };
152
61
  const c7Coeff = (c) => {
153
- c = c ** 7;
154
- return sqrt(c / (c + 25 ** 7));
62
+ c = c ** 7;
63
+ return sqrt(c / (c + 25 ** 7));
155
64
  };
156
65
  const computeDeltaH = (a1, b1, a2, b2, c1, c2, eps = 1e-3) => {
157
- const h1 = atan2Abs(b1, a1);
158
- const h2 = atan2Abs(b2, a2);
159
- if (c1 <= eps || c2 <= eps)
160
- return { deltaH: 0, H: h1 + h2 };
161
- let dh = h2 - h1;
162
- const sumH = h1 + h2;
163
- const absH = abs(dh);
164
- dh = absH <= PI ? dh : h2 <= h1 ? dh + TAU : dh - TAU;
165
- const deltaH = 2 * sqrt(c1 * c2) * sin(dh / 2);
166
- const H = 0.5 * (absH <= PI ? sumH : sumH < TAU ? sumH + TAU : sumH - TAU);
167
- return { deltaH, H };
66
+ const h1 = atan2Abs(b1, a1);
67
+ const h2 = atan2Abs(b2, a2);
68
+ if (c1 <= eps || c2 <= eps)
69
+ return { deltaH: 0, H: h1 + h2 };
70
+ let dh = h2 - h1;
71
+ const sumH = h1 + h2;
72
+ const absH = abs(dh);
73
+ dh = absH <= PI ? dh : h2 <= h1 ? dh + TAU : dh - TAU;
74
+ const deltaH = 2 * sqrt(c1 * c2) * sin(dh / 2);
75
+ const H = 0.5 * (absH <= PI ? sumH : sumH < TAU ? sumH + TAU : sumH - TAU);
76
+ return { deltaH, H };
168
77
  };
169
78
  const H35 = 35 * DEG2RAD;
170
79
  const H164 = 164 * DEG2RAD;
171
80
  const H168 = 168 * DEG2RAD;
172
81
  const H345 = 345 * DEG2RAD;
173
- /**
174
- * Higher order function to compute the CMC l:c (1984) difference measure
175
- * between 2 colors in the CIELAB (D65) space. Takes lightness and chroma weight
176
- * coefficients to adjust ratio of L:C. By default both are 1. Returns a
177
- * {@link ColorDistance} function which converts (if needed) input colors to
178
- * {@link LabD65} and then computes the metric.
179
- *
180
- * @remarks
181
- * Important: This formular is only a quasimetric & violates symmetry, i.e.
182
- * `distCMC(a, b) !== distCMC(b, a)`
183
- *
184
- * References:
185
- * - https://en.wikipedia.org/wiki/Color_difference#CMC_l:c_(1984)
186
- */
187
- export const distCMC = (kl = 1, kc = 1) => (a, b) => {
188
- let { 0: l1, 1: a1, 2: b1 } = labD65(a);
189
- let { 0: l2, 1: a2, 2: b2 } = labD65(b);
190
- l1 *= 100;
191
- a1 *= 100;
192
- b1 *= 100;
193
- l2 *= 100;
194
- a2 *= 100;
195
- b2 *= 100;
196
- const c1 = hypot(a1, b1);
197
- const c2 = hypot(a2, b2);
198
- const dC = c1 - c2;
199
- const dH = sqrt((a2 - a1) ** 2 + (b2 - b1) ** 2 - dC ** 2);
200
- const h1 = atan2Abs(b1, a1);
201
- const t = h1 >= H164 && h1 <= H345
202
- ? 0.56 + abs(0.2 * cos(h1 + H168))
203
- : 0.36 + abs(0.4 * cos(h1 + H35));
204
- const c14 = c1 ** 4;
205
- const f = sqrt(c14 / (c14 + 1900));
206
- const Sl = l1 >= 16 ? (0.040975 * l1) / (1 + 0.01765 * l1) : 0.511;
207
- const Sc = (0.0638 * c1) / (1 + 0.0131 * c1) + 0.638;
208
- const Sh = Sc * (f * t + 1 - f);
209
- return hypot((l1 - l2) / (kl * Sl), dC / (kc * Sc), dH / Sh);
82
+ const distCMC = (kl = 1, kc = 1) => (a, b) => {
83
+ let { 0: l1, 1: a1, 2: b1 } = labD65(a);
84
+ let { 0: l2, 1: a2, 2: b2 } = labD65(b);
85
+ l1 *= 100;
86
+ a1 *= 100;
87
+ b1 *= 100;
88
+ l2 *= 100;
89
+ a2 *= 100;
90
+ b2 *= 100;
91
+ const c1 = hypot(a1, b1);
92
+ const c2 = hypot(a2, b2);
93
+ const dC = c1 - c2;
94
+ const dH = sqrt((a2 - a1) ** 2 + (b2 - b1) ** 2 - dC ** 2);
95
+ const h1 = atan2Abs(b1, a1);
96
+ const t = h1 >= H164 && h1 <= H345 ? 0.56 + abs(0.2 * cos(h1 + H168)) : 0.36 + abs(0.4 * cos(h1 + H35));
97
+ const c14 = c1 ** 4;
98
+ const f = sqrt(c14 / (c14 + 1900));
99
+ const Sl = l1 >= 16 ? 0.040975 * l1 / (1 + 0.01765 * l1) : 0.511;
100
+ const Sc = 0.0638 * c1 / (1 + 0.0131 * c1) + 0.638;
101
+ const Sh = Sc * (f * t + 1 - f);
102
+ return hypot((l1 - l2) / (kl * Sl), dC / (kc * Sc), dH / Sh);
103
+ };
104
+ export {
105
+ distCIEDE2000,
106
+ distCMC,
107
+ distChannel,
108
+ distEucledian3,
109
+ distEucledian4,
110
+ distHsv,
111
+ distHsvLuma,
112
+ distHsvSat,
113
+ distLch,
114
+ distRgbBlue,
115
+ distRgbGreen,
116
+ distRgbLuma,
117
+ distRgbRed,
118
+ distSrgbLuma
210
119
  };
package/gradients.js CHANGED
@@ -3,43 +3,35 @@ import { setS4 } from "@thi.ng/vectors/sets";
3
3
  import { intArgb32Abgr32 } from "./int/int-int.js";
4
4
  import { argb32 } from "./int/int.js";
5
5
  import { mix as $mix } from "./mix.js";
6
- export function multiColorGradient(opts, isABGR) {
7
- const cols = [...gradient(opts)];
8
- if (isABGR === undefined)
9
- return cols;
10
- const rgba = cols.map((x) => argb32(x)[0]);
11
- return isABGR ? rgba.map(intArgb32Abgr32) : rgba;
6
+ function multiColorGradient(opts, isABGR) {
7
+ const cols = [...gradient(opts)];
8
+ if (isABGR === void 0)
9
+ return cols;
10
+ const rgba = cols.map((x) => argb32(x)[0]);
11
+ return isABGR ? rgba.map(intArgb32Abgr32) : rgba;
12
12
  }
13
- /**
14
- * Similar to {@link multiColorGradient}, but writes results into `buffer` from
15
- * given `offset` and component/element strides. Returns buffer.
16
- *
17
- * @remarks
18
- * Intended use case for this function: 1D texturemap/tonemap generation, e.g.
19
- * for dataviz etc. Also @see {@link cosineGradientBuffer}.
20
- *
21
- * @param opts -
22
- * @param buffer - target buffer/array
23
- * @param offset - start index (default: 0)
24
- * @param cstride - channel stride (default: 1)
25
- * @param estride - element stride (default: 4)
26
- */
27
- export const multiColorGradientBuffer = (opts, buffer = [], offset = 0, cstride = 1, estride = 4) => {
28
- for (let col of gradient(opts)) {
29
- setS4(buffer, col, offset, 0, cstride);
30
- offset += estride;
31
- }
32
- return buffer;
13
+ const multiColorGradientBuffer = (opts, buffer = [], offset = 0, cstride = 1, estride = 4) => {
14
+ for (let col of gradient(opts)) {
15
+ setS4(buffer, col, offset, 0, cstride);
16
+ offset += estride;
17
+ }
18
+ return buffer;
33
19
  };
34
- /** @internal */
35
- const gradient = ({ num, stops, easing, mix, }) => tween({
36
- num: num - 1,
37
- stops,
38
- easing,
39
- min: 0,
40
- max: 1,
41
- init: (a, b) => [a, b],
42
- mix: mix
43
- ? ([a, b], t) => mix(a.empty(), a, b, t)
44
- : ([a, b], t) => $mix(a.empty(), a, b, t),
20
+ const gradient = ({
21
+ num,
22
+ stops,
23
+ easing,
24
+ mix
25
+ }) => tween({
26
+ num: num - 1,
27
+ stops,
28
+ easing,
29
+ min: 0,
30
+ max: 1,
31
+ init: (a, b) => [a, b],
32
+ mix: mix ? ([a, b], t) => mix(a.empty(), a, b, t) : ([a, b], t) => $mix(a.empty(), a, b, t)
45
33
  });
34
+ export {
35
+ multiColorGradient,
36
+ multiColorGradientBuffer
37
+ };
package/hcy/hcy-rgb.js CHANGED
@@ -3,17 +3,24 @@ import { setC3 } from "@thi.ng/vectors/setc";
3
3
  import { __ensureAlpha } from "../internal/ensure.js";
4
4
  import { luminanceRgb } from "../luminance-rgb.js";
5
5
  import { hueRgb } from "../rgb/hue-rgb.js";
6
- export const hcyRgb = (out, src) => {
7
- const h = src[0];
8
- let c = src[1];
9
- const y = src[2];
10
- const rgb = hueRgb(out || src, h, __ensureAlpha(src[3]));
11
- const lum = luminanceRgb(rgb);
12
- if (y < lum) {
13
- c *= y / lum;
14
- }
15
- else if (lum < 1) {
16
- c *= (1 - y) / (1 - lum);
17
- }
18
- return setC3(rgb, clamp01((rgb[0] - lum) * c + y), clamp01((rgb[1] - lum) * c + y), clamp01((rgb[2] - lum) * c + y));
6
+ const hcyRgb = (out, src) => {
7
+ const h = src[0];
8
+ let c = src[1];
9
+ const y = src[2];
10
+ const rgb = hueRgb(out || src, h, __ensureAlpha(src[3]));
11
+ const lum = luminanceRgb(rgb);
12
+ if (y < lum) {
13
+ c *= y / lum;
14
+ } else if (lum < 1) {
15
+ c *= (1 - y) / (1 - lum);
16
+ }
17
+ return setC3(
18
+ rgb,
19
+ clamp01((rgb[0] - lum) * c + y),
20
+ clamp01((rgb[1] - lum) * c + y),
21
+ clamp01((rgb[2] - lum) * c + y)
22
+ );
23
+ };
24
+ export {
25
+ hcyRgb
19
26
  };
package/hcy/hcy.js CHANGED
@@ -4,15 +4,13 @@ import { labRgb } from "../lab/lab-rgb.js";
4
4
  import { rgbHcy } from "../rgb/rgb-hcy.js";
5
5
  import { rgbSrgb } from "../rgb/rgb-srgb.js";
6
6
  import { hcyRgb } from "./hcy-rgb.js";
7
- /**
8
- * @remarks
9
- * Note: As with other hue-based color modes in this package, the hue is stored
10
- * normalized (in [0..1] interval) and NOT as degrees.
11
- */
12
- export const hcy = defColor({
13
- mode: "hcy",
14
- channels: { h: { hue: true } },
15
- order: ["h", "c", "y", "alpha"],
16
- from: { rgb: rgbHcy, srgb: rgbHcy, lch: [lchLab, labRgb, rgbSrgb, rgbHcy] },
17
- toRgb: hcyRgb,
7
+ const hcy = defColor({
8
+ mode: "hcy",
9
+ channels: { h: { hue: true } },
10
+ order: ["h", "c", "y", "alpha"],
11
+ from: { rgb: rgbHcy, srgb: rgbHcy, lch: [lchLab, labRgb, rgbSrgb, rgbHcy] },
12
+ toRgb: hcyRgb
18
13
  });
14
+ export {
15
+ hcy
16
+ };
package/hsi/hsi-rgb.js CHANGED
@@ -1,33 +1,35 @@
1
1
  import { setC3 } from "@thi.ng/vectors/setc";
2
2
  import { clampH } from "../clamp.js";
3
- // https://en.wikipedia.org/wiki/HSL_and_HSV#From_HSI
4
- export const hsiRgb = (out, src) => {
5
- out = clampH(out || src, src);
6
- const s = out[1];
7
- const i = out[2];
8
- if (s < 1e-6) {
9
- return setC3(out, i, i, i);
10
- }
11
- const h = (out[0] * 6) % 6;
12
- const m = i * (1 - s);
13
- const z = 1 - Math.abs((h % 2) - 1);
14
- let c = (3 * i * s) / (1 + z);
15
- const x = c * z + m;
16
- c += m;
17
- switch (h | 0) {
18
- case 0:
19
- return setC3(out, c, x, m);
20
- case 1:
21
- return setC3(out, x, c, m);
22
- case 2:
23
- return setC3(out, m, c, x);
24
- case 3:
25
- return setC3(out, m, x, c);
26
- case 4:
27
- return setC3(out, x, m, c);
28
- case 5:
29
- return setC3(out, c, m, x);
30
- default:
31
- return setC3(out, m, m, m);
32
- }
3
+ const hsiRgb = (out, src) => {
4
+ out = clampH(out || src, src);
5
+ const s = out[1];
6
+ const i = out[2];
7
+ if (s < 1e-6) {
8
+ return setC3(out, i, i, i);
9
+ }
10
+ const h = out[0] * 6 % 6;
11
+ const m = i * (1 - s);
12
+ const z = 1 - Math.abs(h % 2 - 1);
13
+ let c = 3 * i * s / (1 + z);
14
+ const x = c * z + m;
15
+ c += m;
16
+ switch (h | 0) {
17
+ case 0:
18
+ return setC3(out, c, x, m);
19
+ case 1:
20
+ return setC3(out, x, c, m);
21
+ case 2:
22
+ return setC3(out, m, c, x);
23
+ case 3:
24
+ return setC3(out, m, x, c);
25
+ case 4:
26
+ return setC3(out, x, m, c);
27
+ case 5:
28
+ return setC3(out, c, m, x);
29
+ default:
30
+ return setC3(out, m, m, m);
31
+ }
32
+ };
33
+ export {
34
+ hsiRgb
33
35
  };
package/hsi/hsi.js CHANGED
@@ -4,15 +4,13 @@ import { labRgb } from "../lab/lab-rgb.js";
4
4
  import { rgbHsi } from "../rgb/rgb-hsi.js";
5
5
  import { rgbSrgb } from "../rgb/rgb-srgb.js";
6
6
  import { hsiRgb } from "./hsi-rgb.js";
7
- /**
8
- * @remarks
9
- * Note: As with other hue-based color modes in this package, the hue is stored
10
- * normalized (in [0..1] interval) and NOT as degrees.
11
- */
12
- export const hsi = defColor({
13
- mode: "hsi",
14
- channels: { h: { hue: true } },
15
- order: ["h", "s", "i", "alpha"],
16
- from: { rgb: rgbHsi, srgb: rgbHsi, lch: [lchLab, labRgb, rgbSrgb, rgbHsi] },
17
- toRgb: hsiRgb,
7
+ const hsi = defColor({
8
+ mode: "hsi",
9
+ channels: { h: { hue: true } },
10
+ order: ["h", "s", "i", "alpha"],
11
+ from: { rgb: rgbHsi, srgb: rgbHsi, lch: [lchLab, labRgb, rgbSrgb, rgbHsi] },
12
+ toRgb: hsiRgb
18
13
  });
14
+ export {
15
+ hsi
16
+ };
package/hsl/hsl-css.js CHANGED
@@ -2,14 +2,13 @@ import { clamp01 } from "@thi.ng/math/interval";
2
2
  import { fract } from "@thi.ng/math/prec";
3
3
  import { FF, PC } from "../api/constants.js";
4
4
  import { __ensureAlpha } from "../internal/ensure.js";
5
- export const hslCss = (src) => {
6
- const h = FF(fract(src[0]) * 360);
7
- const s = PC(clamp01(src[1]));
8
- const l = PC(clamp01(src[2]));
9
- const a = __ensureAlpha(src[3]);
10
- // TODO update to new syntax once CSS Color L4 is more widely supported
11
- // https://www.w3.org/TR/css-color-4/#serializing-lab-lch
12
- // https://test.csswg.org/harness/results/css-color-4_dev/grouped/ (test reports)
13
- // return `hsl(${h} ${s} ${l}` + (a < 1 ? `/${FF(a)})` : ")");
14
- return a < 1 ? `hsla(${h},${s},${l},${FF(a)})` : `hsl(${h},${s},${l})`;
5
+ const hslCss = (src) => {
6
+ const h = FF(fract(src[0]) * 360);
7
+ const s = PC(clamp01(src[1]));
8
+ const l = PC(clamp01(src[2]));
9
+ const a = __ensureAlpha(src[3]);
10
+ return a < 1 ? `hsla(${h},${s},${l},${FF(a)})` : `hsl(${h},${s},${l})`;
11
+ };
12
+ export {
13
+ hslCss
15
14
  };
package/hsl/hsl-hsv.js CHANGED
@@ -1,11 +1,14 @@
1
1
  import { clampH } from "../clamp.js";
2
- export const hslHsv = (out, src) => {
3
- out = clampH(out || src, src);
4
- const s = out[1];
5
- const l = out[2];
6
- const l2 = 2 * l;
7
- const v = (l2 + s * (1 - Math.abs(l2 - 1))) * 0.5;
8
- out[1] = (2 * (v - l)) / v;
9
- out[2] = v;
10
- return out;
2
+ const hslHsv = (out, src) => {
3
+ out = clampH(out || src, src);
4
+ const s = out[1];
5
+ const l = out[2];
6
+ const l2 = 2 * l;
7
+ const v = (l2 + s * (1 - Math.abs(l2 - 1))) * 0.5;
8
+ out[1] = 2 * (v - l) / v;
9
+ out[2] = v;
10
+ return out;
11
+ };
12
+ export {
13
+ hslHsv
11
14
  };
package/hsl/hsl-rgb.js CHANGED
@@ -2,10 +2,18 @@ import { clamp01 } from "@thi.ng/math/interval";
2
2
  import { setC3 } from "@thi.ng/vectors/setc";
3
3
  import { hueRgb } from "../rgb/hue-rgb.js";
4
4
  import { __ensureAlpha } from "../internal/ensure.js";
5
- export const hslRgb = (out, src) => {
6
- const s = clamp01(src[1]);
7
- const l = clamp01(src[2]);
8
- out = hueRgb(out || src, src[0], __ensureAlpha(src[3]));
9
- const c = (1 - Math.abs(2 * l - 1)) * s;
10
- return setC3(out, (out[0] - 0.5) * c + l, (out[1] - 0.5) * c + l, (out[2] - 0.5) * c + l);
5
+ const hslRgb = (out, src) => {
6
+ const s = clamp01(src[1]);
7
+ const l = clamp01(src[2]);
8
+ out = hueRgb(out || src, src[0], __ensureAlpha(src[3]));
9
+ const c = (1 - Math.abs(2 * l - 1)) * s;
10
+ return setC3(
11
+ out,
12
+ (out[0] - 0.5) * c + l,
13
+ (out[1] - 0.5) * c + l,
14
+ (out[2] - 0.5) * c + l
15
+ );
16
+ };
17
+ export {
18
+ hslRgb
11
19
  };
package/hsl/hsl.js CHANGED
@@ -5,20 +5,18 @@ import { labRgb } from "../lab/lab-rgb.js";
5
5
  import { rgbHsl } from "../rgb/rgb-hsl.js";
6
6
  import { rgbSrgb } from "../rgb/rgb-srgb.js";
7
7
  import { hslRgb } from "./hsl-rgb.js";
8
- /**
9
- * @remarks
10
- * Note: As with other hue-based color modes in this package, the hue is stored
11
- * normalized (in [0..1] interval) and NOT as degrees.
12
- */
13
- export const hsl = defColor({
14
- mode: "hsl",
15
- channels: { h: { hue: true } },
16
- order: ["h", "s", "l", "alpha"],
17
- from: {
18
- rgb: rgbHsl,
19
- srgb: rgbHsl,
20
- hsv: hsvHsl,
21
- lch: [lchLab, labRgb, rgbSrgb, rgbHsl],
22
- },
23
- toRgb: hslRgb,
8
+ const hsl = defColor({
9
+ mode: "hsl",
10
+ channels: { h: { hue: true } },
11
+ order: ["h", "s", "l", "alpha"],
12
+ from: {
13
+ rgb: rgbHsl,
14
+ srgb: rgbHsl,
15
+ hsv: hsvHsl,
16
+ lch: [lchLab, labRgb, rgbSrgb, rgbHsl]
17
+ },
18
+ toRgb: hslRgb
24
19
  });
20
+ export {
21
+ hsl
22
+ };