@texel/color 1.1.3 → 1.1.5
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/.jsdoc.json +10 -0
- package/DOC.md +17 -0
- package/README.md +7 -1
- package/package.json +8 -2
- package/src/core.js +131 -8
- package/src/gamut.js +74 -4
- package/src/okhsl.js +40 -0
- package/src/spaces/a98-rgb.js +15 -0
- package/src/spaces/display-p3.js +15 -0
- package/src/spaces/oklab.js +24 -0
- package/src/spaces/prophoto-rgb.js +10 -0
- package/src/spaces/rec2020.js +15 -0
- package/src/spaces/srgb.js +15 -0
- package/src/spaces/util.js +14 -0
- package/src/spaces/xyz.js +26 -2
- package/src/spaces.js +14 -0
- package/src/util.js +121 -19
- package/types/types.d.ts +556 -0
- package/test/almost-equal.js +0 -15
- package/test/banner.png +0 -0
- package/test/bench-colorjs.js +0 -227
- package/test/bench-culori.js +0 -148
- package/test/bench-node.js +0 -51
- package/test/bench-size.js +0 -12
- package/test/canvas-graph.js +0 -212
- package/test/check-gamut-epsilon.js +0 -136
- package/test/colorjs-fn.js +0 -34
- package/test/example-interpolation.js +0 -107
- package/test/logo.js +0 -112
- package/test/logo.png +0 -0
- package/test/profiles/DisplayP3.icc +0 -0
- package/test/spaces/hsl.js +0 -87
- package/test/spaces/lab.js +0 -60
- package/test/test-colorjs.js +0 -86
- package/test/test-other-spaces.js +0 -115
- package/test/test.js +0 -481
- package/tools/__pycache__/calc_oklab_matrices.cpython-311.pyc +0 -0
- package/tools/calc_oklab_matrices.py +0 -233
- package/tools/print_matrices.py +0 -509
package/.jsdoc.json
ADDED
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.
|
|
3
|
+
"version": "1.1.5",
|
|
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 -t node_modules/better-docs -c .jsdoc.json -d docs -R DOC.md",
|
|
32
|
+
"types": "jsdoc -t node_modules/tsd-jsdoc/dist -c .jsdoc.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
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
314
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
*
|
|
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);
|
package/src/spaces/a98-rgb.js
CHANGED
|
@@ -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,
|
package/src/spaces/display-p3.js
CHANGED
|
@@ -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,
|
package/src/spaces/oklab.js
CHANGED
|
@@ -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,
|
package/src/spaces/rec2020.js
CHANGED
|
@@ -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,
|