@texel/color 1.1.4 → 1.1.6

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.
package/DOC.md ADDED
@@ -0,0 +1,17 @@
1
+ `@texel/color` is a minimal and modern color library for JavaScript. Especially useful for real-time applications, generative art, and graphics on the web.
2
+
3
+ ## Source Code
4
+
5
+ The source code is on GitHub:
6
+
7
+ [https://github.com/texel-org/color](https://github.com/texel-org/color)
8
+
9
+ ## Docs
10
+
11
+ The documentation is held here:
12
+
13
+ [https://texel-org.github.io/color](https://texel-org.github.io/color)
14
+
15
+ ## Usage
16
+
17
+ For installation and usage, see the [README.md page](https://github.com/texel-org/color/) on the GitHub repository.
package/README.md CHANGED
@@ -73,7 +73,13 @@ context.fillStyle = color;
73
73
  context.fillRect(0,0, canvas.width, canvas.height);
74
74
  ```
75
75
 
76
- ## API
76
+ ## API Docs
77
+
78
+ Auto-generated documentation with all exposed methods can be found here:
79
+
80
+ [https://texel-org.github.io/color](https://texel-org.github.io/color)
81
+
82
+ ## API Details
77
83
 
78
84
  #### `output = convert(coords, fromSpace, toSpace, output = [0, 0, 0])`
79
85
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@texel/color",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "a minimal and modern color library",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -10,20 +10,26 @@
10
10
  "url": "https://github.com/mattdesl"
11
11
  },
12
12
  "devDependencies": {
13
+ "better-docs": "^2.7.3",
13
14
  "canvas-sketch": "^0.7.7",
14
15
  "canvas-sketch-cli": "^1.11.21",
15
16
  "colorjs.io": "^0.5.2",
16
17
  "culori": "^4.0.1",
17
18
  "esbuild": "^0.23.0",
18
19
  "faucet": "^0.0.4",
20
+ "jsdoc": "^4.0.4",
19
21
  "pako": "^2.1.0",
20
22
  "png-tools": "^1.0.4",
21
23
  "prettier": "^3.3.3",
22
24
  "tape": "^5.8.1",
23
- "terser": "^5.31.3"
25
+ "terser": "^5.31.3",
26
+ "tsd-jsdoc": "^2.5.0"
24
27
  },
28
+ "types": "./types/types.d.ts",
25
29
  "scripts": {
26
30
  "visualize": "canvas-sketch-cli test/canvas-graph.js --open",
31
+ "docs": "jsdoc src -t node_modules/better-docs -c tools/.jsdoc.json -d docs -R DOC.md",
32
+ "types": "jsdoc src -t node_modules/tsd-jsdoc/dist -c tools/.jsdoc.types.json -d types",
27
33
  "test": "faucet test/test*.js",
28
34
  "bench": "node test/bench-colorjs.js",
29
35
  "bench:node": "NODE_ENV=production node --prof --no-logfile-per-isolate test/bench-node.js && node --prof-process v8.log",
package/src/core.js CHANGED
@@ -2,6 +2,48 @@ import { clamp, floatToByte, hexToRGB, vec3 } from "./util.js";
2
2
  import { LMS_to_OKLab_M, OKLab_to_LMS_M } from "./conversion_matrices.js";
3
3
  import { listColorSpaces, sRGB, XYZ } from "./spaces.js";
4
4
 
5
+ /**
6
+ * @typedef {number[][]} Matrix3x3
7
+ * @description A 3x3 matrix represented as an array of arrays.
8
+ * @example
9
+ * const matrix = [
10
+ * [a, b, c],
11
+ * [d, e, f],
12
+ * [g, h, i]
13
+ * ];
14
+ */
15
+
16
+ /**
17
+ * @typedef {number[]} Vector
18
+ * @description A n-dimensional vector represented as an array of numbers, typically in 3D (X, Y, Z).
19
+ * @example
20
+ * const vec = [ x, y, z ];
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} ChromaticAdaptation
25
+ * @property {Matrix3x3} from the matrix to convert from the source whitepoint to the destination whitepoint
26
+ * @property {Matrix3x3} to the matrix to convert from the destination whitepoint to the source whitepoint
27
+ */
28
+
29
+ /**
30
+ * @typedef {Object} ColorSpace
31
+ * @property {String} id the unique identifier for this color space in lowercase
32
+ * @property {Matrix3x3} [toXYZ_M] optional matrix to convert this color directly to XYZ D65
33
+ * @property {Matrix3x3} [fromXYZ_M] optional matrix to convert XYZ D65 to this color space
34
+ * @property {Matrix3x3} [toLMS_M] optional matrix to convert this color space to OKLab's LMS intermediary form
35
+ * @property {Matrix3x3} [fromLMS_M] optional matrix to convert OKLab's LMS intermediary form to this color space
36
+ * @property {ChromaticAdaptation} [adapt] optional chromatic adaptation matrices
37
+ * @property {ColorSpace} [base] an optional base color space that this space is derived from
38
+ * @property {function} [toBase] if a base color space exists, this maps the color to the base space form (e.g. gamma to the linear base space)
39
+ * @property {function} [fromBase] if a base color space exists, this maps the color from the base space form (e.g. the linear base space to the gamma space)
40
+ */
41
+
42
+ /**
43
+ * @typedef {Object} ColorGamut
44
+ * @property {ColorSpace} space the color space associated with this color gamut
45
+ */
46
+
5
47
  const tmp3 = vec3();
6
48
 
7
49
  const cubed3 = (lms) => {
@@ -21,18 +63,45 @@ const cbrt3 = (lms) => {
21
63
 
22
64
  const dot3 = (a, b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
23
65
 
66
+ /**
67
+ * Converts OKLab color to another color space.
68
+ * @param {Vector} OKLab The OKLab color.
69
+ * @param {Matrix3x3} LMS_to_output The transformation matrix from LMS to the output color space.
70
+ * @param {Vector} [out=vec3()] The output vector.
71
+ * @returns {Vector} The transformed color.
72
+ * @method
73
+ * @category oklab
74
+ */
24
75
  export const OKLab_to = (OKLab, LMS_to_output, out = vec3()) => {
25
76
  transform(OKLab, OKLab_to_LMS_M, out);
26
77
  cubed3(out);
27
78
  return transform(out, LMS_to_output, out);
28
79
  };
29
80
 
81
+ /**
82
+ * Converts a color from another color space to OKLab.
83
+ * @param {Vector} input The input color.
84
+ * @param {Matrix3x3} input_to_LMS The transformation matrix from the input color space to LMS.
85
+ * @param {Vector} [out=vec3()] The output vector.
86
+ * @returns {Vector} The transformed color.
87
+ * @method
88
+ * @category oklab
89
+ */
30
90
  export const OKLab_from = (input, input_to_LMS, out = vec3()) => {
31
91
  transform(input, input_to_LMS, out);
32
92
  cbrt3(out);
33
93
  return transform(out, LMS_to_OKLab_M, out);
34
94
  };
35
95
 
96
+ /**
97
+ * Transforms a color vector by the specified 3x3 transformation matrix.
98
+ * @param {Vector} input The input color.
99
+ * @param {Matrix3x3} matrix The transformation matrix.
100
+ * @param {Vector} [out=vec3()] The output vector.
101
+ * @returns {Vector} The transformed color.
102
+ * @method
103
+ * @category core
104
+ */
36
105
  export const transform = (input, matrix, out = vec3()) => {
37
106
  const x = dot3(input, matrix[0]);
38
107
  const y = dot3(input, matrix[1]);
@@ -49,6 +118,15 @@ const vec3Copy = (input, output) => {
49
118
  output[2] = input[2];
50
119
  };
51
120
 
121
+ /**
122
+ * Serializes a color to a CSS color string.
123
+ * @param {Vector} input The input color.
124
+ * @param {ColorSpace} inputSpace The input color space.
125
+ * @param {ColorSpace} [outputSpace=inputSpace] The output color space.
126
+ * @returns {string} The serialized color string.
127
+ * @method
128
+ * @category core
129
+ */
52
130
  export const serialize = (input, inputSpace, outputSpace = inputSpace) => {
53
131
  if (!inputSpace) throw new Error(`must specify an input space`);
54
132
  // extract alpha if present
@@ -86,13 +164,33 @@ const stripAlpha = (coords) => {
86
164
  return coords;
87
165
  };
88
166
 
89
- const parseFloatValue = str => parseFloat(str) || 0;
167
+ const parseFloatValue = (str) => parseFloat(str) || 0;
90
168
 
91
169
  const parseColorValue = (str, is255 = false) => {
92
170
  if (is255) return clamp(parseFloatValue(str) / 0xff, 0, 0xff);
93
- else return str.includes('%') ? parseFloatValue(str) / 100 : parseFloatValue(str);
171
+ else
172
+ return str.includes("%")
173
+ ? parseFloatValue(str) / 100
174
+ : parseFloatValue(str);
94
175
  };
95
176
 
177
+ /**
178
+ * Deserializes a color string to an object with <code>id</code> (color space string) and <code>coords</code> (the vector, in 3 or 4 dimensions).
179
+ * Note this does not return a <code>ColorSpace</code> object; you may want to use the example code below to map the string ID to a <code>ColorSpace</code>, but this will increase the size of your final bundle as it references all spaces.
180
+ *
181
+ * @example
182
+ * import { listColorSpaces, deserialize } from "@texel/color";
183
+ *
184
+ * const { id, coords } = deserialize(str);
185
+ * // now find the actual color space object
186
+ * const space = listColorSpaces().find((f) => id === f.id);
187
+ * console.log(space, coords);
188
+ *
189
+ * @param {string} input The color string to deserialize.
190
+ * @returns {{id: string, coords: Vector}} The deserialized color object.
191
+ * @method
192
+ * @category core
193
+ */
96
194
  export const deserialize = (input) => {
97
195
  if (typeof input !== "string") {
98
196
  throw new Error(`expected a string as input`);
@@ -114,9 +212,9 @@ export const deserialize = (input) => {
114
212
  throw new Error(`could not parse color string ${input}`);
115
213
  }
116
214
  const fn = parts[1].toLowerCase();
117
- if (/^rgba?$/i.test(fn) && parts[2].includes(',')) {
118
- const coords = parts[2].split(',').map((v, i) => {
119
- return parseColorValue(v.trim(), i < 3)
215
+ if (/^rgba?$/i.test(fn) && parts[2].includes(",")) {
216
+ const coords = parts[2].split(",").map((v, i) => {
217
+ return parseColorValue(v.trim(), i < 3);
120
218
  });
121
219
  return {
122
220
  id: "srgb",
@@ -139,7 +237,7 @@ export const deserialize = (input) => {
139
237
  if (/^(oklab|oklch)$/i.test(fn)) {
140
238
  id = fn;
141
239
  } else if (/rgba?/i.test(fn)) {
142
- id = 'srgb';
240
+ id = "srgb";
143
241
  div255 = true;
144
242
  } else {
145
243
  throw new Error(`unknown color function ${fn}`);
@@ -168,6 +266,15 @@ export const deserialize = (input) => {
168
266
  }
169
267
  };
170
268
 
269
+ /**
270
+ * Parses a color string and converts it to the target color space.
271
+ * @param {string} input The color string to parse.
272
+ * @param {ColorSpace} targetSpace The target color space.
273
+ * @param {Vector} [out=vec3()] The output vector.
274
+ * @returns {Vector} The parsed and converted color.
275
+ * @method
276
+ * @category core
277
+ */
171
278
  export const parse = (input, targetSpace, out = vec3()) => {
172
279
  if (!targetSpace)
173
280
  throw new Error(`must specify a target space to parse into`);
@@ -188,6 +295,16 @@ export const parse = (input, targetSpace, out = vec3()) => {
188
295
  return out;
189
296
  };
190
297
 
298
+ /**
299
+ * Converts a color from one color space to another.
300
+ * @param {Vector} input The input color.
301
+ * @param {ColorSpace} fromSpace The source color space.
302
+ * @param {ColorSpace} toSpace The target color space.
303
+ * @param {Vector} [out=vec3()] The output vector.
304
+ * @returns {Vector} The converted color.
305
+ * @method
306
+ * @category core
307
+ */
191
308
  export const convert = (input, fromSpace, toSpace, out = vec3()) => {
192
309
  // place into output
193
310
  vec3Copy(input, out);
@@ -310,8 +427,14 @@ export const convert = (input, fromSpace, toSpace, out = vec3()) => {
310
427
  return out;
311
428
  };
312
429
 
313
- // Calculate deltaE OK
314
- // simple root sum of squares
430
+ /**
431
+ * Calculates the DeltaEOK (color difference) between two OKLab colors.
432
+ * @param {Vector} oklab1 The first OKLab color.
433
+ * @param {Vector} oklab2 The second OKLab color.
434
+ * @returns {number} The delta E value.
435
+ * @method
436
+ * @category core
437
+ */
315
438
  export const deltaEOK = (oklab1, oklab2) => {
316
439
  let dL = oklab1[0] - oklab2[0];
317
440
  let da = oklab1[1] - oklab2[1];
package/src/gamut.js CHANGED
@@ -12,9 +12,37 @@ import { OKLab_to, convert } from "./core.js";
12
12
 
13
13
  const DEFAULT_ALPHA = 0.05;
14
14
 
15
+ /**
16
+ * @typedef {function} GamutMapMethod
17
+ * @description A function that maps an OKLCH color to a lightness value.
18
+ * @param {Vector} oklch The input OKLCH color
19
+ * @param {number[]} cusp A 2D cusp point in the form [L, C]
20
+ * @category mapping
21
+ */
22
+
23
+ /**
24
+ * A {@link GamutMapMethod} that maintains the color's lightness.
25
+ * @type {GamutMapMethod}
26
+ * @category mapping
27
+ */
15
28
  export const MapToL = (oklch) => oklch[0];
29
+ /**
30
+ * A {@link GamutMapMethod} that maps towards middle gray (L = 0.5).
31
+ * @type {GamutMapMethod}
32
+ * @category mapping
33
+ */
16
34
  export const MapToGray = () => 0.5;
35
+ /**
36
+ * A {@link GamutMapMethod} that maps towards the lightness of the current hue's cusp.
37
+ * @type {GamutMapMethod}
38
+ * @category mapping
39
+ */
17
40
  export const MapToCuspL = (_, cusp) => cusp[0];
41
+ /**
42
+ * A {@link GamutMapMethod} that adaptively maps towards gray.
43
+ * @type {GamutMapMethod}
44
+ * @category mapping
45
+ */
18
46
  export const MapToAdaptiveGray = (oklch, cusp) => {
19
47
  const Ld = oklch[0] - cusp[0];
20
48
  const k = 2 * (Ld > 0 ? 1 - cusp[0] : cusp[0]);
@@ -24,7 +52,11 @@ export const MapToAdaptiveGray = (oklch, cusp) => {
24
52
  0.5 * (Math.sign(Ld) * (e1 - Math.sqrt(e1 * e1 - 2 * k * Math.abs(Ld))))
25
53
  );
26
54
  };
27
-
55
+ /**
56
+ * A {@link GamutMapMethod} that adaptively maps towards the cusp's lightness.
57
+ * @type {GamutMapMethod}
58
+ * @category mapping
59
+ */
28
60
  export const MapToAdaptiveCuspL = (oklch) => {
29
61
  const Ld = oklch[0] - 0.5;
30
62
  const e1 = 0.5 + Math.abs(Ld) + DEFAULT_ALPHA * oklch[1];
@@ -55,6 +87,17 @@ const setYZ = (v, a, b) => {
55
87
  v[2] = b;
56
88
  };
57
89
 
90
+ /**
91
+ * Computes the maximum saturation (S = C/L) possible for a given hue that fits within
92
+ * the RGB gamut, using the given coefficients.
93
+ * @param {number} a The normalized a component of the hue.
94
+ * @param {number} b The normalized b component of the hue.
95
+ * @param {number[][]} lmsToRgb The LMS to RGB conversion matrix.
96
+ * @param {number[][][]} okCoeff The OKLab coefficients.
97
+ * @returns {number} The maximum saturation.
98
+ * @method
99
+ * @category mapping
100
+ */
58
101
  export const computeMaxSaturationOKLC = (a, b, lmsToRgb, okCoeff) => {
59
102
  // https://github.com/color-js/color.js/blob/main/src/spaces/okhsl.js
60
103
  // Finds the maximum saturation possible for a given hue that fits in RGB.
@@ -132,6 +175,13 @@ export const computeMaxSaturationOKLC = (a, b, lmsToRgb, okCoeff) => {
132
175
  return sat;
133
176
  };
134
177
 
178
+ /**
179
+ * Retrieves the LMS to RGB conversion matrix from the given gamut.
180
+ * @param {ColorGamut} gamut The gamut object.
181
+ * @returns {Matrix3x3} The LMS to RGB conversion matrix.
182
+ * @method
183
+ * @category mapping
184
+ */
135
185
  export const getGamutLMStoRGB = (gamut) => {
136
186
  if (!gamut) throw new Error(`expected gamut to have { space }`);
137
187
  const lmsToRGB = (gamut.space.base ?? gamut.space).fromLMS_M;
@@ -140,6 +190,16 @@ export const getGamutLMStoRGB = (gamut) => {
140
190
  return lmsToRGB;
141
191
  };
142
192
 
193
+ /**
194
+ * Finds the cusp of the OKLCH color space for a given hue.
195
+ * @param {number} a The normalized a component of the hue.
196
+ * @param {number} b The normalized b component of the hue.
197
+ * @param {ColorGamut} gamut The gamut object.
198
+ * @param {number[]} [out=[0, 0]] The output array to store the cusp values.
199
+ * @returns {number[]} The cusp values [L, C].
200
+ * @method
201
+ * @category mapping
202
+ */
143
203
  export const findCuspOKLCH = (a, b, gamut, out = [0, 0]) => {
144
204
  const lmsToRgb = getGamutLMStoRGB(gamut);
145
205
  const okCoeff = gamut.coefficients;
@@ -182,14 +242,14 @@ export const findGamutIntersectionOKLCH = (a, b, l1, c1, l0, cusp, gamut) => {
182
242
 
183
243
  // Find the intersection for upper and lower half separately
184
244
  if ((l1 - l0) * cusp[1] - (cusp[0] - l0) * c1 <= 0.0) {
185
- const denom = (c1 * cusp[0] + cusp[1] * (l0 - l1));
245
+ const denom = c1 * cusp[0] + cusp[1] * (l0 - l1);
186
246
  // Lower half
187
247
  t = denom === 0 ? 0 : (cusp[1] * l0) / denom;
188
248
  } else {
189
249
  // Upper half
190
250
 
191
251
  // First intersect with triangle
192
- const denom = (c1 * (cusp[0] - 1.0) + cusp[1] * (l0 - l1));
252
+ const denom = c1 * (cusp[0] - 1.0) + cusp[1] * (l0 - l1);
193
253
  t = denom === 0 ? 0 : (cusp[1] * (l0 - 1.0)) / denom;
194
254
 
195
255
  // Then one step Halley's method
@@ -256,7 +316,17 @@ export const findGamutIntersectionOKLCH = (a, b, l1, c1, l0, cusp, gamut) => {
256
316
  };
257
317
 
258
318
  /**
259
- * Takes any OKLCH value and maps it to fall within the given gamut.
319
+ * Applies fast approximate gamut mapping in OKLab space on the given OKLCH input color,
320
+ * using the specified gamut and converting to the target color space.
321
+ * @param {Vector} oklch The input OKLCH color that you wish to gamut map.
322
+ * @param {ColorGamut} [gamut=sRGBGamut] The gamut object.
323
+ * @param {ColorSpace} [targetSpace=gamut.space] The target color space.
324
+ * @param {Vector} [out=vec3()] The output array to store the mapped color.
325
+ * @param {GamutMapMethod} [mapping=MapToCuspL] The gamut mapping function.
326
+ * @param {Vector} [cusp] Optional, you can provide the cusp values [L, C] to avoid re-computing them.
327
+ * @returns {Vector} The mapped color in the target color space.
328
+ * @method
329
+ * @category mapping
260
330
  */
261
331
  export const gamutMapOKLCH = (
262
332
  oklch,
package/src/okhsl.js CHANGED
@@ -116,6 +116,16 @@ const getCs = (l, a, b, cusp, gamut) => {
116
116
  return [c0, cMid, cMax];
117
117
  };
118
118
 
119
+ /**
120
+ * Converts OKHSL color to OKLab color.
121
+ *
122
+ * @method
123
+ * @category oklab
124
+ * @param {Vector} hsl - The OKHSL color as an array [h, s, l].
125
+ * @param {ColorGamut} [gamut=sRGBGamut] - The color gamut.
126
+ * @param {Vector} [out=vec3()] - The output array to store the OKLab color.
127
+ * @returns {Vector} The OKLab color as an array [L, a, b].
128
+ */
119
129
  export const OKHSLToOKLab = (hsl, gamut = sRGBGamut, out = vec3()) => {
120
130
  // Convert Okhsl to Oklab.
121
131
  let h = hsl[0],
@@ -171,6 +181,16 @@ export const OKHSLToOKLab = (hsl, gamut = sRGBGamut, out = vec3()) => {
171
181
  return out;
172
182
  };
173
183
 
184
+ /**
185
+ * Converts OKLab color to OKHSL color.
186
+ *
187
+ * @method
188
+ * @category oklab
189
+ * @param {Vector} lab - The OKLab color as an array [L, a, b].
190
+ * @param {ColorGamut} [gamut=sRGBGamut] - The color gamut.
191
+ * @param {Vector} [out=vec3()] - The output array to store the OKHSL color.
192
+ * @returns {Vector} The OKHSL color as an array [h, s, l].
193
+ */
174
194
  export const OKLabToOKHSL = (lab, gamut = sRGBGamut, out = vec3()) => {
175
195
  // Oklab to Okhsl.
176
196
 
@@ -234,6 +254,16 @@ export const OKLabToOKHSL = (lab, gamut = sRGBGamut, out = vec3()) => {
234
254
  return out;
235
255
  };
236
256
 
257
+ /**
258
+ * Converts OKHSV color to OKLab color.
259
+ *
260
+ * @method
261
+ * @category oklab
262
+ * @param {Vector} hsv - The OKHSV color as an array [h, s, v].
263
+ * @param {ColorGamut} [gamut=sRGBGamut] - The color gamut.
264
+ * @param {Vector} [out=vec3()] - The output array to store the OKLab color.
265
+ * @returns {Vector} The OKLab color as an array [L, a, b].
266
+ */
237
267
  export const OKHSVToOKLab = (hsv, gamut = sRGBGamut, out = vec3()) => {
238
268
  // Convert from Okhsv to Oklab."""
239
269
 
@@ -288,6 +318,16 @@ export const OKHSVToOKLab = (hsv, gamut = sRGBGamut, out = vec3()) => {
288
318
  return out;
289
319
  };
290
320
 
321
+ /**
322
+ * Converts OKLab color to OKHSV color.
323
+ *
324
+ * @method
325
+ * @category oklab
326
+ * @param {Vector} lab The OKLab color as an array [L, a, b].
327
+ * @param {ColorGamut} [gamut=sRGBGamut] The color gamut.
328
+ * @param {Vector} [out=vec3()] The output array to store the OKHSV color.
329
+ * @returns {Vector} The OKHSV color as an array [h, s, v].
330
+ */
291
331
  export const OKLabToOKHSV = (lab, gamut = sRGBGamut, out = vec3()) => {
292
332
  // Oklab to Okhsv.
293
333
  const lmsToRgb = getGamutLMStoRGB(gamut);
@@ -19,6 +19,11 @@ const A98RGBToGamma = (val) => {
19
19
  return sign * Math.pow(abs, 256 / 563);
20
20
  };
21
21
 
22
+ /**
23
+ * The Adobe RGB (1998) color space in linear form, without a transfer function, aliased as <code>"a98-rgb-linear"</code>.
24
+ * @type {ColorSpace}
25
+ * @category spaces
26
+ */
22
27
  export const A98RGBLinear = {
23
28
  id: "a98-rgb-linear",
24
29
  toXYZ_M: linear_A98RGB_to_XYZ_M,
@@ -27,6 +32,11 @@ export const A98RGBLinear = {
27
32
  fromLMS_M: LMS_to_linear_A98RGB_M,
28
33
  };
29
34
 
35
+ /**
36
+ * The Adobe RGB (1998) color space, with a transfer function, aliased as <code>"a98-rgb"</code>. Inherits from the {@link A98RGBLinear} color space.
37
+ * @type {ColorSpace}
38
+ * @category spaces
39
+ */
30
40
  export const A98RGB = {
31
41
  id: "a98-rgb",
32
42
  base: A98RGBLinear,
@@ -44,6 +54,11 @@ export const A98RGB = {
44
54
  },
45
55
  };
46
56
 
57
+ /**
58
+ * A color gamut for the {@link A98RGB}, or Adobe RGB (1998), color space.
59
+ * @type {ColorGamut}
60
+ * @category gamuts
61
+ */
47
62
  export const A98RGBGamut = {
48
63
  space: A98RGB,
49
64
  coefficients: OKLab_to_linear_A98RGB_coefficients,
@@ -7,6 +7,11 @@ import {
7
7
  } from "../conversion_matrices.js";
8
8
  import { sRGBGammaToLinearVec3, sRGBLinearToGammaVec3 } from "./util.js";
9
9
 
10
+ /**
11
+ * The Display-P3 color space in linear form, without a transfer function, aliased as <code>"display-p3-linear"</code>.
12
+ * @type {ColorSpace}
13
+ * @category spaces
14
+ */
10
15
  export const DisplayP3Linear = {
11
16
  id: "display-p3-linear",
12
17
  toXYZ_M: linear_DisplayP3_to_XYZ_M,
@@ -15,6 +20,11 @@ export const DisplayP3Linear = {
15
20
  fromLMS_M: LMS_to_linear_DisplayP3_M,
16
21
  };
17
22
 
23
+ /**
24
+ * The Display-P3 color space, with a transfer function, aliased as <code>"display-p3"</code>. Inherits from the {@link DisplayP3Linear} color space.
25
+ * @type {ColorSpace}
26
+ * @category spaces
27
+ */
18
28
  export const DisplayP3 = {
19
29
  id: "display-p3",
20
30
  base: DisplayP3Linear,
@@ -22,6 +32,11 @@ export const DisplayP3 = {
22
32
  fromBase: sRGBLinearToGammaVec3,
23
33
  };
24
34
 
35
+ /**
36
+ * A color gamut for the {@link DisplayP3} color space.
37
+ * @type {ColorGamut}
38
+ * @category gamuts
39
+ */
25
40
  export const DisplayP3Gamut = {
26
41
  space: DisplayP3,
27
42
  coefficients: OKLab_to_linear_DisplayP3_coefficients,
@@ -13,10 +13,20 @@ import { sRGBGamut } from "./srgb.js";
13
13
  // based on colorjs.io, could perhaps use a more specific number than this
14
14
  const ACHROMATIC_EPSILON = (0.4 - 0.0) / 100000;
15
15
 
16
+ /**
17
+ * The OKLab color space.
18
+ * @type {ColorSpace}
19
+ * @category spaces
20
+ */
16
21
  export const OKLab = {
17
22
  id: "oklab",
18
23
  };
19
24
 
25
+ /**
26
+ * The OKLCH color space, with Lightness, Chroma, and Hue components. This is the cylindrical form of the {@link OKLab} color space.
27
+ * @type {ColorSpace}
28
+ * @category spaces
29
+ */
20
30
  export const OKLCH = {
21
31
  id: "oklch",
22
32
  base: OKLab,
@@ -51,6 +61,13 @@ export const OKLCH = {
51
61
  },
52
62
  };
53
63
 
64
+ /**
65
+ * An implementation of the OKHSL color space, fixed to the {@link sRGBGamut}. This is useful for color pickers and other applications where
66
+ * you wish to work with components in a well-defined and enclosed cylindrical form. If you wish to use OKHSL with a different gamut, you'll
67
+ * need to use the {@link OKHSLToOKLab} and {@link OKLabToOKHSL} methods directly, passing your desired gamut.
68
+ * @type {ColorSpace}
69
+ * @category spaces
70
+ */
54
71
  export const OKHSL = {
55
72
  // Note: sRGB gamut only
56
73
  // For other gamuts, use okhsl method directly
@@ -60,6 +77,13 @@ export const OKHSL = {
60
77
  fromBase: (oklab, out = vec3()) => OKLabToOKHSL(oklab, sRGBGamut, out),
61
78
  };
62
79
 
80
+ /**
81
+ * An implementation of the OKHSV color space, fixed to the {@link sRGBGamut}. This is useful for color pickers and other applications where
82
+ * you wish to work with components in a well-defined and enclosed cylindrical form. If you wish to use OKHSL with a different gamut, you'll
83
+ * need to use the {@link OKHSLToOKLab} and {@link OKLabToOKHSL} methods directly, passing your desired gamut.
84
+ * @type {ColorSpace}
85
+ * @category spaces
86
+ */
63
87
  export const OKHSV = {
64
88
  // Note: sRGB gamut only
65
89
  // For other gamuts, use okhsv method directly
@@ -35,6 +35,11 @@ const ProPhotoRGBToGamma = (v) => (v >= Et ? v ** (1 / 1.8) : 16 * v);
35
35
  // return abs >= Et ? sign * Math.pow(abs, 1 / 1.8) : 16 * val;
36
36
  // };
37
37
 
38
+ /**
39
+ * The ProPhotoRGB color space in linear form, without a transfer function, aliased as <code>"prophoto-rgb-linear"</code>.
40
+ * @type {ColorSpace}
41
+ * @category spaces
42
+ */
38
43
  export const ProPhotoRGBLinear = {
39
44
  id: "prophoto-rgb-linear",
40
45
  adapt: {
@@ -47,6 +52,11 @@ export const ProPhotoRGBLinear = {
47
52
  fromXYZ_M: XYZ_to_linear_ProPhotoRGB_M,
48
53
  };
49
54
 
55
+ /**
56
+ * The ProPhotoRGB color space, with a transfer function, aliased as <code>"prophoto-rgb"</code>. Inherits from the {@link ProPhotoRGBLinear} color space.
57
+ * @type {ColorSpace}
58
+ * @category spaces
59
+ */
50
60
  export const ProPhotoRGB = {
51
61
  id: "prophoto-rgb",
52
62
  base: ProPhotoRGBLinear,
@@ -16,6 +16,11 @@ const Rec2020ToLinear = (val) =>
16
16
  const Rec2020ToGamma = (val) =>
17
17
  val >= BETA ? ALPHA * Math.pow(val, 0.45) - (ALPHA - 1) : 4.5 * val;
18
18
 
19
+ /**
20
+ * The Rec2020 color space in linear form, without a transfer function, aliased as <code>"rec2020-linear"</code>.
21
+ * @type {ColorSpace}
22
+ * @category spaces
23
+ */
19
24
  export const Rec2020Linear = {
20
25
  id: "rec2020-linear",
21
26
  toXYZ_M: linear_Rec2020_to_XYZ_M,
@@ -24,6 +29,11 @@ export const Rec2020Linear = {
24
29
  fromLMS_M: LMS_to_linear_Rec2020_M,
25
30
  };
26
31
 
32
+ /**
33
+ * The Rec2020 color space, with a transfer function, aliased as <code>"rec2020"</code>. Inherits from the {@link Rec2020Linear} color space.
34
+ * @type {ColorSpace}
35
+ * @category spaces
36
+ */
27
37
  export const Rec2020 = {
28
38
  id: "rec2020",
29
39
  base: Rec2020Linear,
@@ -41,6 +51,11 @@ export const Rec2020 = {
41
51
  },
42
52
  };
43
53
 
54
+ /**
55
+ * A color gamut for the {@link Rec2020} color space.
56
+ * @type {ColorGamut}
57
+ * @category gamuts
58
+ */
44
59
  export const Rec2020Gamut = {
45
60
  space: Rec2020,
46
61
  coefficients: OKLab_to_linear_Rec2020_coefficients,
@@ -8,6 +8,11 @@ import {
8
8
 
9
9
  import { sRGBGammaToLinearVec3, sRGBLinearToGammaVec3 } from "./util.js";
10
10
 
11
+ /**
12
+ * The sRGB color space in linear form, without a transfer function, aliased as <code>"srgb-linear"</code>.
13
+ * @type {ColorSpace}
14
+ * @category spaces
15
+ */
11
16
  export const sRGBLinear = {
12
17
  id: "srgb-linear",
13
18
  toXYZ_M: linear_sRGB_to_XYZ_M,
@@ -16,6 +21,11 @@ export const sRGBLinear = {
16
21
  fromLMS_M: LMS_to_linear_sRGB_M,
17
22
  };
18
23
 
24
+ /**
25
+ * The sRGB color space, with a transfer function, aliased as <code>"srgb"</code>. Inherits from the {@link sRGBLinear} color space.
26
+ * @type {ColorSpace}
27
+ * @category spaces
28
+ */
19
29
  export const sRGB = {
20
30
  id: "srgb",
21
31
  base: sRGBLinear,
@@ -23,6 +33,11 @@ export const sRGB = {
23
33
  fromBase: sRGBLinearToGammaVec3,
24
34
  };
25
35
 
36
+ /**
37
+ * A color gamut for the {@link sRGB} color space.
38
+ * @type {ColorGamut}
39
+ * @category gamuts
40
+ */
26
41
  export const sRGBGamut = {
27
42
  space: sRGB,
28
43
  coefficients: OKLab_to_linear_sRGB_coefficients,
@@ -1,5 +1,12 @@
1
1
  import { vec3 } from "../util.js";
2
2
 
3
+ /**
4
+ * Converts a single sRGB gamma-corrected channel value to linear light (un-companded) form.
5
+ * @param {number} val - The sRGB gamma-corrected channel value in the range [0, 1].
6
+ * @returns {number} The linear light channel value.
7
+ * @method
8
+ * @category rgb
9
+ */
3
10
  export const sRGBGammaToLinear = (val) => {
4
11
  // convert a single channel value
5
12
  // where in-gamut values are in the range [0 - 1]
@@ -15,6 +22,13 @@ export const sRGBGammaToLinear = (val) => {
15
22
  : sign * Math.pow((abs + 0.055) / 1.055, 2.4);
16
23
  };
17
24
 
25
+ /**
26
+ * Converts a single linear-light channel value to sRGB gamma-corrected form.
27
+ * @param {number} val - The linear-light channel value in the range [0, 1].
28
+ * @returns {number} The sRGB gamma-corrected channel value.
29
+ * @method
30
+ * @category rgb
31
+ */
18
32
  export const sRGBLinearToGamma = (val) => {
19
33
  // convert a single channel linear-light value in range 0-1
20
34
  // to gamma corrected form
package/src/spaces/xyz.js CHANGED
@@ -28,20 +28,44 @@ export const D50_to_D65_M = [
28
28
  [0.012314014864481998, -0.020507649298898964, 1.330365926242124],
29
29
  ];
30
30
 
31
+ /**
32
+ * Converts a color from XYZ with D65 whitepoint to XYZ with D50 whitepoint.
33
+ * @method
34
+ * @category xyz
35
+ * @param {Vector} XYZ - The input color in XYZ with D65 whitepoint.
36
+ * @param {Vector} [out=vec3()] - The output color in XYZ with D50 whitepoint.
37
+ * @returns {Vector} The converted color in XYZ with D50 whitepoint.
38
+ */
31
39
  export const XYZD65ToD50 = (XYZ, out = vec3()) =>
32
40
  transform(XYZ, D65_to_D50_M, out);
33
41
 
42
+ /**
43
+ * Converts a color from XYZ with D50 whitepoint to XYZ with D65 whitepoint.
44
+ * @method
45
+ * @category xyz
46
+ * @param {Vector} XYZ - The input color in XYZ with D50 whitepoint.
47
+ * @param {Vector} [out=vec3()] - The output color in XYZ with D65 whitepoint.
48
+ * @returns {Vector} The converted color in XYZ with D65 whitepoint.
49
+ */
34
50
  export const XYZD50ToD65 = (XYZ, out = vec3()) =>
35
51
  transform(XYZ, D50_to_D65_M, out);
36
52
 
37
- // XYZ using D65 whitepoint
53
+ /**
54
+ * XYZ color space with D65 whitepoint, aliased as <code>"xyz"</code>.
55
+ * @type {ColorSpace}
56
+ * @category spaces
57
+ */
38
58
  export const XYZ = {
39
59
  id: "xyz", // xyz-d65
40
60
  toLMS_M: XYZ_to_LMS_M,
41
61
  fromLMS_M: LMS_to_XYZ_M,
42
62
  };
43
63
 
44
- // XYZ using D50 whitepoint
64
+ /**
65
+ * XYZ color space with D50 whitepoint, aliased as <code>"xyz-d50"</code>.
66
+ * @type {ColorSpace}
67
+ * @category spaces
68
+ */
45
69
  export const XYZD50 = {
46
70
  id: "xyz-d50",
47
71
  base: XYZ,
package/src/spaces.js CHANGED
@@ -18,6 +18,13 @@ export * from "./spaces/rec2020.js";
18
18
  export * from "./spaces/a98-rgb.js";
19
19
  export * from "./spaces/prophoto-rgb.js";
20
20
 
21
+ /**
22
+ * Returns a list of color spaces.
23
+ *
24
+ * @method
25
+ * @returns {ColorSpace[]} An array of color space objects.
26
+ * @category core
27
+ */
21
28
  export const listColorSpaces = () => {
22
29
  return [
23
30
  XYZ, // D65
@@ -39,6 +46,13 @@ export const listColorSpaces = () => {
39
46
  ];
40
47
  };
41
48
 
49
+ /**
50
+ * Returns a list of color gamuts.
51
+ *
52
+ * @method
53
+ * @returns {ColorGamut[]} An array of color gamut objects.
54
+ * @category core
55
+ */
42
56
  export const listColorGamuts = () => {
43
57
  return [sRGBGamut, DisplayP3Gamut, Rec2020Gamut, A98RGBGamut];
44
58
  };
package/src/util.js CHANGED
@@ -1,15 +1,60 @@
1
- const GAMUT_EPSILON = 0.000075;
2
-
1
+ /**
2
+ * Clamps a value between a minimum and maximum value.
3
+ * @method
4
+ * @param {number} value The value to clamp.
5
+ * @param {number} min The minimum value.
6
+ * @param {number} max The maximum value.
7
+ * @returns {number} The clamped value.
8
+ * @category utils
9
+ */
3
10
  export const clamp = (value, min, max) => Math.max(Math.min(value, max), min);
4
11
 
12
+ /**
13
+ * Linearly interpolates between two values.
14
+ * @method
15
+ * @param {number} min The start value.
16
+ * @param {number} max The end value.
17
+ * @param {number} t The interpolation factor between 0 and 1.
18
+ * @returns {number} The interpolated value.
19
+ * @category utils
20
+ */
5
21
  export const lerp = (min, max, t) => min * (1 - t) + max * t;
6
22
 
23
+ /**
24
+ * Converts degrees to radians.
25
+ * @method
26
+ * @param {number} n The angle in degrees.
27
+ * @returns {number} The angle in radians.
28
+ * @category utils
29
+ */
7
30
  export const degToRad = (n) => (n * Math.PI) / 180;
8
31
 
32
+ /**
33
+ * Converts radians to degrees.
34
+ * @method
35
+ * @param {number} n The angle in radians.
36
+ * @returns {number} The angle in degrees.
37
+ * @category utils
38
+ */
9
39
  export const radToDeg = (n) => (n * 180) / Math.PI;
10
40
 
41
+ /**
42
+ * Constrains an angle to the range [0, 360).
43
+ * @method
44
+ * @param {number} angle The angle in degrees.
45
+ * @returns {number} The constrained angle.
46
+ * @category utils
47
+ */
11
48
  export const constrainAngle = (angle) => ((angle % 360) + 360) % 360;
12
49
 
50
+ /**
51
+ * Converts a hex color string to an RGB array.
52
+ * @method
53
+ * @param {string} str The hex color string.
54
+ * @param {Vector} [out=vec3()] The output array.
55
+ * @returns {Vector} The RGB array.
56
+ * @category rgb
57
+ */
13
58
  export const hexToRGB = (str, out = vec3()) => {
14
59
  let hex = str.replace(/#/, "");
15
60
  if (hex.length === 3) {
@@ -26,12 +71,31 @@ export const hexToRGB = (str, out = vec3()) => {
26
71
  return out;
27
72
  };
28
73
 
74
+ /**
75
+ * Converts an RGB array to a hex color string.
76
+ * @method
77
+ * @param {Vector} rgb The RGB array.
78
+ * @returns {string} The hex color string.
79
+ * @category rgb
80
+ */
29
81
  export const RGBToHex = (rgb) =>
30
82
  `#${rgb.map((n) => floatToByte(n).toString(16).padStart(2, "0")).join("")}`;
31
83
 
32
- /** @deprecated use RGBToHex */
84
+ /**
85
+ * @method
86
+ * @deprecated Use RGBToHex instead.
87
+ * @category rgb
88
+ */
33
89
  export const RGBtoHex = RGBToHex;
34
90
 
91
+ /**
92
+ * Checks if an RGB color is within the gamut.
93
+ * @method
94
+ * @param {Vector} lrgb The linear RGB array.
95
+ * @param {number} [ep=GAMUT_EPSILON] The epsilon value for comparison.
96
+ * @returns {boolean} True if the color is within the gamut, false otherwise.
97
+ * @category rgb
98
+ */
35
99
  export const isRGBInGamut = (lrgb, ep = GAMUT_EPSILON) => {
36
100
  const r = lrgb[0];
37
101
  const g = lrgb[1];
@@ -46,6 +110,14 @@ export const isRGBInGamut = (lrgb, ep = GAMUT_EPSILON) => {
46
110
  );
47
111
  };
48
112
 
113
+ /**
114
+ * Clamps an RGB array to the range [0, 1].
115
+ * @method
116
+ * @param {Vector} rgb The RGB array.
117
+ * @param {Vector} [out=vec3()] The output array.
118
+ * @returns {Vector} The clamped RGB array.
119
+ * @category rgb
120
+ */
49
121
  export const clampedRGB = (rgb, out = vec3()) => {
50
122
  out[0] = clamp(rgb[0], 0, 1);
51
123
  out[1] = clamp(rgb[1], 0, 1);
@@ -53,6 +125,14 @@ export const clampedRGB = (rgb, out = vec3()) => {
53
125
  return out;
54
126
  };
55
127
 
128
+ /**
129
+ * Converts xyY color space to XYZ color space.
130
+ * @method
131
+ * @param {Vector} arg The xyY array.
132
+ * @param {Vector} [out=vec3()] The output array.
133
+ * @returns {Vector} The XYZ array.
134
+ * @category xyz
135
+ */
56
136
  export const xyY_to_XYZ = (arg, out = vec3()) => {
57
137
  let X, Y, Z, x, y;
58
138
  x = arg[0];
@@ -70,6 +150,14 @@ export const xyY_to_XYZ = (arg, out = vec3()) => {
70
150
  return out;
71
151
  };
72
152
 
153
+ /**
154
+ * Converts XYZ color space to xyY color space.
155
+ * @method
156
+ * @param {Vector} arg The XYZ array.
157
+ * @param {Vector} [out=vec3()] The output array.
158
+ * @returns {Vector} The xyY array.
159
+ * @category xyz
160
+ */
73
161
  export const XYZ_to_xyY = (arg, out = vec3()) => {
74
162
  let sum, X, Y, Z;
75
163
  X = arg[0];
@@ -87,29 +175,43 @@ export const XYZ_to_xyY = (arg, out = vec3()) => {
87
175
  return out;
88
176
  };
89
177
 
178
+ /**
179
+ * Converts a float value to a byte value.
180
+ * @method
181
+ * @param {number} n The float value.
182
+ * @returns {number} The byte value.
183
+ * @category utils
184
+ */
90
185
  export const floatToByte = (n) => clamp(Math.round(255 * n), 0, 255);
91
186
 
92
- // Undocumented
93
-
187
+ /**
188
+ * Creates a new vec3 array.
189
+ * @method
190
+ * @returns {Vector} The vec3 array.
191
+ * @category utils
192
+ */
94
193
  export const vec3 = () => [0, 0, 0];
95
194
 
96
- // export const normalizeHue = (hue) => ((hue = hue % 360) < 0 ? hue + 360 : hue);
97
-
98
- // in degrees
99
- // export const angle_delta = (angle1, angle2) => {
100
- // const diff = ((angle2 - angle1 + 180) % 360) - 180;
101
- // return diff < -180 ? diff + 360 : diff;
102
- // };
103
-
104
- // function shortAngleDistRad(a0, a1) {
105
- // var max = Math.PI * 2;
106
- // var da = (a1 - a0) % max;
107
- // return ((2 * da) % max) - da;
108
- // }
109
-
195
+ /**
196
+ * Calculates the delta angle between two angles.
197
+ * @method
198
+ * @param {number} a0 The first angle in degrees.
199
+ * @param {number} a1 The second angle in degrees.
200
+ * @returns {number} The delta angle in degrees.
201
+ * @category utils
202
+ */
110
203
  export const deltaAngle = (a0, a1) => {
111
204
  var da = (a1 - a0) % 360;
112
205
  return ((2 * da) % 360) - da;
113
206
  };
114
207
 
208
+ /**
209
+ * Linearly interpolates between two angles.
210
+ * @method
211
+ * @param {number} a0 The start angle in degrees.
212
+ * @param {number} a1 The end angle in degrees.
213
+ * @param {number} t The interpolation factor between 0 and 1.
214
+ * @returns {number} The interpolated angle in degrees.
215
+ * @category utils
216
+ */
115
217
  export const lerpAngle = (a0, a1, t) => a0 + deltaAngle(a0, a1) * t;
@@ -0,0 +1,332 @@
1
+ declare module "@texel/color" {
2
+ /**
3
+ * A 3x3 matrix represented as an array of arrays.
4
+ * @example
5
+ * const matrix = [
6
+ * [a, b, c],
7
+ * [d, e, f],
8
+ * [g, h, i]
9
+ * ];
10
+ */
11
+ type Matrix3x3 = number[][];
12
+ /**
13
+ * A n-dimensional vector represented as an array of numbers, typically in 3D (X, Y, Z).
14
+ * @example
15
+ * const vec = [ x, y, z ];
16
+ */
17
+ type Vector = number[];
18
+ /**
19
+ * @property from - the matrix to convert from the source whitepoint to the destination whitepoint
20
+ * @property to - the matrix to convert from the destination whitepoint to the source whitepoint
21
+ */
22
+ type ChromaticAdaptation = {
23
+ from: Matrix3x3;
24
+ to: Matrix3x3;
25
+ };
26
+ /**
27
+ * @property id - the unique identifier for this color space in lowercase
28
+ * @property [toXYZ_M] - optional matrix to convert this color directly to XYZ D65
29
+ * @property [fromXYZ_M] - optional matrix to convert XYZ D65 to this color space
30
+ * @property [toLMS_M] - optional matrix to convert this color space to OKLab's LMS intermediary form
31
+ * @property [fromLMS_M] - optional matrix to convert OKLab's LMS intermediary form to this color space
32
+ * @property [adapt] - optional chromatic adaptation matrices
33
+ * @property [base] - an optional base color space that this space is derived from
34
+ * @property [toBase] - if a base color space exists, this maps the color to the base space form (e.g. gamma to the linear base space)
35
+ * @property [fromBase] - if a base color space exists, this maps the color from the base space form (e.g. the linear base space to the gamma space)
36
+ */
37
+ type ColorSpace = {
38
+ id: string;
39
+ toXYZ_M?: Matrix3x3;
40
+ fromXYZ_M?: Matrix3x3;
41
+ toLMS_M?: Matrix3x3;
42
+ fromLMS_M?: Matrix3x3;
43
+ adapt?: ChromaticAdaptation;
44
+ base?: ColorSpace;
45
+ toBase?: (...params: any[]) => any;
46
+ fromBase?: (...params: any[]) => any;
47
+ };
48
+ /**
49
+ * @property space - the color space associated with this color gamut
50
+ */
51
+ type ColorGamut = {
52
+ space: ColorSpace;
53
+ };
54
+ /**
55
+ * Converts OKLab color to another color space.
56
+ * @param OKLab - The OKLab color.
57
+ * @param LMS_to_output - The transformation matrix from LMS to the output color space.
58
+ * @param [out = vec3()] - The output vector.
59
+ * @returns The transformed color.
60
+ */
61
+ function OKLab_to(OKLab: Vector, LMS_to_output: Matrix3x3, out?: Vector): Vector;
62
+ /**
63
+ * Converts a color from another color space to OKLab.
64
+ * @param input - The input color.
65
+ * @param input_to_LMS - The transformation matrix from the input color space to LMS.
66
+ * @param [out = vec3()] - The output vector.
67
+ * @returns The transformed color.
68
+ */
69
+ function OKLab_from(input: Vector, input_to_LMS: Matrix3x3, out?: Vector): Vector;
70
+ /**
71
+ * Transforms a color vector by the specified 3x3 transformation matrix.
72
+ * @param input - The input color.
73
+ * @param matrix - The transformation matrix.
74
+ * @param [out = vec3()] - The output vector.
75
+ * @returns The transformed color.
76
+ */
77
+ function transform(input: Vector, matrix: Matrix3x3, out?: Vector): Vector;
78
+ /**
79
+ * Serializes a color to a CSS color string.
80
+ * @param input - The input color.
81
+ * @param inputSpace - The input color space.
82
+ * @param [outputSpace = inputSpace] - The output color space.
83
+ * @returns The serialized color string.
84
+ */
85
+ function serialize(input: Vector, inputSpace: ColorSpace, outputSpace?: ColorSpace): string;
86
+ /**
87
+ * Deserializes a color string to an object with <code>id</code> (color space string) and <code>coords</code> (the vector, in 3 or 4 dimensions).
88
+ * Note this does not return a <code>ColorSpace</code> object; you may want to use the example code below to map the string ID to a <code>ColorSpace</code>, but this will increase the size of your final bundle as it references all spaces.
89
+ * @example
90
+ * import { listColorSpaces, deserialize } from "@texel/color";
91
+ *
92
+ * const { id, coords } = deserialize(str);
93
+ * // now find the actual color space object
94
+ * const space = listColorSpaces().find((f) => id === f.id);
95
+ * console.log(space, coords);
96
+ * @param input - The color string to deserialize.
97
+ * @returns The deserialized color object.
98
+ */
99
+ function deserialize(input: string): any;
100
+ /**
101
+ * Parses a color string and converts it to the target color space.
102
+ * @param input - The color string to parse.
103
+ * @param targetSpace - The target color space.
104
+ * @param [out = vec3()] - The output vector.
105
+ * @returns The parsed and converted color.
106
+ */
107
+ function parse(input: string, targetSpace: ColorSpace, out?: Vector): Vector;
108
+ /**
109
+ * Converts a color from one color space to another.
110
+ * @param input - The input color.
111
+ * @param fromSpace - The source color space.
112
+ * @param toSpace - The target color space.
113
+ * @param [out = vec3()] - The output vector.
114
+ * @returns The converted color.
115
+ */
116
+ function convert(input: Vector, fromSpace: ColorSpace, toSpace: ColorSpace, out?: Vector): Vector;
117
+ /**
118
+ * Calculates the DeltaEOK (color difference) between two OKLab colors.
119
+ * @param oklab1 - The first OKLab color.
120
+ * @param oklab2 - The second OKLab color.
121
+ * @returns The delta E value.
122
+ */
123
+ function deltaEOK(oklab1: Vector, oklab2: Vector): number;
124
+ /**
125
+ * A function that maps an OKLCH color to a lightness value.
126
+ * @param oklch - The input OKLCH color
127
+ * @param cusp - A 2D cusp point in the form [L, C]
128
+ */
129
+ type GamutMapMethod = (oklch: Vector, cusp: number[]) => void;
130
+ /**
131
+ * A {@link GamutMapMethod} that maintains the color's lightness.
132
+ */
133
+ const MapToL: GamutMapMethod;
134
+ /**
135
+ * A {@link GamutMapMethod} that maps towards middle gray (L = 0.5).
136
+ */
137
+ const MapToGray: GamutMapMethod;
138
+ /**
139
+ * A {@link GamutMapMethod} that maps towards the lightness of the current hue's cusp.
140
+ */
141
+ const MapToCuspL: GamutMapMethod;
142
+ /**
143
+ * A {@link GamutMapMethod} that adaptively maps towards gray.
144
+ */
145
+ const MapToAdaptiveGray: GamutMapMethod;
146
+ /**
147
+ * A {@link GamutMapMethod} that adaptively maps towards the cusp's lightness.
148
+ */
149
+ const MapToAdaptiveCuspL: GamutMapMethod;
150
+ /**
151
+ * Computes the maximum saturation (S = C/L) possible for a given hue that fits within
152
+ * the RGB gamut, using the given coefficients.
153
+ * @param a - The normalized a component of the hue.
154
+ * @param b - The normalized b component of the hue.
155
+ * @param lmsToRgb - The LMS to RGB conversion matrix.
156
+ * @param okCoeff - The OKLab coefficients.
157
+ * @returns The maximum saturation.
158
+ */
159
+ function computeMaxSaturationOKLC(a: number, b: number, lmsToRgb: number[][], okCoeff: number[][][]): number;
160
+ /**
161
+ * Retrieves the LMS to RGB conversion matrix from the given gamut.
162
+ * @param gamut - The gamut object.
163
+ * @returns The LMS to RGB conversion matrix.
164
+ */
165
+ function getGamutLMStoRGB(gamut: ColorGamut): Matrix3x3;
166
+ /**
167
+ * Finds the cusp of the OKLCH color space for a given hue.
168
+ * @param a - The normalized a component of the hue.
169
+ * @param b - The normalized b component of the hue.
170
+ * @param gamut - The gamut object.
171
+ * @param [out = [0, 0]] - The output array to store the cusp values.
172
+ * @returns The cusp values [L, C].
173
+ */
174
+ function findCuspOKLCH(a: number, b: number, gamut: ColorGamut, out?: number[]): number[];
175
+ /**
176
+ * Applies fast approximate gamut mapping in OKLab space on the given OKLCH input color,
177
+ * using the specified gamut and converting to the target color space.
178
+ * @param oklch - The input OKLCH color that you wish to gamut map.
179
+ * @param [gamut = sRGBGamut] - The gamut object.
180
+ * @param [targetSpace = gamut.space] - The target color space.
181
+ * @param [out = vec3()] - The output array to store the mapped color.
182
+ * @param [mapping = MapToCuspL] - The gamut mapping function.
183
+ * @param [cusp] - Optional, you can provide the cusp values [L, C] to avoid re-computing them.
184
+ * @returns The mapped color in the target color space.
185
+ */
186
+ function gamutMapOKLCH(oklch: Vector, gamut?: ColorGamut, targetSpace?: ColorSpace, out?: Vector, mapping?: GamutMapMethod, cusp?: Vector): Vector;
187
+ /**
188
+ * Converts OKHSL color to OKLab color.
189
+ * @param hsl - The OKHSL color as an array [h, s, l].
190
+ * @param [gamut = sRGBGamut] - The color gamut.
191
+ * @param [out = vec3()] - The output array to store the OKLab color.
192
+ * @returns The OKLab color as an array [L, a, b].
193
+ */
194
+ function OKHSLToOKLab(hsl: Vector, gamut?: ColorGamut, out?: Vector): Vector;
195
+ /**
196
+ * Converts OKLab color to OKHSL color.
197
+ * @param lab - The OKLab color as an array [L, a, b].
198
+ * @param [gamut = sRGBGamut] - The color gamut.
199
+ * @param [out = vec3()] - The output array to store the OKHSL color.
200
+ * @returns The OKHSL color as an array [h, s, l].
201
+ */
202
+ function OKLabToOKHSL(lab: Vector, gamut?: ColorGamut, out?: Vector): Vector;
203
+ /**
204
+ * Converts OKHSV color to OKLab color.
205
+ * @param hsv - The OKHSV color as an array [h, s, v].
206
+ * @param [gamut = sRGBGamut] - The color gamut.
207
+ * @param [out = vec3()] - The output array to store the OKLab color.
208
+ * @returns The OKLab color as an array [L, a, b].
209
+ */
210
+ function OKHSVToOKLab(hsv: Vector, gamut?: ColorGamut, out?: Vector): Vector;
211
+ /**
212
+ * Converts OKLab color to OKHSV color.
213
+ * @param lab - The OKLab color as an array [L, a, b].
214
+ * @param [gamut = sRGBGamut] - The color gamut.
215
+ * @param [out = vec3()] - The output array to store the OKHSV color.
216
+ * @returns The OKHSV color as an array [h, s, v].
217
+ */
218
+ function OKLabToOKHSV(lab: Vector, gamut?: ColorGamut, out?: Vector): Vector;
219
+ /**
220
+ * Returns a list of color spaces.
221
+ * @returns An array of color space objects.
222
+ */
223
+ function listColorSpaces(): ColorSpace[];
224
+ /**
225
+ * Returns a list of color gamuts.
226
+ * @returns An array of color gamut objects.
227
+ */
228
+ function listColorGamuts(): ColorGamut[];
229
+ /**
230
+ * Clamps a value between a minimum and maximum value.
231
+ * @param value - The value to clamp.
232
+ * @param min - The minimum value.
233
+ * @param max - The maximum value.
234
+ * @returns The clamped value.
235
+ */
236
+ function clamp(value: number, min: number, max: number): number;
237
+ /**
238
+ * Linearly interpolates between two values.
239
+ * @param min - The start value.
240
+ * @param max - The end value.
241
+ * @param t - The interpolation factor between 0 and 1.
242
+ * @returns The interpolated value.
243
+ */
244
+ function lerp(min: number, max: number, t: number): number;
245
+ /**
246
+ * Converts degrees to radians.
247
+ * @param n - The angle in degrees.
248
+ * @returns The angle in radians.
249
+ */
250
+ function degToRad(n: number): number;
251
+ /**
252
+ * Converts radians to degrees.
253
+ * @param n - The angle in radians.
254
+ * @returns The angle in degrees.
255
+ */
256
+ function radToDeg(n: number): number;
257
+ /**
258
+ * Constrains an angle to the range [0, 360).
259
+ * @param angle - The angle in degrees.
260
+ * @returns The constrained angle.
261
+ */
262
+ function constrainAngle(angle: number): number;
263
+ /**
264
+ * Converts a hex color string to an RGB array.
265
+ * @param str - The hex color string.
266
+ * @param [out = vec3()] - The output array.
267
+ * @returns The RGB array.
268
+ */
269
+ function hexToRGB(str: string, out?: Vector): Vector;
270
+ /**
271
+ * Converts an RGB array to a hex color string.
272
+ * @param rgb - The RGB array.
273
+ * @returns The hex color string.
274
+ */
275
+ function RGBToHex(rgb: Vector): string;
276
+ function RGBtoHex(): void;
277
+ /**
278
+ * Checks if an RGB color is within the gamut.
279
+ * @param lrgb - The linear RGB array.
280
+ * @param [ep = GAMUT_EPSILON] - The epsilon value for comparison.
281
+ * @returns True if the color is within the gamut, false otherwise.
282
+ */
283
+ function isRGBInGamut(lrgb: Vector, ep?: number): boolean;
284
+ /**
285
+ * Clamps an RGB array to the range [0, 1].
286
+ * @param rgb - The RGB array.
287
+ * @param [out = vec3()] - The output array.
288
+ * @returns The clamped RGB array.
289
+ */
290
+ function clampedRGB(rgb: Vector, out?: Vector): Vector;
291
+ /**
292
+ * Converts xyY color space to XYZ color space.
293
+ * @param arg - The xyY array.
294
+ * @param [out = vec3()] - The output array.
295
+ * @returns The XYZ array.
296
+ */
297
+ function xyY_to_XYZ(arg: Vector, out?: Vector): Vector;
298
+ /**
299
+ * Converts XYZ color space to xyY color space.
300
+ * @param arg - The XYZ array.
301
+ * @param [out = vec3()] - The output array.
302
+ * @returns The xyY array.
303
+ */
304
+ function XYZ_to_xyY(arg: Vector, out?: Vector): Vector;
305
+ /**
306
+ * Converts a float value to a byte value.
307
+ * @param n - The float value.
308
+ * @returns The byte value.
309
+ */
310
+ function floatToByte(n: number): number;
311
+ /**
312
+ * Creates a new vec3 array.
313
+ * @returns The vec3 array.
314
+ */
315
+ function vec3(): Vector;
316
+ /**
317
+ * Calculates the delta angle between two angles.
318
+ * @param a0 - The first angle in degrees.
319
+ * @param a1 - The second angle in degrees.
320
+ * @returns The delta angle in degrees.
321
+ */
322
+ function deltaAngle(a0: number, a1: number): number;
323
+ /**
324
+ * Linearly interpolates between two angles.
325
+ * @param a0 - The start angle in degrees.
326
+ * @param a1 - The end angle in degrees.
327
+ * @param t - The interpolation factor between 0 and 1.
328
+ * @returns The interpolated angle in degrees.
329
+ */
330
+ function lerpAngle(a0: number, a1: number, t: number): number;
331
+ }
332
+