First Commit
This commit is contained in:
14
node_modules/culori/src/_prepare.js
generated
vendored
Normal file
14
node_modules/culori/src/_prepare.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import parse from './parse.js';
|
||||
|
||||
const prepare = (color, mode) =>
|
||||
color === undefined
|
||||
? undefined
|
||||
: typeof color !== 'object'
|
||||
? parse(color)
|
||||
: color.mode !== undefined
|
||||
? color
|
||||
: mode
|
||||
? { ...color, mode }
|
||||
: undefined;
|
||||
|
||||
export default prepare;
|
37
node_modules/culori/src/a98/convertA98ToXyz65.js
generated
vendored
Normal file
37
node_modules/culori/src/a98/convertA98ToXyz65.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Convert A98 RGB values to CIE XYZ D65
|
||||
|
||||
References:
|
||||
* https://drafts.csswg.org/css-color/#color-conversion-code
|
||||
* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
|
||||
* https://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf
|
||||
*/
|
||||
|
||||
const linearize = v => Math.pow(Math.abs(v), 563 / 256) * Math.sign(v);
|
||||
|
||||
const convertA98ToXyz65 = a98 => {
|
||||
let r = linearize(a98.r);
|
||||
let g = linearize(a98.g);
|
||||
let b = linearize(a98.b);
|
||||
let res = {
|
||||
mode: 'xyz65',
|
||||
x:
|
||||
0.5766690429101305 * r +
|
||||
0.1855582379065463 * g +
|
||||
0.1882286462349947 * b,
|
||||
y:
|
||||
0.297344975250536 * r +
|
||||
0.6273635662554661 * g +
|
||||
0.0752914584939979 * b,
|
||||
z:
|
||||
0.0270313613864123 * r +
|
||||
0.0706888525358272 * g +
|
||||
0.9913375368376386 * b
|
||||
};
|
||||
if (a98.alpha !== undefined) {
|
||||
res.alpha = a98.alpha;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertA98ToXyz65;
|
36
node_modules/culori/src/a98/convertXyz65ToA98.js
generated
vendored
Normal file
36
node_modules/culori/src/a98/convertXyz65ToA98.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Convert CIE XYZ D65 values to A98 RGB
|
||||
|
||||
References:
|
||||
* https://drafts.csswg.org/css-color/#color-conversion-code
|
||||
* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
|
||||
*/
|
||||
|
||||
const gamma = v => Math.pow(Math.abs(v), 256 / 563) * Math.sign(v);
|
||||
|
||||
const convertXyz65ToA98 = ({ x, y, z, alpha }) => {
|
||||
let res = {
|
||||
mode: 'a98',
|
||||
r: gamma(
|
||||
x * 2.0415879038107465 -
|
||||
y * 0.5650069742788597 -
|
||||
0.3447313507783297 * z
|
||||
),
|
||||
g: gamma(
|
||||
x * -0.9692436362808798 +
|
||||
y * 1.8759675015077206 +
|
||||
0.0415550574071756 * z
|
||||
),
|
||||
b: gamma(
|
||||
x * 0.0134442806320312 -
|
||||
y * 0.1183623922310184 +
|
||||
1.0151749943912058 * z
|
||||
)
|
||||
};
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertXyz65ToA98;
|
25
node_modules/culori/src/a98/definition.js
generated
vendored
Normal file
25
node_modules/culori/src/a98/definition.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import rgb from '../rgb/definition.js';
|
||||
|
||||
import convertA98ToXyz65 from './convertA98ToXyz65.js';
|
||||
import convertXyz65ToA98 from './convertXyz65ToA98.js';
|
||||
import convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';
|
||||
import convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';
|
||||
|
||||
const definition = {
|
||||
...rgb,
|
||||
mode: 'a98',
|
||||
parse: ['a98-rgb'],
|
||||
serialize: 'a98-rgb',
|
||||
|
||||
fromMode: {
|
||||
rgb: color => convertXyz65ToA98(convertRgbToXyz65(color)),
|
||||
xyz65: convertXyz65ToA98
|
||||
},
|
||||
|
||||
toMode: {
|
||||
rgb: color => convertXyz65ToRgb(convertA98ToXyz65(color)),
|
||||
xyz65: convertA98ToXyz65
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
52
node_modules/culori/src/average.js
generated
vendored
Normal file
52
node_modules/culori/src/average.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import converter from './converter.js';
|
||||
import { getMode } from './modes.js';
|
||||
|
||||
const averageAngle = val => {
|
||||
// See: https://en.wikipedia.org/wiki/Mean_of_circular_quantities
|
||||
let sum = val.reduce(
|
||||
(sum, val) => {
|
||||
if (val !== undefined) {
|
||||
let rad = (val * Math.PI) / 180;
|
||||
sum.sin += Math.sin(rad);
|
||||
sum.cos += Math.cos(rad);
|
||||
}
|
||||
return sum;
|
||||
},
|
||||
{ sin: 0, cos: 0 }
|
||||
);
|
||||
return (Math.atan2(sum.sin, sum.cos) * 180) / Math.PI;
|
||||
};
|
||||
|
||||
const averageNumber = val => {
|
||||
let a = val.filter(v => v !== undefined);
|
||||
return a.length ? a.reduce((sum, v) => sum + v, 0) / a.length : undefined;
|
||||
};
|
||||
|
||||
const isfn = o => typeof o === 'function';
|
||||
|
||||
function average(colors, mode = 'rgb', overrides) {
|
||||
let def = getMode(mode);
|
||||
let cc = colors.map(converter(mode));
|
||||
return def.channels.reduce(
|
||||
(res, ch) => {
|
||||
let arr = cc.map(c => c[ch]).filter(val => val !== undefined);
|
||||
if (arr.length) {
|
||||
let fn;
|
||||
if (isfn(overrides)) {
|
||||
fn = overrides;
|
||||
} else if (overrides && isfn(overrides[ch])) {
|
||||
fn = overrides[ch];
|
||||
} else if (def.average && isfn(def.average[ch])) {
|
||||
fn = def.average[ch];
|
||||
} else {
|
||||
fn = averageNumber;
|
||||
}
|
||||
res[ch] = fn(arr, ch);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
{ mode }
|
||||
);
|
||||
}
|
||||
|
||||
export { average, averageAngle, averageNumber };
|
81
node_modules/culori/src/blend.js
generated
vendored
Normal file
81
node_modules/culori/src/blend.js
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Color blend modes, as defined in the
|
||||
CSS Compositing Level 4 spec
|
||||
|
||||
https://drafts.fxtf.org/compositing-2/
|
||||
https://en.wikipedia.org/wiki/Blend_modes
|
||||
https://en.wikipedia.org/wiki/Alpha_compositing
|
||||
https://keithp.com/~keithp/porterduff/p253-porter.pdf
|
||||
*/
|
||||
|
||||
import converter from './converter.js';
|
||||
import { getMode } from './modes.js';
|
||||
|
||||
const BLENDS = {
|
||||
normal: (b, s) => s,
|
||||
multiply: (b, s) => b * s,
|
||||
screen: (b, s) => b + s - b * s,
|
||||
'hard-light': (b, s) => (s < 0.5 ? b * 2 * s : 2 * s * (1 - b) - 1),
|
||||
overlay: (b, s) => (b < 0.5 ? s * 2 * b : 2 * b * (1 - s) - 1),
|
||||
darken: (b, s) => Math.min(b, s),
|
||||
lighten: (b, s) => Math.max(b, s),
|
||||
'color-dodge': (b, s) =>
|
||||
b === 0 ? 0 : s === 1 ? 1 : Math.min(1, b / (1 - s)),
|
||||
'color-burn': (b, s) =>
|
||||
b === 1 ? 1 : s === 0 ? 0 : 1 - Math.min(1, (1 - b) / s),
|
||||
'soft-light': (b, s) =>
|
||||
s < 0.5
|
||||
? b - (1 - 2 * s) * b * (1 - b)
|
||||
: b +
|
||||
(2 * s - 1) *
|
||||
((b < 0.25 ? ((16 * b - 12) * b + 4) * b : Math.sqrt(b)) -
|
||||
b),
|
||||
difference: (b, s) => Math.abs(b - s),
|
||||
exclusion: (b, s) => b + s - 2 * b * s
|
||||
};
|
||||
|
||||
const blend = (colors, type = 'normal', mode = 'rgb') => {
|
||||
let fn = typeof type === 'function' ? type : BLENDS[type];
|
||||
|
||||
let conv = converter(mode);
|
||||
|
||||
// get mode channels
|
||||
let channels = getMode(mode).channels;
|
||||
|
||||
// convert all colors to the mode
|
||||
// and assume undefined alphas are 1
|
||||
let converted = colors.map(c => {
|
||||
let cc = conv(c);
|
||||
if (cc.alpha === undefined) {
|
||||
cc.alpha = 1;
|
||||
}
|
||||
return cc;
|
||||
});
|
||||
|
||||
return converted.reduce((b, s) => {
|
||||
if (b === undefined) return s;
|
||||
// blend backdrop and source
|
||||
let alpha = s.alpha + b.alpha * (1 - s.alpha);
|
||||
return channels.reduce(
|
||||
(res, ch) => {
|
||||
if (ch !== 'alpha') {
|
||||
if (alpha === 0) {
|
||||
res[ch] = 0;
|
||||
} else {
|
||||
res[ch] =
|
||||
s.alpha * (1 - b.alpha) * s[ch] +
|
||||
s.alpha * b.alpha * fn(b[ch], s[ch]) +
|
||||
(1 - s.alpha) * b.alpha * b[ch];
|
||||
// TODO fix() assumes [0, 1] colors
|
||||
// and is only true for RGB / LRGB
|
||||
res[ch] = Math.max(0, Math.min(1, res[ch] / alpha));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
},
|
||||
{ mode, alpha }
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export default blend;
|
61
node_modules/culori/src/bootstrap/all.js
generated
vendored
Normal file
61
node_modules/culori/src/bootstrap/all.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
// Color space definitions
|
||||
import modeA98 from '../a98/definition.js';
|
||||
import modeCubehelix from '../cubehelix/definition.js';
|
||||
import modeDlab from '../dlab/definition.js';
|
||||
import modeDlch from '../dlch/definition.js';
|
||||
import modeHsi from '../hsi/definition.js';
|
||||
import modeHsl from '../hsl/definition.js';
|
||||
import modeHsv from '../hsv/definition.js';
|
||||
import modeHwb from '../hwb/definition.js';
|
||||
import modeJab from '../jab/definition.js';
|
||||
import modeJch from '../jch/definition.js';
|
||||
import modeLab from '../lab/definition.js';
|
||||
import modeLab65 from '../lab65/definition.js';
|
||||
import modeLch from '../lch/definition.js';
|
||||
import modeLch65 from '../lch65/definition.js';
|
||||
import modeLchuv from '../lchuv/definition.js';
|
||||
import modeLrgb from '../lrgb/definition.js';
|
||||
import modeLuv from '../luv/definition.js';
|
||||
import modeOkhsl from '../okhsl/modeOkhsl.js';
|
||||
import modeOkhsv from '../okhsv/modeOkhsv.js';
|
||||
import modeOklab from '../oklab/definition.js';
|
||||
import modeOklch from '../oklch/definition.js';
|
||||
import modeP3 from '../p3/definition.js';
|
||||
import modeProphoto from '../prophoto/definition.js';
|
||||
import modeRec2020 from '../rec2020/definition.js';
|
||||
import modeRgb from '../rgb/definition.js';
|
||||
import modeXyb from '../xyb/definition.js';
|
||||
import modeXyz50 from '../xyz50/definition.js';
|
||||
import modeXyz65 from '../xyz65/definition.js';
|
||||
import modeYiq from '../yiq/definition.js';
|
||||
import { useMode } from '../modes.js';
|
||||
|
||||
export const a98 = useMode(modeA98);
|
||||
export const cubehelix = useMode(modeCubehelix);
|
||||
export const dlab = useMode(modeDlab);
|
||||
export const dlch = useMode(modeDlch);
|
||||
export const hsi = useMode(modeHsi);
|
||||
export const hsl = useMode(modeHsl);
|
||||
export const hsv = useMode(modeHsv);
|
||||
export const hwb = useMode(modeHwb);
|
||||
export const jab = useMode(modeJab);
|
||||
export const jch = useMode(modeJch);
|
||||
export const lab = useMode(modeLab);
|
||||
export const lab65 = useMode(modeLab65);
|
||||
export const lch = useMode(modeLch);
|
||||
export const lch65 = useMode(modeLch65);
|
||||
export const lchuv = useMode(modeLchuv);
|
||||
export const lrgb = useMode(modeLrgb);
|
||||
export const luv = useMode(modeLuv);
|
||||
export const okhsl = useMode(modeOkhsl);
|
||||
export const okhsv = useMode(modeOkhsv);
|
||||
export const oklab = useMode(modeOklab);
|
||||
export const oklch = useMode(modeOklch);
|
||||
export const p3 = useMode(modeP3);
|
||||
export const prophoto = useMode(modeProphoto);
|
||||
export const rec2020 = useMode(modeRec2020);
|
||||
export const rgb = useMode(modeRgb);
|
||||
export const xyb = useMode(modeXyb);
|
||||
export const xyz50 = useMode(modeXyz50);
|
||||
export const xyz65 = useMode(modeXyz65);
|
||||
export const yiq = useMode(modeYiq);
|
37
node_modules/culori/src/bootstrap/css.js
generated
vendored
Normal file
37
node_modules/culori/src/bootstrap/css.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// Color space definitions
|
||||
import modeA98 from '../a98/definition.js';
|
||||
import modeHsl from '../hsl/definition.js';
|
||||
import modeHsv from '../hsv/definition.js';
|
||||
import modeHwb from '../hwb/definition.js';
|
||||
import modeLab from '../lab/definition.js';
|
||||
import modeLab65 from '../lab65/definition.js';
|
||||
import modeLch from '../lch/definition.js';
|
||||
import modeLch65 from '../lch65/definition.js';
|
||||
import modeLrgb from '../lrgb/definition.js';
|
||||
import modeOklab from '../oklab/definition.js';
|
||||
import modeOklch from '../oklch/definition.js';
|
||||
import modeP3 from '../p3/definition.js';
|
||||
import modeProphoto from '../prophoto/definition.js';
|
||||
import modeRec2020 from '../rec2020/definition.js';
|
||||
import modeRgb from '../rgb/definition.js';
|
||||
import modeXyz50 from '../xyz50/definition.js';
|
||||
import modeXyz65 from '../xyz65/definition.js';
|
||||
import { useMode } from '../modes.js';
|
||||
|
||||
export const a98 = useMode(modeA98);
|
||||
export const hsl = useMode(modeHsl);
|
||||
export const hsv = useMode(modeHsv);
|
||||
export const hwb = useMode(modeHwb);
|
||||
export const lab = useMode(modeLab);
|
||||
export const lab65 = useMode(modeLab65);
|
||||
export const lch = useMode(modeLch);
|
||||
export const lch65 = useMode(modeLch65);
|
||||
export const lrgb = useMode(modeLrgb);
|
||||
export const oklab = useMode(modeOklab);
|
||||
export const oklch = useMode(modeOklch);
|
||||
export const p3 = useMode(modeP3);
|
||||
export const prophoto = useMode(modeProphoto);
|
||||
export const rec2020 = useMode(modeRec2020);
|
||||
export const rgb = useMode(modeRgb);
|
||||
export const xyz50 = useMode(modeXyz50);
|
||||
export const xyz65 = useMode(modeXyz65);
|
255
node_modules/culori/src/clamp.js
generated
vendored
Normal file
255
node_modules/culori/src/clamp.js
generated
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
import converter from './converter.js';
|
||||
import prepare from './_prepare.js';
|
||||
import { getMode } from './modes.js';
|
||||
import { differenceEuclidean } from './difference.js';
|
||||
|
||||
const rgb = converter('rgb');
|
||||
const fixup_rgb = c => {
|
||||
const res = {
|
||||
mode: c.mode,
|
||||
r: Math.max(0, Math.min(c.r, 1)),
|
||||
g: Math.max(0, Math.min(c.g, 1)),
|
||||
b: Math.max(0, Math.min(c.b, 1))
|
||||
};
|
||||
if (c.alpha !== undefined) {
|
||||
res.alpha = c.alpha;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
const to_displayable_srgb = c => fixup_rgb(rgb(c));
|
||||
|
||||
const inrange_rgb = c => {
|
||||
return (
|
||||
c !== undefined &&
|
||||
c.r >= 0 &&
|
||||
c.r <= 1 &&
|
||||
c.g >= 0 &&
|
||||
c.g <= 1 &&
|
||||
c.b >= 0 &&
|
||||
c.b <= 1
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
Returns whether the color is in the sRGB gamut.
|
||||
*/
|
||||
export function displayable(color) {
|
||||
return inrange_rgb(rgb(color));
|
||||
}
|
||||
|
||||
/*
|
||||
Given a color space `mode`, returns a function
|
||||
with which to check whether a color is
|
||||
in that color space's gamut.
|
||||
*/
|
||||
export function inGamut(mode = 'rgb') {
|
||||
const { gamut } = getMode(mode);
|
||||
if (!gamut) {
|
||||
return color => true;
|
||||
}
|
||||
const conv = converter(typeof gamut === 'string' ? gamut : mode);
|
||||
return color => inrange_rgb(conv(color));
|
||||
}
|
||||
|
||||
/*
|
||||
Obtain a color that's in the sRGB gamut
|
||||
by converting it to sRGB and clipping the channel values
|
||||
so that they're within the [0, 1] range.
|
||||
|
||||
The result is returned in the color's original color space.
|
||||
*/
|
||||
export function clampRgb(color) {
|
||||
color = prepare(color);
|
||||
|
||||
// if the color is undefined or displayable, return it directly
|
||||
if (color === undefined || displayable(color)) return color;
|
||||
|
||||
// keep track of color's original mode
|
||||
let conv = converter(color.mode);
|
||||
|
||||
return conv(to_displayable_srgb(color));
|
||||
}
|
||||
|
||||
/*
|
||||
Given the `mode` color space, returns a function
|
||||
with which to obtain a color that's in gamut for
|
||||
the `mode` color space by clipping the channel values
|
||||
so that they fit in their respective ranges.
|
||||
|
||||
It's similar to `clampRgb`, but works for any
|
||||
bounded color space (RGB or not) for which
|
||||
any combination of in-range channel values
|
||||
produces an in-gamut color.
|
||||
*/
|
||||
export function clampGamut(mode = 'rgb') {
|
||||
const { gamut } = getMode(mode);
|
||||
if (!gamut) {
|
||||
return color => prepare(color);
|
||||
}
|
||||
const destMode = typeof gamut === 'string' ? gamut : mode;
|
||||
const destConv = converter(destMode);
|
||||
const inDestGamut = inGamut(destMode);
|
||||
return color => {
|
||||
const original = prepare(color);
|
||||
if (!original) {
|
||||
return undefined;
|
||||
}
|
||||
const converted = destConv(original);
|
||||
if (inDestGamut(converted)) {
|
||||
return original;
|
||||
}
|
||||
const clamped = fixup_rgb(converted);
|
||||
if (original.mode === clamped.mode) {
|
||||
return clamped;
|
||||
}
|
||||
return converter(original.mode)(clamped);
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
Obtain a color that’s in a RGB gamut (by default sRGB)
|
||||
by first converting it to `mode` and then finding
|
||||
the greatest chroma value that fits the gamut.
|
||||
|
||||
By default, the CIELCh color space is used,
|
||||
but any color that has a chroma component will do.
|
||||
|
||||
The result is returned in the color's original color space.
|
||||
*/
|
||||
export function clampChroma(color, mode = 'lch', rgbGamut = 'rgb') {
|
||||
color = prepare(color);
|
||||
|
||||
let inDestinationGamut =
|
||||
rgbGamut === 'rgb' ? displayable : inGamut(rgbGamut);
|
||||
let clipToGamut =
|
||||
rgbGamut === 'rgb' ? to_displayable_srgb : clampGamut(rgbGamut);
|
||||
|
||||
// if the color is undefined or displayable, return it directly
|
||||
if (color === undefined || inDestinationGamut(color)) return color;
|
||||
|
||||
// keep track of color's original mode
|
||||
let conv = converter(color.mode);
|
||||
|
||||
// convert to the provided `mode` for clamping
|
||||
color = converter(mode)(color);
|
||||
|
||||
// try with chroma = 0
|
||||
let clamped = { ...color, c: 0 };
|
||||
|
||||
// if not even chroma = 0 is displayable
|
||||
// fall back to RGB clamping
|
||||
if (!inDestinationGamut(clamped)) {
|
||||
return conv(clipToGamut(clamped));
|
||||
}
|
||||
|
||||
// By this time we know chroma = 0 is displayable and our current chroma is not.
|
||||
// Find the displayable chroma through the bisection method.
|
||||
let start = 0;
|
||||
let end = color.c;
|
||||
let range = getMode(mode).ranges.c;
|
||||
let resolution = (range[1] - range[0]) / Math.pow(2, 13);
|
||||
let _last_good_c;
|
||||
|
||||
while (end - start > resolution) {
|
||||
clamped.c = start + (end - start) * 0.5;
|
||||
if (inDestinationGamut(clamped)) {
|
||||
_last_good_c = clamped.c;
|
||||
start = clamped.c;
|
||||
} else {
|
||||
end = clamped.c;
|
||||
}
|
||||
}
|
||||
|
||||
return conv(
|
||||
inDestinationGamut(clamped) ? clamped : { ...clamped, c: _last_good_c }
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
Obtain a color that's in the `dest` gamut,
|
||||
by first converting it to the `mode` color space
|
||||
and then finding the largest chroma that's in gamut,
|
||||
similar to `clampChroma`.
|
||||
|
||||
The color returned is in the `dest` color space.
|
||||
|
||||
To address the shortcomings of `clampChroma`, which can
|
||||
sometimes produce colors more desaturated than necessary,
|
||||
the test used in the binary search is replaced with
|
||||
"is color is roughly in gamut", by comparing the candidate
|
||||
to the clipped version (obtained with `clampGamut`).
|
||||
The test passes if the colors are not too dissimilar,
|
||||
judged by the `delta` color difference function
|
||||
and an associated `jnd` just-noticeable difference value.
|
||||
|
||||
The default arguments for this function correspond to the
|
||||
gamut mapping algorithm defined in CSS Color Level 4:
|
||||
https://drafts.csswg.org/css-color/#css-gamut-mapping
|
||||
|
||||
To disable the “roughly in gamut” part, pass either
|
||||
`null` for the `delta` parameter, or zero for `jnd`.
|
||||
*/
|
||||
export function toGamut(
|
||||
dest = 'rgb',
|
||||
mode = 'oklch',
|
||||
delta = differenceEuclidean('oklch'),
|
||||
jnd = 0.02
|
||||
) {
|
||||
const destConv = converter(dest);
|
||||
|
||||
if (!getMode(dest).gamut) {
|
||||
return color => destConv(color);
|
||||
}
|
||||
|
||||
const inDestinationGamut = inGamut(dest);
|
||||
const clipToGamut = clampGamut(dest);
|
||||
|
||||
const ucs = converter(mode);
|
||||
const { ranges } = getMode(mode);
|
||||
|
||||
const White = destConv('white');
|
||||
const Black = destConv('black');
|
||||
|
||||
return color => {
|
||||
color = prepare(color);
|
||||
if (color === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const candidate = { ...ucs(color) };
|
||||
if (candidate.l >= ranges.l[1]) {
|
||||
const res = { ...White };
|
||||
if (color.alpha !== undefined) {
|
||||
res.alpha = color.alpha;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
if (candidate.l <= ranges.l[0]) {
|
||||
const res = { ...Black };
|
||||
if (color.alpha !== undefined) {
|
||||
res.alpha = color.alpha;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
if (inDestinationGamut(candidate)) {
|
||||
return destConv(candidate);
|
||||
}
|
||||
let start = 0;
|
||||
let end = candidate.c;
|
||||
let epsilon = (ranges.c[1] - ranges.c[0]) / 4000; // 0.0001 for oklch()
|
||||
let clipped = clipToGamut(candidate);
|
||||
while (end - start > epsilon) {
|
||||
candidate.c = (start + end) * 0.5;
|
||||
clipped = clipToGamut(candidate);
|
||||
if (
|
||||
inDestinationGamut(candidate) ||
|
||||
(delta && jnd > 0 && delta(candidate, clipped) <= jnd)
|
||||
) {
|
||||
start = candidate.c;
|
||||
} else {
|
||||
end = candidate.c;
|
||||
}
|
||||
}
|
||||
return destConv(inDestinationGamut(candidate) ? candidate : clipped);
|
||||
};
|
||||
}
|
156
node_modules/culori/src/colors/named.js
generated
vendored
Normal file
156
node_modules/culori/src/colors/named.js
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
const named = {
|
||||
aliceblue: 0xf0f8ff,
|
||||
antiquewhite: 0xfaebd7,
|
||||
aqua: 0x00ffff,
|
||||
aquamarine: 0x7fffd4,
|
||||
azure: 0xf0ffff,
|
||||
beige: 0xf5f5dc,
|
||||
bisque: 0xffe4c4,
|
||||
black: 0x000000,
|
||||
blanchedalmond: 0xffebcd,
|
||||
blue: 0x0000ff,
|
||||
blueviolet: 0x8a2be2,
|
||||
brown: 0xa52a2a,
|
||||
burlywood: 0xdeb887,
|
||||
cadetblue: 0x5f9ea0,
|
||||
chartreuse: 0x7fff00,
|
||||
chocolate: 0xd2691e,
|
||||
coral: 0xff7f50,
|
||||
cornflowerblue: 0x6495ed,
|
||||
cornsilk: 0xfff8dc,
|
||||
crimson: 0xdc143c,
|
||||
cyan: 0x00ffff,
|
||||
darkblue: 0x00008b,
|
||||
darkcyan: 0x008b8b,
|
||||
darkgoldenrod: 0xb8860b,
|
||||
darkgray: 0xa9a9a9,
|
||||
darkgreen: 0x006400,
|
||||
darkgrey: 0xa9a9a9,
|
||||
darkkhaki: 0xbdb76b,
|
||||
darkmagenta: 0x8b008b,
|
||||
darkolivegreen: 0x556b2f,
|
||||
darkorange: 0xff8c00,
|
||||
darkorchid: 0x9932cc,
|
||||
darkred: 0x8b0000,
|
||||
darksalmon: 0xe9967a,
|
||||
darkseagreen: 0x8fbc8f,
|
||||
darkslateblue: 0x483d8b,
|
||||
darkslategray: 0x2f4f4f,
|
||||
darkslategrey: 0x2f4f4f,
|
||||
darkturquoise: 0x00ced1,
|
||||
darkviolet: 0x9400d3,
|
||||
deeppink: 0xff1493,
|
||||
deepskyblue: 0x00bfff,
|
||||
dimgray: 0x696969,
|
||||
dimgrey: 0x696969,
|
||||
dodgerblue: 0x1e90ff,
|
||||
firebrick: 0xb22222,
|
||||
floralwhite: 0xfffaf0,
|
||||
forestgreen: 0x228b22,
|
||||
fuchsia: 0xff00ff,
|
||||
gainsboro: 0xdcdcdc,
|
||||
ghostwhite: 0xf8f8ff,
|
||||
gold: 0xffd700,
|
||||
goldenrod: 0xdaa520,
|
||||
gray: 0x808080,
|
||||
green: 0x008000,
|
||||
greenyellow: 0xadff2f,
|
||||
grey: 0x808080,
|
||||
honeydew: 0xf0fff0,
|
||||
hotpink: 0xff69b4,
|
||||
indianred: 0xcd5c5c,
|
||||
indigo: 0x4b0082,
|
||||
ivory: 0xfffff0,
|
||||
khaki: 0xf0e68c,
|
||||
lavender: 0xe6e6fa,
|
||||
lavenderblush: 0xfff0f5,
|
||||
lawngreen: 0x7cfc00,
|
||||
lemonchiffon: 0xfffacd,
|
||||
lightblue: 0xadd8e6,
|
||||
lightcoral: 0xf08080,
|
||||
lightcyan: 0xe0ffff,
|
||||
lightgoldenrodyellow: 0xfafad2,
|
||||
lightgray: 0xd3d3d3,
|
||||
lightgreen: 0x90ee90,
|
||||
lightgrey: 0xd3d3d3,
|
||||
lightpink: 0xffb6c1,
|
||||
lightsalmon: 0xffa07a,
|
||||
lightseagreen: 0x20b2aa,
|
||||
lightskyblue: 0x87cefa,
|
||||
lightslategray: 0x778899,
|
||||
lightslategrey: 0x778899,
|
||||
lightsteelblue: 0xb0c4de,
|
||||
lightyellow: 0xffffe0,
|
||||
lime: 0x00ff00,
|
||||
limegreen: 0x32cd32,
|
||||
linen: 0xfaf0e6,
|
||||
magenta: 0xff00ff,
|
||||
maroon: 0x800000,
|
||||
mediumaquamarine: 0x66cdaa,
|
||||
mediumblue: 0x0000cd,
|
||||
mediumorchid: 0xba55d3,
|
||||
mediumpurple: 0x9370db,
|
||||
mediumseagreen: 0x3cb371,
|
||||
mediumslateblue: 0x7b68ee,
|
||||
mediumspringgreen: 0x00fa9a,
|
||||
mediumturquoise: 0x48d1cc,
|
||||
mediumvioletred: 0xc71585,
|
||||
midnightblue: 0x191970,
|
||||
mintcream: 0xf5fffa,
|
||||
mistyrose: 0xffe4e1,
|
||||
moccasin: 0xffe4b5,
|
||||
navajowhite: 0xffdead,
|
||||
navy: 0x000080,
|
||||
oldlace: 0xfdf5e6,
|
||||
olive: 0x808000,
|
||||
olivedrab: 0x6b8e23,
|
||||
orange: 0xffa500,
|
||||
orangered: 0xff4500,
|
||||
orchid: 0xda70d6,
|
||||
palegoldenrod: 0xeee8aa,
|
||||
palegreen: 0x98fb98,
|
||||
paleturquoise: 0xafeeee,
|
||||
palevioletred: 0xdb7093,
|
||||
papayawhip: 0xffefd5,
|
||||
peachpuff: 0xffdab9,
|
||||
peru: 0xcd853f,
|
||||
pink: 0xffc0cb,
|
||||
plum: 0xdda0dd,
|
||||
powderblue: 0xb0e0e6,
|
||||
purple: 0x800080,
|
||||
|
||||
// Added in CSS Colors Level 4:
|
||||
// https://drafts.csswg.org/css-color/#changes-from-3
|
||||
rebeccapurple: 0x663399,
|
||||
|
||||
red: 0xff0000,
|
||||
rosybrown: 0xbc8f8f,
|
||||
royalblue: 0x4169e1,
|
||||
saddlebrown: 0x8b4513,
|
||||
salmon: 0xfa8072,
|
||||
sandybrown: 0xf4a460,
|
||||
seagreen: 0x2e8b57,
|
||||
seashell: 0xfff5ee,
|
||||
sienna: 0xa0522d,
|
||||
silver: 0xc0c0c0,
|
||||
skyblue: 0x87ceeb,
|
||||
slateblue: 0x6a5acd,
|
||||
slategray: 0x708090,
|
||||
slategrey: 0x708090,
|
||||
snow: 0xfffafa,
|
||||
springgreen: 0x00ff7f,
|
||||
steelblue: 0x4682b4,
|
||||
tan: 0xd2b48c,
|
||||
teal: 0x008080,
|
||||
thistle: 0xd8bfd8,
|
||||
tomato: 0xff6347,
|
||||
turquoise: 0x40e0d0,
|
||||
violet: 0xee82ee,
|
||||
wheat: 0xf5deb3,
|
||||
white: 0xffffff,
|
||||
whitesmoke: 0xf5f5f5,
|
||||
yellow: 0xffff00,
|
||||
yellowgreen: 0x9acd32
|
||||
};
|
||||
|
||||
export default named;
|
22
node_modules/culori/src/constants.js
generated
vendored
Normal file
22
node_modules/culori/src/constants.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
The XYZ tristimulus values (white point)
|
||||
of standard illuminants for the CIE 1931 2°
|
||||
standard observer.
|
||||
|
||||
See: https://en.wikipedia.org/wiki/Standard_illuminant
|
||||
*/
|
||||
|
||||
export const D50 = {
|
||||
X: 0.3457 / 0.3585,
|
||||
Y: 1,
|
||||
Z: (1 - 0.3457 - 0.3585) / 0.3585
|
||||
};
|
||||
|
||||
export const D65 = {
|
||||
X: 0.3127 / 0.329,
|
||||
Y: 1,
|
||||
Z: (1 - 0.3127 - 0.329) / 0.329
|
||||
};
|
||||
|
||||
export const k = Math.pow(29, 3) / Math.pow(3, 3);
|
||||
export const e = Math.pow(6, 3) / Math.pow(29, 3);
|
26
node_modules/culori/src/converter.js
generated
vendored
Normal file
26
node_modules/culori/src/converter.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import { converters } from './modes.js';
|
||||
import prepare from './_prepare.js';
|
||||
|
||||
const converter =
|
||||
(target_mode = 'rgb') =>
|
||||
color =>
|
||||
(color = prepare(color, target_mode)) !== undefined
|
||||
? // if the color's mode corresponds to our target mode
|
||||
color.mode === target_mode
|
||||
? // then just return the color
|
||||
color
|
||||
: // otherwise check to see if we have a dedicated
|
||||
// converter for the target mode
|
||||
converters[color.mode][target_mode]
|
||||
? // and return its result...
|
||||
converters[color.mode][target_mode](color)
|
||||
: // ...otherwise pass through RGB as an intermediary step.
|
||||
// if the target mode is RGB...
|
||||
target_mode === 'rgb'
|
||||
? // just return the RGB
|
||||
converters[color.mode].rgb(color)
|
||||
: // otherwise convert color.mode -> RGB -> target_mode
|
||||
converters.rgb[target_mode](converters[color.mode].rgb(color))
|
||||
: undefined;
|
||||
|
||||
export default converter;
|
4
node_modules/culori/src/cubehelix/constants.js
generated
vendored
Normal file
4
node_modules/culori/src/cubehelix/constants.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
export const M = [-0.14861, 1.78277, -0.29227, -0.90649, 1.97294, 0];
|
||||
|
||||
export const degToRad = Math.PI / 180;
|
||||
export const radToDeg = 180 / Math.PI;
|
21
node_modules/culori/src/cubehelix/convertCubehelixToRgb.js
generated
vendored
Normal file
21
node_modules/culori/src/cubehelix/convertCubehelixToRgb.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import { degToRad, M } from './constants.js';
|
||||
|
||||
const convertCubehelixToRgb = ({ h, s, l, alpha }) => {
|
||||
let res = { mode: 'rgb' };
|
||||
|
||||
h = (h === undefined ? 0 : h + 120) * degToRad;
|
||||
|
||||
let amp = s === undefined ? 0 : s * l * (1 - l);
|
||||
|
||||
let cosh = Math.cos(h);
|
||||
let sinh = Math.sin(h);
|
||||
|
||||
res.r = l + amp * (M[0] * cosh + M[1] * sinh);
|
||||
res.g = l + amp * (M[2] * cosh + M[3] * sinh);
|
||||
res.b = l + amp * (M[4] * cosh + M[5] * sinh);
|
||||
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertCubehelixToRgb;
|
40
node_modules/culori/src/cubehelix/convertRgbToCubehelix.js
generated
vendored
Normal file
40
node_modules/culori/src/cubehelix/convertRgbToCubehelix.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Convert a RGB color to the Cubehelix HSL color space.
|
||||
|
||||
This computation is not present in Green's paper:
|
||||
https://arxiv.org/pdf/1108.5083.pdf
|
||||
|
||||
...but can be derived from the inverse, HSL to RGB conversion.
|
||||
|
||||
It matches the math in Mike Bostock's D3 implementation:
|
||||
|
||||
https://github.com/d3/d3-color/blob/master/src/cubehelix.js
|
||||
*/
|
||||
|
||||
import { radToDeg, M } from './constants.js';
|
||||
|
||||
let DE = M[3] * M[4];
|
||||
let BE = M[1] * M[4];
|
||||
let BCAD = M[1] * M[2] - M[0] * M[3];
|
||||
|
||||
const convertRgbToCubehelix = ({ r, g, b, alpha }) => {
|
||||
let l = (BCAD * b + r * DE - g * BE) / (BCAD + DE - BE);
|
||||
let x = b - l;
|
||||
let y = (M[4] * (g - l) - M[2] * x) / M[3];
|
||||
|
||||
let res = {
|
||||
mode: 'cubehelix',
|
||||
l: l,
|
||||
s:
|
||||
l === 0 || l === 1
|
||||
? undefined
|
||||
: Math.sqrt(x * x + y * y) / (M[4] * l * (1 - l))
|
||||
};
|
||||
|
||||
if (res.s) res.h = Math.atan2(y, x) * radToDeg - 120;
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertRgbToCubehelix;
|
84
node_modules/culori/src/cubehelix/definition.js
generated
vendored
Normal file
84
node_modules/culori/src/cubehelix/definition.js
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Dave Green's Cubehelix
|
||||
----------------------
|
||||
|
||||
Green, D. A., 2011, "A colour scheme for the display of astronomical intensity images",
|
||||
Bulletin of the Astronomical Society of India, 39, 289. (2011BASI...39..289G at ADS.)
|
||||
|
||||
https://www.mrao.cam.ac.uk/%7Edag/CUBEHELIX/
|
||||
https://arxiv.org/pdf/1108.5083.pdf
|
||||
|
||||
Although Cubehelix was defined to be a method to obtain a colour scheme,
|
||||
it actually contains a definition of a colour space, as identified by
|
||||
Mike Bostock and implemented in D3.js.
|
||||
|
||||
Green's paper introduces the following terminology:
|
||||
|
||||
* a `lightness` dimension in the interval [0, 1]
|
||||
on which we interpolate to obtain the colour scheme
|
||||
* a `start` colour that is analogous to a Hue in HSL space
|
||||
* a number of `rotations` around the Hue cylinder.
|
||||
* a `hue` parameter which should more appropriately be called `saturation`
|
||||
|
||||
As such, the original definition of the Cubehelix scheme is actually an
|
||||
interpolation between two colors in the Cubehelix space:
|
||||
|
||||
H: start H: start + 360 * rotations
|
||||
S: hue -> S: hue
|
||||
L: 0 L: 1
|
||||
|
||||
We can therefore extend the interpolation to any two colors in this space,
|
||||
with a variable Saturation and a Lightness interval other than the fixed 0 -> 1.
|
||||
*/
|
||||
|
||||
import { fixupHueShorter } from '../fixup/hue.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import convertRgbToCubehelix from './convertRgbToCubehelix.js';
|
||||
import convertCubehelixToRgb from './convertCubehelixToRgb.js';
|
||||
import { differenceHueSaturation } from '../difference.js';
|
||||
import { averageAngle } from '../average.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'cubehelix',
|
||||
channels: ['h', 's', 'l', 'alpha'],
|
||||
parse: ['--cubehelix'],
|
||||
serialize: '--cubehelix',
|
||||
|
||||
ranges: {
|
||||
h: [0, 360],
|
||||
s: [0, 4.614],
|
||||
l: [0, 1]
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
rgb: convertRgbToCubehelix
|
||||
},
|
||||
|
||||
toMode: {
|
||||
rgb: convertCubehelixToRgb
|
||||
},
|
||||
|
||||
interpolate: {
|
||||
h: {
|
||||
use: interpolatorLinear,
|
||||
fixup: fixupHueShorter
|
||||
},
|
||||
s: interpolatorLinear,
|
||||
l: interpolatorLinear,
|
||||
alpha: {
|
||||
use: interpolatorLinear,
|
||||
fixup: fixupAlpha
|
||||
}
|
||||
},
|
||||
|
||||
difference: {
|
||||
h: differenceHueSaturation
|
||||
},
|
||||
|
||||
average: {
|
||||
h: averageAngle
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
190
node_modules/culori/src/deficiency.js
generated
vendored
Normal file
190
node_modules/culori/src/deficiency.js
generated
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
import converter from './converter.js';
|
||||
import prepare from './_prepare.js';
|
||||
import { lerp } from './interpolate/lerp.js';
|
||||
|
||||
let rgb = converter('rgb');
|
||||
|
||||
/*
|
||||
Color vision deficiency (CVD) simulation based on:
|
||||
|
||||
G. M. Machado, M. M. Oliveira and L. A. F. Fernandes,
|
||||
"A Physiologically-based Model for Simulation of Color Vision Deficiency"
|
||||
in IEEE Transactions on Visualization and Computer Graphics,
|
||||
vol. 15, no. 6, pp. 1291-1298, Nov.-Dec. 2009,
|
||||
doi: 10.1109/TVCG.2009.113.
|
||||
|
||||
Functions use precomputed matrices from:
|
||||
|
||||
https://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html
|
||||
|
||||
Via the `colorspace` R package documentation:
|
||||
|
||||
http://colorspace.r-forge.r-project.org/reference/simulate_cvd.html
|
||||
*/
|
||||
|
||||
const PROT = [
|
||||
[1.0, 0.0, -0.0, 0.0, 1.0, 0.0, -0.0, -0.0, 1.0],
|
||||
[
|
||||
0.856167, 0.182038, -0.038205, 0.029342, 0.955115, 0.015544, -0.00288,
|
||||
-0.001563, 1.004443
|
||||
],
|
||||
[
|
||||
0.734766, 0.334872, -0.069637, 0.05184, 0.919198, 0.028963, -0.004928,
|
||||
-0.004209, 1.009137
|
||||
],
|
||||
[
|
||||
0.630323, 0.465641, -0.095964, 0.069181, 0.890046, 0.040773, -0.006308,
|
||||
-0.007724, 1.014032
|
||||
],
|
||||
[
|
||||
0.539009, 0.579343, -0.118352, 0.082546, 0.866121, 0.051332, -0.007136,
|
||||
-0.011959, 1.019095
|
||||
],
|
||||
[
|
||||
0.458064, 0.679578, -0.137642, 0.092785, 0.846313, 0.060902, -0.007494,
|
||||
-0.016807, 1.024301
|
||||
],
|
||||
[
|
||||
0.38545, 0.769005, -0.154455, 0.100526, 0.829802, 0.069673, -0.007442,
|
||||
-0.02219, 1.029632
|
||||
],
|
||||
[
|
||||
0.319627, 0.849633, -0.169261, 0.106241, 0.815969, 0.07779, -0.007025,
|
||||
-0.028051, 1.035076
|
||||
],
|
||||
[
|
||||
0.259411, 0.923008, -0.18242, 0.110296, 0.80434, 0.085364, -0.006276,
|
||||
-0.034346, 1.040622
|
||||
],
|
||||
[
|
||||
0.203876, 0.990338, -0.194214, 0.112975, 0.794542, 0.092483, -0.005222,
|
||||
-0.041043, 1.046265
|
||||
],
|
||||
[
|
||||
0.152286, 1.052583, -0.204868, 0.114503, 0.786281, 0.099216, -0.003882,
|
||||
-0.048116, 1.051998
|
||||
]
|
||||
];
|
||||
|
||||
const DEUTER = [
|
||||
[1.0, 0.0, -0.0, 0.0, 1.0, 0.0, -0.0, -0.0, 1.0],
|
||||
[
|
||||
0.866435, 0.177704, -0.044139, 0.049567, 0.939063, 0.01137, -0.003453,
|
||||
0.007233, 0.99622
|
||||
],
|
||||
[
|
||||
0.760729, 0.319078, -0.079807, 0.090568, 0.889315, 0.020117, -0.006027,
|
||||
0.013325, 0.992702
|
||||
],
|
||||
[
|
||||
0.675425, 0.43385, -0.109275, 0.125303, 0.847755, 0.026942, -0.00795,
|
||||
0.018572, 0.989378
|
||||
],
|
||||
[
|
||||
0.605511, 0.52856, -0.134071, 0.155318, 0.812366, 0.032316, -0.009376,
|
||||
0.023176, 0.9862
|
||||
],
|
||||
[
|
||||
0.547494, 0.607765, -0.155259, 0.181692, 0.781742, 0.036566, -0.01041,
|
||||
0.027275, 0.983136
|
||||
],
|
||||
[
|
||||
0.498864, 0.674741, -0.173604, 0.205199, 0.754872, 0.039929, -0.011131,
|
||||
0.030969, 0.980162
|
||||
],
|
||||
[
|
||||
0.457771, 0.731899, -0.18967, 0.226409, 0.731012, 0.042579, -0.011595,
|
||||
0.034333, 0.977261
|
||||
],
|
||||
[
|
||||
0.422823, 0.781057, -0.203881, 0.245752, 0.709602, 0.044646, -0.011843,
|
||||
0.037423, 0.974421
|
||||
],
|
||||
[
|
||||
0.392952, 0.82361, -0.216562, 0.263559, 0.69021, 0.046232, -0.01191,
|
||||
0.040281, 0.97163
|
||||
],
|
||||
[
|
||||
0.367322, 0.860646, -0.227968, 0.280085, 0.672501, 0.047413, -0.01182,
|
||||
0.04294, 0.968881
|
||||
]
|
||||
];
|
||||
|
||||
const TRIT = [
|
||||
[1.0, 0.0, -0.0, 0.0, 1.0, 0.0, -0.0, -0.0, 1.0],
|
||||
[
|
||||
0.92667, 0.092514, -0.019184, 0.021191, 0.964503, 0.014306, 0.008437,
|
||||
0.054813, 0.93675
|
||||
],
|
||||
[
|
||||
0.89572, 0.13333, -0.02905, 0.029997, 0.9454, 0.024603, 0.013027,
|
||||
0.104707, 0.882266
|
||||
],
|
||||
[
|
||||
0.905871, 0.127791, -0.033662, 0.026856, 0.941251, 0.031893, 0.01341,
|
||||
0.148296, 0.838294
|
||||
],
|
||||
[
|
||||
0.948035, 0.08949, -0.037526, 0.014364, 0.946792, 0.038844, 0.010853,
|
||||
0.193991, 0.795156
|
||||
],
|
||||
[
|
||||
1.017277, 0.027029, -0.044306, -0.006113, 0.958479, 0.047634, 0.006379,
|
||||
0.248708, 0.744913
|
||||
],
|
||||
[
|
||||
1.104996, -0.046633, -0.058363, -0.032137, 0.971635, 0.060503, 0.001336,
|
||||
0.317922, 0.680742
|
||||
],
|
||||
[
|
||||
1.193214, -0.109812, -0.083402, -0.058496, 0.97941, 0.079086, -0.002346,
|
||||
0.403492, 0.598854
|
||||
],
|
||||
[
|
||||
1.257728, -0.139648, -0.118081, -0.078003, 0.975409, 0.102594,
|
||||
-0.003316, 0.501214, 0.502102
|
||||
],
|
||||
[
|
||||
1.278864, -0.125333, -0.153531, -0.084748, 0.957674, 0.127074,
|
||||
-0.000989, 0.601151, 0.399838
|
||||
],
|
||||
[
|
||||
1.255528, -0.076749, -0.178779, -0.078411, 0.930809, 0.147602, 0.004733,
|
||||
0.691367, 0.3039
|
||||
]
|
||||
];
|
||||
|
||||
const deficiency = (lut, t) => {
|
||||
let tt = Math.max(0, Math.min(1, t));
|
||||
let i = Math.round(tt / 0.1);
|
||||
let w = Math.round(tt % 0.1);
|
||||
let arr = lut[i];
|
||||
if (w > 0 && i < lut.length - 1) {
|
||||
let arr_2 = lut[i + 1];
|
||||
arr = arr.map((v, idx) => lerp(arr[idx], arr_2[idx], w));
|
||||
}
|
||||
return color => {
|
||||
let c = prepare(color);
|
||||
if (c === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
let { r, g, b } = rgb(c);
|
||||
let ret = {
|
||||
mode: 'rgb',
|
||||
r: arr[0] * r + arr[1] * g + arr[2] * b,
|
||||
g: arr[3] * r + arr[4] * g + arr[5] * b,
|
||||
b: arr[6] * r + arr[7] * g + arr[8] * b
|
||||
};
|
||||
if (c.alpha !== undefined) {
|
||||
ret.alpha = c.alpha;
|
||||
}
|
||||
return converter(c.mode)(ret);
|
||||
};
|
||||
};
|
||||
|
||||
export const filterDeficiencyProt = (severity = 1) =>
|
||||
deficiency(PROT, severity);
|
||||
export const filterDeficiencyDeuter = (severity = 1) =>
|
||||
deficiency(DEUTER, severity);
|
||||
export const filterDeficiencyTrit = (severity = 1) =>
|
||||
deficiency(TRIT, severity);
|
306
node_modules/culori/src/difference.js
generated
vendored
Normal file
306
node_modules/culori/src/difference.js
generated
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
import { getMode } from './modes.js';
|
||||
import converter from './converter.js';
|
||||
import normalizeHue from './util/normalizeHue.js';
|
||||
|
||||
const differenceHueSaturation = (std, smp) => {
|
||||
if (std.h === undefined || smp.h === undefined || !std.s || !smp.s) {
|
||||
return 0;
|
||||
}
|
||||
let std_h = normalizeHue(std.h);
|
||||
let smp_h = normalizeHue(smp.h);
|
||||
let dH = Math.sin((((smp_h - std_h + 360) / 2) * Math.PI) / 180);
|
||||
return 2 * Math.sqrt(std.s * smp.s) * dH;
|
||||
};
|
||||
|
||||
const differenceHueNaive = (std, smp) => {
|
||||
if (std.h === undefined || smp.h === undefined) {
|
||||
return 0;
|
||||
}
|
||||
let std_h = normalizeHue(std.h);
|
||||
let smp_h = normalizeHue(smp.h);
|
||||
if (Math.abs(smp_h - std_h) > 180) {
|
||||
// todo should this be normalized once again?
|
||||
return std_h - (smp_h - 360 * Math.sign(smp_h - std_h));
|
||||
}
|
||||
return smp_h - std_h;
|
||||
};
|
||||
|
||||
const differenceHueChroma = (std, smp) => {
|
||||
if (std.h === undefined || smp.h === undefined || !std.c || !smp.c) {
|
||||
return 0;
|
||||
}
|
||||
let std_h = normalizeHue(std.h);
|
||||
let smp_h = normalizeHue(smp.h);
|
||||
let dH = Math.sin((((smp_h - std_h + 360) / 2) * Math.PI) / 180);
|
||||
return 2 * Math.sqrt(std.c * smp.c) * dH;
|
||||
};
|
||||
|
||||
const differenceEuclidean = (mode = 'rgb', weights = [1, 1, 1, 0]) => {
|
||||
let def = getMode(mode);
|
||||
let channels = def.channels;
|
||||
let diffs = def.difference;
|
||||
let conv = converter(mode);
|
||||
return (std, smp) => {
|
||||
let ConvStd = conv(std);
|
||||
let ConvSmp = conv(smp);
|
||||
return Math.sqrt(
|
||||
channels.reduce((sum, k, idx) => {
|
||||
let delta = diffs[k]
|
||||
? diffs[k](ConvStd, ConvSmp)
|
||||
: ConvStd[k] - ConvSmp[k];
|
||||
return (
|
||||
sum +
|
||||
(weights[idx] || 0) * Math.pow(isNaN(delta) ? 0 : delta, 2)
|
||||
);
|
||||
}, 0)
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
const differenceCie76 = () => differenceEuclidean('lab65');
|
||||
|
||||
const differenceCie94 = (kL = 1, K1 = 0.045, K2 = 0.015) => {
|
||||
let lab = converter('lab65');
|
||||
|
||||
return (std, smp) => {
|
||||
let LabStd = lab(std);
|
||||
let LabSmp = lab(smp);
|
||||
|
||||
// Extract Lab values, and compute Chroma
|
||||
let lStd = LabStd.l;
|
||||
let aStd = LabStd.a;
|
||||
let bStd = LabStd.b;
|
||||
let cStd = Math.sqrt(aStd * aStd + bStd * bStd);
|
||||
|
||||
let lSmp = LabSmp.l;
|
||||
let aSmp = LabSmp.a;
|
||||
let bSmp = LabSmp.b;
|
||||
let cSmp = Math.sqrt(aSmp * aSmp + bSmp * bSmp);
|
||||
|
||||
let dL2 = Math.pow(lStd - lSmp, 2);
|
||||
let dC2 = Math.pow(cStd - cSmp, 2);
|
||||
let dH2 = Math.pow(aStd - aSmp, 2) + Math.pow(bStd - bSmp, 2) - dC2;
|
||||
|
||||
return Math.sqrt(
|
||||
dL2 / Math.pow(kL, 2) +
|
||||
dC2 / Math.pow(1 + K1 * cStd, 2) +
|
||||
dH2 / Math.pow(1 + K2 * cStd, 2)
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
CIEDE2000 color difference, original Matlab implementation by Gaurav Sharma
|
||||
Based on "The CIEDE2000 Color-Difference Formula: Implementation Notes, Supplementary Test Data, and Mathematical Observations"
|
||||
by Gaurav Sharma, Wencheng Wu, Edul N. Dalal in Color Research and Application, vol. 30. No. 1, pp. 21-30, February 2005.
|
||||
http://www2.ece.rochester.edu/~gsharma/ciede2000/
|
||||
*/
|
||||
|
||||
const differenceCiede2000 = (Kl = 1, Kc = 1, Kh = 1) => {
|
||||
let lab = converter('lab65');
|
||||
return (std, smp) => {
|
||||
let LabStd = lab(std);
|
||||
let LabSmp = lab(smp);
|
||||
|
||||
let lStd = LabStd.l;
|
||||
let aStd = LabStd.a;
|
||||
let bStd = LabStd.b;
|
||||
let cStd = Math.sqrt(aStd * aStd + bStd * bStd);
|
||||
|
||||
let lSmp = LabSmp.l;
|
||||
let aSmp = LabSmp.a;
|
||||
let bSmp = LabSmp.b;
|
||||
let cSmp = Math.sqrt(aSmp * aSmp + bSmp * bSmp);
|
||||
|
||||
let cAvg = (cStd + cSmp) / 2;
|
||||
|
||||
let G =
|
||||
0.5 *
|
||||
(1 -
|
||||
Math.sqrt(
|
||||
Math.pow(cAvg, 7) / (Math.pow(cAvg, 7) + Math.pow(25, 7))
|
||||
));
|
||||
|
||||
let apStd = aStd * (1 + G);
|
||||
let apSmp = aSmp * (1 + G);
|
||||
|
||||
let cpStd = Math.sqrt(apStd * apStd + bStd * bStd);
|
||||
let cpSmp = Math.sqrt(apSmp * apSmp + bSmp * bSmp);
|
||||
|
||||
let hpStd =
|
||||
Math.abs(apStd) + Math.abs(bStd) === 0
|
||||
? 0
|
||||
: Math.atan2(bStd, apStd);
|
||||
hpStd += (hpStd < 0) * 2 * Math.PI;
|
||||
|
||||
let hpSmp =
|
||||
Math.abs(apSmp) + Math.abs(bSmp) === 0
|
||||
? 0
|
||||
: Math.atan2(bSmp, apSmp);
|
||||
hpSmp += (hpSmp < 0) * 2 * Math.PI;
|
||||
|
||||
let dL = lSmp - lStd;
|
||||
let dC = cpSmp - cpStd;
|
||||
|
||||
let dhp = cpStd * cpSmp === 0 ? 0 : hpSmp - hpStd;
|
||||
dhp -= (dhp > Math.PI) * 2 * Math.PI;
|
||||
dhp += (dhp < -Math.PI) * 2 * Math.PI;
|
||||
|
||||
let dH = 2 * Math.sqrt(cpStd * cpSmp) * Math.sin(dhp / 2);
|
||||
|
||||
let Lp = (lStd + lSmp) / 2;
|
||||
let Cp = (cpStd + cpSmp) / 2;
|
||||
|
||||
let hp;
|
||||
if (cpStd * cpSmp === 0) {
|
||||
hp = hpStd + hpSmp;
|
||||
} else {
|
||||
hp = (hpStd + hpSmp) / 2;
|
||||
hp -= (Math.abs(hpStd - hpSmp) > Math.PI) * Math.PI;
|
||||
hp += (hp < 0) * 2 * Math.PI;
|
||||
}
|
||||
|
||||
let Lpm50 = Math.pow(Lp - 50, 2);
|
||||
let T =
|
||||
1 -
|
||||
0.17 * Math.cos(hp - Math.PI / 6) +
|
||||
0.24 * Math.cos(2 * hp) +
|
||||
0.32 * Math.cos(3 * hp + Math.PI / 30) -
|
||||
0.2 * Math.cos(4 * hp - (63 * Math.PI) / 180);
|
||||
|
||||
let Sl = 1 + (0.015 * Lpm50) / Math.sqrt(20 + Lpm50);
|
||||
let Sc = 1 + 0.045 * Cp;
|
||||
let Sh = 1 + 0.015 * Cp * T;
|
||||
|
||||
let deltaTheta =
|
||||
((30 * Math.PI) / 180) *
|
||||
Math.exp(-1 * Math.pow(((180 / Math.PI) * hp - 275) / 25, 2));
|
||||
let Rc =
|
||||
2 *
|
||||
Math.sqrt(Math.pow(Cp, 7) / (Math.pow(Cp, 7) + Math.pow(25, 7)));
|
||||
|
||||
let Rt = -1 * Math.sin(2 * deltaTheta) * Rc;
|
||||
|
||||
return Math.sqrt(
|
||||
Math.pow(dL / (Kl * Sl), 2) +
|
||||
Math.pow(dC / (Kc * Sc), 2) +
|
||||
Math.pow(dH / (Kh * Sh), 2) +
|
||||
(((Rt * dC) / (Kc * Sc)) * dH) / (Kh * Sh)
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
CMC (l:c) difference formula
|
||||
|
||||
References:
|
||||
https://en.wikipedia.org/wiki/Color_difference#CMC_l:c_(1984)
|
||||
http://www.brucelindbloom.com/index.html?Eqn_DeltaE_CMC.html
|
||||
*/
|
||||
const differenceCmc = (l = 1, c = 1) => {
|
||||
let lab = converter('lab65');
|
||||
|
||||
/*
|
||||
Comparte two colors:
|
||||
std - standard (first) color
|
||||
smp - sample (second) color
|
||||
*/
|
||||
return (std, smp) => {
|
||||
// convert standard color to Lab
|
||||
let LabStd = lab(std);
|
||||
let lStd = LabStd.l;
|
||||
let aStd = LabStd.a;
|
||||
let bStd = LabStd.b;
|
||||
|
||||
// Obtain hue/chroma
|
||||
let cStd = Math.sqrt(aStd * aStd + bStd * bStd);
|
||||
let hStd = Math.atan2(bStd, aStd);
|
||||
hStd = hStd + 2 * Math.PI * (hStd < 0);
|
||||
|
||||
// convert sample color to Lab, obtain LCh
|
||||
let LabSmp = lab(smp);
|
||||
let lSmp = LabSmp.l;
|
||||
let aSmp = LabSmp.a;
|
||||
let bSmp = LabSmp.b;
|
||||
|
||||
// Obtain chroma
|
||||
let cSmp = Math.sqrt(aSmp * aSmp + bSmp * bSmp);
|
||||
|
||||
// lightness delta squared
|
||||
let dL2 = Math.pow(lStd - lSmp, 2);
|
||||
|
||||
// chroma delta squared
|
||||
let dC2 = Math.pow(cStd - cSmp, 2);
|
||||
|
||||
// hue delta squared
|
||||
let dH2 = Math.pow(aStd - aSmp, 2) + Math.pow(bStd - bSmp, 2) - dC2;
|
||||
|
||||
let F = Math.sqrt(Math.pow(cStd, 4) / (Math.pow(cStd, 4) + 1900));
|
||||
let T =
|
||||
hStd >= (164 / 180) * Math.PI && hStd <= (345 / 180) * Math.PI
|
||||
? 0.56 + Math.abs(0.2 * Math.cos(hStd + (168 / 180) * Math.PI))
|
||||
: 0.36 + Math.abs(0.4 * Math.cos(hStd + (35 / 180) * Math.PI));
|
||||
|
||||
let Sl = lStd < 16 ? 0.511 : (0.040975 * lStd) / (1 + 0.01765 * lStd);
|
||||
let Sc = (0.0638 * cStd) / (1 + 0.0131 * cStd) + 0.638;
|
||||
let Sh = Sc * (F * T + 1 - F);
|
||||
|
||||
return Math.sqrt(
|
||||
dL2 / Math.pow(l * Sl, 2) +
|
||||
dC2 / Math.pow(c * Sc, 2) +
|
||||
dH2 / Math.pow(Sh, 2)
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
HyAB color difference formula, introduced in:
|
||||
|
||||
Abasi S, Amani Tehran M, Fairchild MD.
|
||||
"Distance metrics for very large color differences."
|
||||
Color Res Appl. 2019; 1–16.
|
||||
https://doi.org/10.1002/col.22451
|
||||
|
||||
PDF available at:
|
||||
|
||||
http://markfairchild.org/PDFs/PAP40.pdf
|
||||
*/
|
||||
const differenceHyab = () => {
|
||||
let lab = converter('lab65');
|
||||
return (std, smp) => {
|
||||
let LabStd = lab(std);
|
||||
let LabSmp = lab(smp);
|
||||
let dL = LabStd.l - LabSmp.l;
|
||||
let dA = LabStd.a - LabSmp.a;
|
||||
let dB = LabStd.b - LabSmp.b;
|
||||
return Math.abs(dL) + Math.sqrt(dA * dA + dB * dB);
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
"Measuring perceived color difference using YIQ NTSC
|
||||
transmission color space in mobile applications"
|
||||
|
||||
by Yuriy Kotsarenko, Fernando Ramos in:
|
||||
Programación Matemática y Software (2010)
|
||||
|
||||
Available at:
|
||||
|
||||
http://www.progmat.uaem.mx:8080/artVol2Num2/Articulo3Vol2Num2.pdf
|
||||
*/
|
||||
const differenceKotsarenkoRamos = () =>
|
||||
differenceEuclidean('yiq', [0.5053, 0.299, 0.1957]);
|
||||
|
||||
export {
|
||||
differenceHueChroma,
|
||||
differenceHueSaturation,
|
||||
differenceHueNaive,
|
||||
differenceEuclidean,
|
||||
differenceCie76,
|
||||
differenceCie94,
|
||||
differenceCiede2000,
|
||||
differenceCmc,
|
||||
differenceHyab,
|
||||
differenceKotsarenkoRamos
|
||||
};
|
48
node_modules/culori/src/dlab/definition.js
generated
vendored
Normal file
48
node_modules/culori/src/dlab/definition.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
import convertLabToLch from '../lch/convertLabToLch.js';
|
||||
import convertLchToLab from '../lch/convertLchToLab.js';
|
||||
import convertLab65ToRgb from '../lab65/convertLab65ToRgb.js';
|
||||
import convertRgbToLab65 from '../lab65/convertRgbToLab65.js';
|
||||
import convertDlchToLab65 from '../dlch/convertDlchToLab65.js';
|
||||
import convertLab65ToDlch from '../dlch/convertLab65ToDlch.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
|
||||
const convertDlabToLab65 = c => convertDlchToLab65(convertLabToLch(c, 'dlch'));
|
||||
const convertLab65ToDlab = c => convertLchToLab(convertLab65ToDlch(c), 'dlab');
|
||||
|
||||
const definition = {
|
||||
mode: 'dlab',
|
||||
|
||||
parse: ['--din99o-lab'],
|
||||
serialize: '--din99o-lab',
|
||||
|
||||
toMode: {
|
||||
lab65: convertDlabToLab65,
|
||||
rgb: c => convertLab65ToRgb(convertDlabToLab65(c))
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
lab65: convertLab65ToDlab,
|
||||
rgb: c => convertLab65ToDlab(convertRgbToLab65(c))
|
||||
},
|
||||
|
||||
channels: ['l', 'a', 'b', 'alpha'],
|
||||
|
||||
ranges: {
|
||||
l: [0, 100],
|
||||
a: [-40.09, 45.501],
|
||||
b: [-40.469, 44.344]
|
||||
},
|
||||
|
||||
interpolate: {
|
||||
l: interpolatorLinear,
|
||||
a: interpolatorLinear,
|
||||
b: interpolatorLinear,
|
||||
alpha: {
|
||||
use: interpolatorLinear,
|
||||
fixup: fixupAlpha
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
6
node_modules/culori/src/dlch/constants.js
generated
vendored
Normal file
6
node_modules/culori/src/dlch/constants.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export const kE = 1;
|
||||
export const kCH = 1;
|
||||
export const θ = (26 / 180) * Math.PI;
|
||||
export const cosθ = Math.cos(θ);
|
||||
export const sinθ = Math.sin(θ);
|
||||
export const factor = 100 / Math.log(139 / 100); // ~ 303.67
|
28
node_modules/culori/src/dlch/convertDlchToLab65.js
generated
vendored
Normal file
28
node_modules/culori/src/dlch/convertDlchToLab65.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import { kCH, kE, sinθ, cosθ, θ, factor } from './constants.js';
|
||||
|
||||
/*
|
||||
Convert DIN99o LCh to CIELab D65
|
||||
--------------------------------
|
||||
*/
|
||||
|
||||
const convertDlchToLab65 = ({ l, c, h, alpha }) => {
|
||||
let res = {
|
||||
mode: 'lab65',
|
||||
l: (Math.exp((l * kE) / factor) - 1) / 0.0039
|
||||
};
|
||||
|
||||
if (h === undefined) {
|
||||
res.a = res.b = 0;
|
||||
} else {
|
||||
let G = (Math.exp(0.0435 * c * kCH * kE) - 1) / 0.075;
|
||||
let e = G * Math.cos((h / 180) * Math.PI - θ);
|
||||
let f = G * Math.sin((h / 180) * Math.PI - θ);
|
||||
res.a = e * cosθ - (f / 0.83) * sinθ;
|
||||
res.b = e * sinθ + (f / 0.83) * cosθ;
|
||||
}
|
||||
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertDlchToLab65;
|
27
node_modules/culori/src/dlch/convertLab65ToDlch.js
generated
vendored
Normal file
27
node_modules/culori/src/dlch/convertLab65ToDlch.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { kCH, kE, sinθ, cosθ, θ, factor } from './constants.js';
|
||||
import normalizeHue from '../util/normalizeHue.js';
|
||||
|
||||
/*
|
||||
Convert CIELab D65 to DIN99o LCh
|
||||
================================
|
||||
*/
|
||||
|
||||
const convertLab65ToDlch = ({ l, a, b, alpha }) => {
|
||||
let e = a * cosθ + b * sinθ;
|
||||
let f = 0.83 * (b * cosθ - a * sinθ);
|
||||
let G = Math.sqrt(e * e + f * f);
|
||||
let res = {
|
||||
mode: 'dlch',
|
||||
l: (factor / kE) * Math.log(1 + 0.0039 * l),
|
||||
c: Math.log(1 + 0.075 * G) / (0.0435 * kCH * kE)
|
||||
};
|
||||
|
||||
if (res.c) {
|
||||
res.h = normalizeHue(((Math.atan2(f, e) + θ) / Math.PI) * 180);
|
||||
}
|
||||
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertLab65ToDlch;
|
62
node_modules/culori/src/dlch/definition.js
generated
vendored
Normal file
62
node_modules/culori/src/dlch/definition.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
import convertLabToLch from '../lch/convertLabToLch.js';
|
||||
import convertLchToLab from '../lch/convertLchToLab.js';
|
||||
import convertDlchToLab65 from './convertDlchToLab65.js';
|
||||
import convertLab65ToDlch from './convertLab65ToDlch.js';
|
||||
import convertLab65ToRgb from '../lab65/convertLab65ToRgb.js';
|
||||
import convertRgbToLab65 from '../lab65/convertRgbToLab65.js';
|
||||
|
||||
import { fixupHueShorter } from '../fixup/hue.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { differenceHueChroma } from '../difference.js';
|
||||
import { averageAngle } from '../average.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'dlch',
|
||||
|
||||
parse: ['--din99o-lch'],
|
||||
serialize: '--din99o-lch',
|
||||
|
||||
toMode: {
|
||||
lab65: convertDlchToLab65,
|
||||
dlab: c => convertLchToLab(c, 'dlab'),
|
||||
rgb: c => convertLab65ToRgb(convertDlchToLab65(c))
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
lab65: convertLab65ToDlch,
|
||||
dlab: c => convertLabToLch(c, 'dlch'),
|
||||
rgb: c => convertLab65ToDlch(convertRgbToLab65(c))
|
||||
},
|
||||
|
||||
channels: ['l', 'c', 'h', 'alpha'],
|
||||
|
||||
ranges: {
|
||||
l: [0, 100],
|
||||
c: [0, 51.484],
|
||||
h: [0, 360]
|
||||
},
|
||||
|
||||
interpolate: {
|
||||
l: interpolatorLinear,
|
||||
c: interpolatorLinear,
|
||||
h: {
|
||||
use: interpolatorLinear,
|
||||
fixup: fixupHueShorter
|
||||
},
|
||||
alpha: {
|
||||
use: interpolatorLinear,
|
||||
fixup: fixupAlpha
|
||||
}
|
||||
},
|
||||
|
||||
difference: {
|
||||
h: differenceHueChroma
|
||||
},
|
||||
|
||||
average: {
|
||||
h: averageAngle
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
3
node_modules/culori/src/easing/gamma.js
generated
vendored
Normal file
3
node_modules/culori/src/easing/gamma.js
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
const gamma = (γ = 1) => (γ === 1 ? t => t : t => Math.pow(t, γ));
|
||||
|
||||
export default gamma;
|
6
node_modules/culori/src/easing/inOutSine.js
generated
vendored
Normal file
6
node_modules/culori/src/easing/inOutSine.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
Sinusoidal (cosine) in-out easing
|
||||
*/
|
||||
const inOutSine = t => (1 - Math.cos(t * Math.PI)) / 2;
|
||||
|
||||
export default inOutSine;
|
5
node_modules/culori/src/easing/midpoint.js
generated
vendored
Normal file
5
node_modules/culori/src/easing/midpoint.js
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// Color interpolation hint exponential function
|
||||
const midpoint = (H = 0.5) => t =>
|
||||
H <= 0 ? 1 : H >= 1 ? 0 : Math.pow(t, Math.log(0.5) / Math.log(H));
|
||||
|
||||
export default midpoint;
|
7
node_modules/culori/src/easing/smootherstep.js
generated
vendored
Normal file
7
node_modules/culori/src/easing/smootherstep.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
Smootherstep easing function proposed by K. Perlin
|
||||
Reference: https://en.wikipedia.org/wiki/Smoothstep
|
||||
*/
|
||||
const smootherstep = t => t * t * t * (t * (t * 6 - 15) + 10);
|
||||
|
||||
export default smootherstep;
|
8
node_modules/culori/src/easing/smoothstep.js
generated
vendored
Normal file
8
node_modules/culori/src/easing/smoothstep.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
Smoothstep easing function and its inverse
|
||||
Reference: https://en.wikipedia.org/wiki/Smoothstep
|
||||
*/
|
||||
const easingSmoothstep = t => t * t * (3 - 2 * t);
|
||||
const easingSmoothstepInverse = t => 0.5 - Math.sin(Math.asin(1 - 2 * t) / 3);
|
||||
|
||||
export { easingSmoothstep, easingSmoothstepInverse };
|
162
node_modules/culori/src/filter.js
generated
vendored
Normal file
162
node_modules/culori/src/filter.js
generated
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
import { mapper, mapTransferLinear } from './map.js';
|
||||
import converter from './converter.js';
|
||||
import prepare from './_prepare.js';
|
||||
import { getMode } from './modes.js';
|
||||
|
||||
const minzero = v => Math.max(v, 0);
|
||||
const clamp = v => Math.max(Math.min(v, 1), 0);
|
||||
const lerp = (a, b, t) =>
|
||||
a === undefined || b === undefined ? undefined : a + t * (b - a);
|
||||
|
||||
const matrixSepia = amount => {
|
||||
let a = 1 - clamp(amount);
|
||||
return [
|
||||
0.393 + 0.607 * a,
|
||||
0.769 - 0.769 * a,
|
||||
0.189 - 0.189 * a,
|
||||
0,
|
||||
0.349 - 0.349 * a,
|
||||
0.686 + 0.314 * a,
|
||||
0.168 - 0.168 * a,
|
||||
0,
|
||||
0.272 - 0.272 * a,
|
||||
0.534 - 0.534 * a,
|
||||
0.131 + 0.869 * a,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
];
|
||||
};
|
||||
|
||||
const matrixSaturate = sat => {
|
||||
let s = minzero(sat);
|
||||
return [
|
||||
0.213 + 0.787 * s,
|
||||
0.715 - 0.715 * s,
|
||||
0.072 - 0.072 * s,
|
||||
0,
|
||||
0.213 - 0.213 * s,
|
||||
0.715 + 0.285 * s,
|
||||
0.072 - 0.072 * s,
|
||||
0,
|
||||
0.213 - 0.213 * s,
|
||||
0.715 - 0.715 * s,
|
||||
0.072 + 0.928 * s,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
];
|
||||
};
|
||||
|
||||
const matrixGrayscale = amount => {
|
||||
let a = 1 - clamp(amount);
|
||||
return [
|
||||
0.2126 + 0.7874 * a,
|
||||
0.7152 - 0.7152 * a,
|
||||
0.0722 - 0.0722 * a,
|
||||
0,
|
||||
0.2126 - 0.2126 * a,
|
||||
0.7152 + 0.2848 * a,
|
||||
0.0722 - 0.0722 * a,
|
||||
0,
|
||||
0.2126 - 0.2126 * a,
|
||||
0.7152 - 0.7152 * a,
|
||||
0.0722 + 0.9278 * a,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
];
|
||||
};
|
||||
|
||||
const matrixHueRotate = degrees => {
|
||||
let rad = (Math.PI * degrees) / 180;
|
||||
let c = Math.cos(rad);
|
||||
let s = Math.sin(rad);
|
||||
return [
|
||||
0.213 + c * 0.787 - s * 0.213,
|
||||
0.715 - c * 0.715 - s * 0.715,
|
||||
0.072 - c * 0.072 + s * 0.928,
|
||||
0,
|
||||
0.213 - c * 0.213 + s * 0.143,
|
||||
0.715 + c * 0.285 + s * 0.14,
|
||||
0.072 - c * 0.072 - s * 0.283,
|
||||
0,
|
||||
0.213 - c * 0.213 - s * 0.787,
|
||||
0.715 - c * 0.715 + s * 0.715,
|
||||
0.072 + c * 0.928 + s * 0.072,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1
|
||||
];
|
||||
};
|
||||
|
||||
const matrix = (values, mode, preserve_mode = false) => {
|
||||
let conv = converter(mode);
|
||||
let channels = getMode(mode).channels;
|
||||
return color => {
|
||||
let c = conv(color);
|
||||
if (!c) {
|
||||
return undefined;
|
||||
}
|
||||
let res = { mode };
|
||||
let ch;
|
||||
let count = channels.length;
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
ch = channels[Math.floor(i / count)];
|
||||
if (c[ch] === undefined) {
|
||||
continue;
|
||||
}
|
||||
res[ch] =
|
||||
(res[ch] || 0) + values[i] * (c[channels[i % count]] || 0);
|
||||
}
|
||||
if (!preserve_mode) {
|
||||
return res;
|
||||
}
|
||||
let prep = prepare(color);
|
||||
return prep && res.mode !== prep.mode ? converter(prep.mode)(res) : res;
|
||||
};
|
||||
};
|
||||
|
||||
const filterBrightness = (amt = 1, mode = 'rgb') => {
|
||||
let a = minzero(amt);
|
||||
return mapper(mapTransferLinear(a), mode, true);
|
||||
};
|
||||
|
||||
const filterContrast = (amt = 1, mode = 'rgb') => {
|
||||
let a = minzero(amt);
|
||||
return mapper(mapTransferLinear(a, (1 - a) / 2), mode, true);
|
||||
};
|
||||
const filterSepia = (amt = 1, mode = 'rgb') =>
|
||||
matrix(matrixSepia(amt), mode, true);
|
||||
const filterSaturate = (amt = 1, mode = 'rgb') =>
|
||||
matrix(matrixSaturate(amt), mode, true);
|
||||
const filterGrayscale = (amt = 1, mode = 'rgb') =>
|
||||
matrix(matrixGrayscale(amt), mode, true);
|
||||
const filterInvert = (amt = 1, mode = 'rgb') => {
|
||||
let a = clamp(amt);
|
||||
return mapper(
|
||||
(v, ch) => (ch === 'alpha' ? v : lerp(a, 1 - a, v)),
|
||||
mode,
|
||||
true
|
||||
);
|
||||
};
|
||||
const filterHueRotate = (deg = 0, mode = 'rgb') =>
|
||||
matrix(matrixHueRotate(deg), mode, true);
|
||||
|
||||
export {
|
||||
filterBrightness,
|
||||
filterContrast,
|
||||
filterSepia,
|
||||
filterSaturate,
|
||||
filterGrayscale,
|
||||
filterInvert,
|
||||
filterHueRotate
|
||||
};
|
13
node_modules/culori/src/fixup/alpha.js
generated
vendored
Normal file
13
node_modules/culori/src/fixup/alpha.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
const fixupAlpha = arr => {
|
||||
let some_defined = false;
|
||||
let res = arr.map(v => {
|
||||
if (v !== undefined) {
|
||||
some_defined = true;
|
||||
return v;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
return some_defined ? res : arr;
|
||||
};
|
||||
|
||||
export { fixupAlpha };
|
41
node_modules/culori/src/fixup/hue.js
generated
vendored
Normal file
41
node_modules/culori/src/fixup/hue.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
import normalizeHue from '../util/normalizeHue.js';
|
||||
|
||||
const hue = (hues, fn) => {
|
||||
return hues
|
||||
.map((hue, idx, arr) => {
|
||||
if (hue === undefined) {
|
||||
return hue;
|
||||
}
|
||||
let normalized = normalizeHue(hue);
|
||||
if (idx === 0 || hues[idx - 1] === undefined) {
|
||||
return normalized;
|
||||
}
|
||||
return fn(normalized - normalizeHue(arr[idx - 1]));
|
||||
})
|
||||
.reduce((acc, curr) => {
|
||||
if (
|
||||
!acc.length ||
|
||||
curr === undefined ||
|
||||
acc[acc.length - 1] === undefined
|
||||
) {
|
||||
acc.push(curr);
|
||||
return acc;
|
||||
}
|
||||
acc.push(curr + acc[acc.length - 1]);
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
|
||||
const fixupHueShorter = arr =>
|
||||
hue(arr, d => (Math.abs(d) <= 180 ? d : d - 360 * Math.sign(d)));
|
||||
const fixupHueLonger = arr =>
|
||||
hue(arr, d => (Math.abs(d) >= 180 || d === 0 ? d : d - 360 * Math.sign(d)));
|
||||
const fixupHueIncreasing = arr => hue(arr, d => (d >= 0 ? d : d + 360));
|
||||
const fixupHueDecreasing = arr => hue(arr, d => (d <= 0 ? d : d - 360));
|
||||
|
||||
export {
|
||||
fixupHueShorter,
|
||||
fixupHueLonger,
|
||||
fixupHueIncreasing,
|
||||
fixupHueDecreasing
|
||||
};
|
103
node_modules/culori/src/formatter.js
generated
vendored
Normal file
103
node_modules/culori/src/formatter.js
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
import converter from './converter.js';
|
||||
import round from './round.js';
|
||||
import prepare from './_prepare.js';
|
||||
import { getMode } from './modes.js';
|
||||
|
||||
let twoDecimals = round(2);
|
||||
|
||||
const clamp = value => Math.max(0, Math.min(1, value));
|
||||
const fixup = value => Math.round(clamp(value) * 255);
|
||||
|
||||
export const serializeHex = color => {
|
||||
if (color === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let r = fixup(color.r);
|
||||
let g = fixup(color.g);
|
||||
let b = fixup(color.b);
|
||||
|
||||
return '#' + ((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1);
|
||||
};
|
||||
|
||||
export const serializeHex8 = color => {
|
||||
if (color === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let a = fixup(color.alpha !== undefined ? color.alpha : 1);
|
||||
return serializeHex(color) + ((1 << 8) | a).toString(16).slice(1);
|
||||
};
|
||||
|
||||
export const serializeRgb = color => {
|
||||
if (color === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let r = color.r !== undefined ? fixup(color.r) : 'none';
|
||||
let g = color.g !== undefined ? fixup(color.g) : 'none';
|
||||
let b = color.b !== undefined ? fixup(color.b) : 'none';
|
||||
|
||||
if (color.alpha === undefined || color.alpha === 1) {
|
||||
// opaque color
|
||||
return `rgb(${r}, ${g}, ${b})`;
|
||||
} else {
|
||||
// transparent color
|
||||
return `rgba(${r}, ${g}, ${b}, ${twoDecimals(clamp(color.alpha))})`;
|
||||
}
|
||||
};
|
||||
|
||||
export const serializeHsl = color => {
|
||||
if (color === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const h = twoDecimals(color.h || 0);
|
||||
const s =
|
||||
color.s !== undefined
|
||||
? twoDecimals(clamp(color.s) * 100) + '%'
|
||||
: 'none';
|
||||
const l =
|
||||
color.l !== undefined
|
||||
? twoDecimals(clamp(color.l) * 100) + '%'
|
||||
: 'none';
|
||||
|
||||
if (color.alpha === undefined || color.alpha === 1) {
|
||||
// opaque color
|
||||
return `hsl(${h}, ${s}, ${l})`;
|
||||
} else {
|
||||
// transparent color
|
||||
return `hsla(${h}, ${s}, ${l}, ${twoDecimals(clamp(color.alpha))})`;
|
||||
}
|
||||
};
|
||||
|
||||
export const formatCss = c => {
|
||||
const color = prepare(c);
|
||||
if (!color) {
|
||||
return undefined;
|
||||
}
|
||||
const def = getMode(color.mode);
|
||||
if (!def.serialize || typeof def.serialize === 'string') {
|
||||
let res = `color(${def.serialize || `--${color.mode}`} `;
|
||||
def.channels.forEach((ch, i) => {
|
||||
if (ch !== 'alpha') {
|
||||
res +=
|
||||
(i ? ' ' : '') +
|
||||
(color[ch] !== undefined ? color[ch] : 'none');
|
||||
}
|
||||
});
|
||||
if (color.alpha !== undefined && color.alpha < 1) {
|
||||
res += ` / ${color.alpha}`;
|
||||
}
|
||||
return res + ')';
|
||||
}
|
||||
if (typeof def.serialize === 'function') {
|
||||
return def.serialize(color);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const formatHex = c => serializeHex(converter('rgb')(c));
|
||||
export const formatHex8 = c => serializeHex8(converter('rgb')(c));
|
||||
export const formatRgb = c => serializeRgb(converter('rgb')(c));
|
||||
export const formatHsl = c => serializeHsl(converter('hsl')(c));
|
59
node_modules/culori/src/hsi/convertHsiToRgb.js
generated
vendored
Normal file
59
node_modules/culori/src/hsi/convertHsiToRgb.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import normalizeHue from '../util/normalizeHue.js';
|
||||
|
||||
// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB
|
||||
|
||||
export default function convertHsiToRgb({ h, s, i, alpha }) {
|
||||
h = normalizeHue(h);
|
||||
let f = Math.abs(((h / 60) % 2) - 1);
|
||||
let res;
|
||||
switch (Math.floor(h / 60)) {
|
||||
case 0:
|
||||
res = {
|
||||
r: i * (1 + s * (3 / (2 - f) - 1)),
|
||||
g: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),
|
||||
b: i * (1 - s)
|
||||
};
|
||||
break;
|
||||
case 1:
|
||||
res = {
|
||||
r: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),
|
||||
g: i * (1 + s * (3 / (2 - f) - 1)),
|
||||
b: i * (1 - s)
|
||||
};
|
||||
break;
|
||||
case 2:
|
||||
res = {
|
||||
r: i * (1 - s),
|
||||
g: i * (1 + s * (3 / (2 - f) - 1)),
|
||||
b: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1))
|
||||
};
|
||||
break;
|
||||
case 3:
|
||||
res = {
|
||||
r: i * (1 - s),
|
||||
g: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),
|
||||
b: i * (1 + s * (3 / (2 - f) - 1))
|
||||
};
|
||||
break;
|
||||
case 4:
|
||||
res = {
|
||||
r: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),
|
||||
g: i * (1 - s),
|
||||
b: i * (1 + s * (3 / (2 - f) - 1))
|
||||
};
|
||||
break;
|
||||
case 5:
|
||||
res = {
|
||||
r: i * (1 + s * (3 / (2 - f) - 1)),
|
||||
g: i * (1 - s),
|
||||
b: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1))
|
||||
};
|
||||
break;
|
||||
default:
|
||||
res = { r: i * (1 - s), g: i * (1 - s), b: i * (1 - s) };
|
||||
}
|
||||
|
||||
res.mode = 'rgb';
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
}
|
20
node_modules/culori/src/hsi/convertRgbToHsi.js
generated
vendored
Normal file
20
node_modules/culori/src/hsi/convertRgbToHsi.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation
|
||||
|
||||
export default function convertRgbToHsi({ r, g, b, alpha }) {
|
||||
let M = Math.max(r, g, b),
|
||||
m = Math.min(r, g, b);
|
||||
let res = {
|
||||
mode: 'hsi',
|
||||
s: r + g + b === 0 ? 0 : 1 - (3 * m) / (r + g + b),
|
||||
i: (r + g + b) / 3
|
||||
};
|
||||
if (M - m !== 0)
|
||||
res.h =
|
||||
(M === r
|
||||
? (g - b) / (M - m) + (g < b) * 6
|
||||
: M === g
|
||||
? (b - r) / (M - m) + 2
|
||||
: (r - g) / (M - m) + 4) * 60;
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
}
|
47
node_modules/culori/src/hsi/definition.js
generated
vendored
Normal file
47
node_modules/culori/src/hsi/definition.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
import convertHsiToRgb from './convertHsiToRgb.js';
|
||||
import convertRgbToHsi from './convertRgbToHsi.js';
|
||||
import { fixupHueShorter } from '../fixup/hue.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { differenceHueSaturation } from '../difference.js';
|
||||
import { averageAngle } from '../average.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'hsi',
|
||||
|
||||
toMode: {
|
||||
rgb: convertHsiToRgb
|
||||
},
|
||||
|
||||
parse: ['--hsi'],
|
||||
serialize: '--hsi',
|
||||
|
||||
fromMode: {
|
||||
rgb: convertRgbToHsi
|
||||
},
|
||||
|
||||
channels: ['h', 's', 'i', 'alpha'],
|
||||
|
||||
ranges: {
|
||||
h: [0, 360]
|
||||
},
|
||||
|
||||
gamut: 'rgb',
|
||||
|
||||
interpolate: {
|
||||
h: { use: interpolatorLinear, fixup: fixupHueShorter },
|
||||
s: interpolatorLinear,
|
||||
i: interpolatorLinear,
|
||||
alpha: { use: interpolatorLinear, fixup: fixupAlpha }
|
||||
},
|
||||
|
||||
difference: {
|
||||
h: differenceHueSaturation
|
||||
},
|
||||
|
||||
average: {
|
||||
h: averageAngle
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
34
node_modules/culori/src/hsl/convertHslToRgb.js
generated
vendored
Normal file
34
node_modules/culori/src/hsl/convertHslToRgb.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import normalizeHue from '../util/normalizeHue.js';
|
||||
// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB
|
||||
|
||||
export default function convertHslToRgb({ h, s, l, alpha }) {
|
||||
h = normalizeHue(h);
|
||||
let m1 = l + s * (l < 0.5 ? l : 1 - l);
|
||||
let m2 = m1 - (m1 - l) * 2 * Math.abs(((h / 60) % 2) - 1);
|
||||
let res;
|
||||
switch (Math.floor(h / 60)) {
|
||||
case 0:
|
||||
res = { r: m1, g: m2, b: 2 * l - m1 };
|
||||
break;
|
||||
case 1:
|
||||
res = { r: m2, g: m1, b: 2 * l - m1 };
|
||||
break;
|
||||
case 2:
|
||||
res = { r: 2 * l - m1, g: m1, b: m2 };
|
||||
break;
|
||||
case 3:
|
||||
res = { r: 2 * l - m1, g: m2, b: m1 };
|
||||
break;
|
||||
case 4:
|
||||
res = { r: m2, g: 2 * l - m1, b: m1 };
|
||||
break;
|
||||
case 5:
|
||||
res = { r: m1, g: 2 * l - m1, b: m2 };
|
||||
break;
|
||||
default:
|
||||
res = { r: 2 * l - m1, g: 2 * l - m1, b: 2 * l - m1 };
|
||||
}
|
||||
res.mode = 'rgb';
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
}
|
20
node_modules/culori/src/hsl/convertRgbToHsl.js
generated
vendored
Normal file
20
node_modules/culori/src/hsl/convertRgbToHsl.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation
|
||||
|
||||
export default function convertRgbToHsl({ r, g, b, alpha }) {
|
||||
let M = Math.max(r, g, b),
|
||||
m = Math.min(r, g, b);
|
||||
let res = {
|
||||
mode: 'hsl',
|
||||
s: M === m ? 0 : (M - m) / (1 - Math.abs(M + m - 1)),
|
||||
l: 0.5 * (M + m)
|
||||
};
|
||||
if (M - m !== 0)
|
||||
res.h =
|
||||
(M === r
|
||||
? (g - b) / (M - m) + (g < b) * 6
|
||||
: M === g
|
||||
? (b - r) / (M - m) + 2
|
||||
: (r - g) / (M - m) + 4) * 60;
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
}
|
52
node_modules/culori/src/hsl/definition.js
generated
vendored
Normal file
52
node_modules/culori/src/hsl/definition.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import convertHslToRgb from './convertHslToRgb.js';
|
||||
import convertRgbToHsl from './convertRgbToHsl.js';
|
||||
import parseHslLegacy from './parseHslLegacy.js';
|
||||
import parseHsl from './parseHsl.js';
|
||||
import { fixupHueShorter } from '../fixup/hue.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { differenceHueSaturation } from '../difference.js';
|
||||
import { averageAngle } from '../average.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'hsl',
|
||||
|
||||
toMode: {
|
||||
rgb: convertHslToRgb
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
rgb: convertRgbToHsl
|
||||
},
|
||||
|
||||
channels: ['h', 's', 'l', 'alpha'],
|
||||
|
||||
ranges: {
|
||||
h: [0, 360]
|
||||
},
|
||||
|
||||
gamut: 'rgb',
|
||||
|
||||
parse: [parseHsl, parseHslLegacy],
|
||||
serialize: c =>
|
||||
`hsl(${c.h || 0} ${c.s !== undefined ? c.s * 100 + '%' : 'none'} ${
|
||||
c.l !== undefined ? c.l * 100 + '%' : 'none'
|
||||
}${c.alpha < 1 ? ` / ${c.alpha}` : ''})`,
|
||||
|
||||
interpolate: {
|
||||
h: { use: interpolatorLinear, fixup: fixupHueShorter },
|
||||
s: interpolatorLinear,
|
||||
l: interpolatorLinear,
|
||||
alpha: { use: interpolatorLinear, fixup: fixupAlpha }
|
||||
},
|
||||
|
||||
difference: {
|
||||
h: differenceHueSaturation
|
||||
},
|
||||
|
||||
average: {
|
||||
h: averageAngle
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
38
node_modules/culori/src/hsl/parseHsl.js
generated
vendored
Normal file
38
node_modules/culori/src/hsl/parseHsl.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Tok } from '../parse.js';
|
||||
|
||||
function parseHsl(color, parsed) {
|
||||
if (!parsed || (parsed[0] !== 'hsl' && parsed[0] !== 'hsla')) {
|
||||
return undefined;
|
||||
}
|
||||
const res = { mode: 'hsl' };
|
||||
const [, h, s, l, alpha] = parsed;
|
||||
|
||||
if (h.type !== Tok.None) {
|
||||
if (h.type === Tok.Percentage) {
|
||||
return undefined;
|
||||
}
|
||||
res.h = h.value;
|
||||
}
|
||||
|
||||
if (s.type !== Tok.None) {
|
||||
if (s.type === Tok.Hue) {
|
||||
return undefined;
|
||||
}
|
||||
res.s = s.type === Tok.Number ? s.value : s.value / 100;
|
||||
}
|
||||
|
||||
if (l.type !== Tok.None) {
|
||||
if (l.type === Tok.Hue) {
|
||||
return undefined;
|
||||
}
|
||||
res.l = l.type === Tok.Number ? l.value : l.value / 100;
|
||||
}
|
||||
|
||||
if (alpha.type !== Tok.None) {
|
||||
res.alpha = alpha.type === Tok.Number ? alpha.value : alpha.value / 100;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
export default parseHsl;
|
39
node_modules/culori/src/hsl/parseHslLegacy.js
generated
vendored
Normal file
39
node_modules/culori/src/hsl/parseHslLegacy.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import hueToDeg from '../util/hue.js';
|
||||
import { hue, per, num_per, c } from '../util/regex.js';
|
||||
|
||||
/*
|
||||
hsl() regular expressions for legacy format
|
||||
Reference: https://drafts.csswg.org/css-color/#the-hsl-notation
|
||||
*/
|
||||
const hsl_old = new RegExp(
|
||||
`^hsla?\\(\\s*${hue}${c}${per}${c}${per}\\s*(?:,\\s*${num_per}\\s*)?\\)$`
|
||||
);
|
||||
|
||||
const parseHslLegacy = color => {
|
||||
let match = color.match(hsl_old);
|
||||
if (!match) return;
|
||||
let res = { mode: 'hsl' };
|
||||
|
||||
if (match[3] !== undefined) {
|
||||
res.h = +match[3];
|
||||
} else if (match[1] !== undefined && match[2] !== undefined) {
|
||||
res.h = hueToDeg(match[1], match[2]);
|
||||
}
|
||||
|
||||
if (match[4] !== undefined) {
|
||||
res.s = Math.min(Math.max(0, match[4] / 100), 1);
|
||||
}
|
||||
|
||||
if (match[5] !== undefined) {
|
||||
res.l = Math.min(Math.max(0, match[5] / 100), 1);
|
||||
}
|
||||
|
||||
if (match[6] !== undefined) {
|
||||
res.alpha = match[6] / 100;
|
||||
} else if (match[7] !== undefined) {
|
||||
res.alpha = +match[7];
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export default parseHslLegacy;
|
34
node_modules/culori/src/hsv/convertHsvToRgb.js
generated
vendored
Normal file
34
node_modules/culori/src/hsv/convertHsvToRgb.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import normalizeHue from '../util/normalizeHue.js';
|
||||
|
||||
// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB
|
||||
|
||||
export default function convertHsvToRgb({ h, s, v, alpha }) {
|
||||
h = normalizeHue(h);
|
||||
let f = Math.abs(((h / 60) % 2) - 1);
|
||||
let res;
|
||||
switch (Math.floor(h / 60)) {
|
||||
case 0:
|
||||
res = { r: v, g: v * (1 - s * f), b: v * (1 - s) };
|
||||
break;
|
||||
case 1:
|
||||
res = { r: v * (1 - s * f), g: v, b: v * (1 - s) };
|
||||
break;
|
||||
case 2:
|
||||
res = { r: v * (1 - s), g: v, b: v * (1 - s * f) };
|
||||
break;
|
||||
case 3:
|
||||
res = { r: v * (1 - s), g: v * (1 - s * f), b: v };
|
||||
break;
|
||||
case 4:
|
||||
res = { r: v * (1 - s * f), g: v * (1 - s), b: v };
|
||||
break;
|
||||
case 5:
|
||||
res = { r: v, g: v * (1 - s), b: v * (1 - s * f) };
|
||||
break;
|
||||
default:
|
||||
res = { r: v * (1 - s), g: v * (1 - s), b: v * (1 - s) };
|
||||
}
|
||||
res.mode = 'rgb';
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
}
|
20
node_modules/culori/src/hsv/convertRgbToHsv.js
generated
vendored
Normal file
20
node_modules/culori/src/hsv/convertRgbToHsv.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation
|
||||
|
||||
export default function convertRgbToHsv({ r, g, b, alpha }) {
|
||||
let M = Math.max(r, g, b),
|
||||
m = Math.min(r, g, b);
|
||||
let res = {
|
||||
mode: 'hsv',
|
||||
s: M === 0 ? 0 : 1 - m / M,
|
||||
v: M
|
||||
};
|
||||
if (M - m !== 0)
|
||||
res.h =
|
||||
(M === r
|
||||
? (g - b) / (M - m) + (g < b) * 6
|
||||
: M === g
|
||||
? (b - r) / (M - m) + 2
|
||||
: (r - g) / (M - m) + 4) * 60;
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
}
|
47
node_modules/culori/src/hsv/definition.js
generated
vendored
Normal file
47
node_modules/culori/src/hsv/definition.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
import convertHsvToRgb from './convertHsvToRgb.js';
|
||||
import convertRgbToHsv from './convertRgbToHsv.js';
|
||||
import { fixupHueShorter } from '../fixup/hue.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { differenceHueSaturation } from '../difference.js';
|
||||
import { averageAngle } from '../average.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'hsv',
|
||||
|
||||
toMode: {
|
||||
rgb: convertHsvToRgb
|
||||
},
|
||||
|
||||
parse: ['--hsv'],
|
||||
serialize: '--hsv',
|
||||
|
||||
fromMode: {
|
||||
rgb: convertRgbToHsv
|
||||
},
|
||||
|
||||
channels: ['h', 's', 'v', 'alpha'],
|
||||
|
||||
ranges: {
|
||||
h: [0, 360]
|
||||
},
|
||||
|
||||
gamut: 'rgb',
|
||||
|
||||
interpolate: {
|
||||
h: { use: interpolatorLinear, fixup: fixupHueShorter },
|
||||
s: interpolatorLinear,
|
||||
v: interpolatorLinear,
|
||||
alpha: { use: interpolatorLinear, fixup: fixupAlpha }
|
||||
},
|
||||
|
||||
difference: {
|
||||
h: differenceHueSaturation
|
||||
},
|
||||
|
||||
average: {
|
||||
h: averageAngle
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
26
node_modules/culori/src/hwb/convertHwbToRgb.js
generated
vendored
Normal file
26
node_modules/culori/src/hwb/convertHwbToRgb.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
HWB to RGB converter
|
||||
--------------------
|
||||
|
||||
References:
|
||||
* https://drafts.csswg.org/css-color/#hwb-to-rgb
|
||||
* https://en.wikipedia.org/wiki/HWB_color_model
|
||||
* http://alvyray.com/Papers/CG/HWB_JGTv208.pdf
|
||||
*/
|
||||
|
||||
import convertHsvToRgb from '../hsv/convertHsvToRgb.js';
|
||||
|
||||
export default function convertHwbToRgb({ h, w, b, alpha }) {
|
||||
// normalize w + b to 1
|
||||
if (w + b > 1) {
|
||||
let s = w + b;
|
||||
w /= s;
|
||||
b /= s;
|
||||
}
|
||||
return convertHsvToRgb({
|
||||
h: h,
|
||||
s: b === 1 ? 1 : 1 - w / (1 - b),
|
||||
v: 1 - b,
|
||||
alpha: alpha
|
||||
});
|
||||
}
|
24
node_modules/culori/src/hwb/convertRgbToHwb.js
generated
vendored
Normal file
24
node_modules/culori/src/hwb/convertRgbToHwb.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
RGB to HWB converter
|
||||
--------------------
|
||||
|
||||
References:
|
||||
* https://drafts.csswg.org/css-color/#hwb-to-rgb
|
||||
* https://en.wikipedia.org/wiki/HWB_color_model
|
||||
* http://alvyray.com/Papers/CG/HWB_JGTv208.pdf
|
||||
*/
|
||||
|
||||
import convertRgbToHsv from '../hsv/convertRgbToHsv.js';
|
||||
|
||||
export default function convertRgbToHwb(rgba) {
|
||||
let hsv = convertRgbToHsv(rgba);
|
||||
if (hsv === undefined) return undefined;
|
||||
let res = {
|
||||
mode: 'hwb',
|
||||
w: (1 - hsv.s) * hsv.v,
|
||||
b: 1 - hsv.v
|
||||
};
|
||||
if (hsv.h !== undefined) res.h = hsv.h;
|
||||
if (hsv.alpha !== undefined) res.alpha = hsv.alpha;
|
||||
return res;
|
||||
}
|
51
node_modules/culori/src/hwb/definition.js
generated
vendored
Normal file
51
node_modules/culori/src/hwb/definition.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
import convertHwbToRgb from './convertHwbToRgb.js';
|
||||
import convertRgbToHwb from './convertRgbToHwb.js';
|
||||
import parseHwb from './parseHwb.js';
|
||||
import { fixupHueShorter } from '../fixup/hue.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { differenceHueNaive } from '../difference.js';
|
||||
import { averageAngle } from '../average.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'hwb',
|
||||
|
||||
toMode: {
|
||||
rgb: convertHwbToRgb
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
rgb: convertRgbToHwb
|
||||
},
|
||||
|
||||
channels: ['h', 'w', 'b', 'alpha'],
|
||||
|
||||
ranges: {
|
||||
h: [0, 360]
|
||||
},
|
||||
|
||||
gamut: 'rgb',
|
||||
|
||||
parse: [parseHwb],
|
||||
serialize: c =>
|
||||
`hwb(${c.h || 0} ${c.w * 100}% ${c.b * 100}%${
|
||||
c.alpha < 1 ? ` / ${c.alpha}` : ''
|
||||
})`,
|
||||
|
||||
interpolate: {
|
||||
h: { use: interpolatorLinear, fixup: fixupHueShorter },
|
||||
w: interpolatorLinear,
|
||||
b: interpolatorLinear,
|
||||
alpha: { use: interpolatorLinear, fixup: fixupAlpha }
|
||||
},
|
||||
|
||||
difference: {
|
||||
h: differenceHueNaive
|
||||
},
|
||||
|
||||
average: {
|
||||
h: averageAngle
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
38
node_modules/culori/src/hwb/parseHwb.js
generated
vendored
Normal file
38
node_modules/culori/src/hwb/parseHwb.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Tok } from '../parse.js';
|
||||
|
||||
function ParseHwb(color, parsed) {
|
||||
if (!parsed || parsed[0] !== 'hwb') {
|
||||
return undefined;
|
||||
}
|
||||
const res = { mode: 'hwb' };
|
||||
const [, h, w, b, alpha] = parsed;
|
||||
|
||||
if (h.type !== Tok.None) {
|
||||
if (h.type === Tok.Percentage) {
|
||||
return undefined;
|
||||
}
|
||||
res.h = h.value;
|
||||
}
|
||||
|
||||
if (w.type !== Tok.None) {
|
||||
if (w.type === Tok.Hue) {
|
||||
return undefined;
|
||||
}
|
||||
res.w = w.type === Tok.Number ? w.value : w.value / 100;
|
||||
}
|
||||
|
||||
if (b.type !== Tok.None) {
|
||||
if (b.type === Tok.Hue) {
|
||||
return undefined;
|
||||
}
|
||||
res.b = b.type === Tok.Number ? b.value : b.value / 100;
|
||||
}
|
||||
|
||||
if (alpha.type !== Tok.None) {
|
||||
res.alpha = alpha.type === Tok.Number ? alpha.value : alpha.value / 100;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
export default ParseHwb;
|
226
node_modules/culori/src/index-fn.js
generated
vendored
Normal file
226
node_modules/culori/src/index-fn.js
generated
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
// Color space definitions
|
||||
export { default as modeA98 } from './a98/definition.js';
|
||||
export { default as modeCubehelix } from './cubehelix/definition.js';
|
||||
export { default as modeDlab } from './dlab/definition.js';
|
||||
export { default as modeDlch } from './dlch/definition.js';
|
||||
export { default as modeHsi } from './hsi/definition.js';
|
||||
export { default as modeHsl } from './hsl/definition.js';
|
||||
export { default as modeHsv } from './hsv/definition.js';
|
||||
export { default as modeHwb } from './hwb/definition.js';
|
||||
export { default as modeJab } from './jab/definition.js';
|
||||
export { default as modeJch } from './jch/definition.js';
|
||||
export { default as modeLab } from './lab/definition.js';
|
||||
export { default as modeLab65 } from './lab65/definition.js';
|
||||
export { default as modeLch } from './lch/definition.js';
|
||||
export { default as modeLch65 } from './lch65/definition.js';
|
||||
export { default as modeLchuv } from './lchuv/definition.js';
|
||||
export { default as modeLrgb } from './lrgb/definition.js';
|
||||
export { default as modeLuv } from './luv/definition.js';
|
||||
export { default as modeOkhsl } from './okhsl/modeOkhsl.js';
|
||||
export { default as modeOkhsv } from './okhsv/modeOkhsv.js';
|
||||
export { default as modeOklab } from './oklab/definition.js';
|
||||
export { default as modeOklch } from './oklch/definition.js';
|
||||
export { default as modeP3 } from './p3/definition.js';
|
||||
export { default as modeProphoto } from './prophoto/definition.js';
|
||||
export { default as modeRec2020 } from './rec2020/definition.js';
|
||||
export { default as modeRgb } from './rgb/definition.js';
|
||||
export { default as modeXyb } from './xyb/definition.js';
|
||||
export { default as modeXyz50 } from './xyz50/definition.js';
|
||||
export { default as modeXyz65 } from './xyz65/definition.js';
|
||||
export { default as modeYiq } from './yiq/definition.js';
|
||||
|
||||
export { default as converter } from './converter.js';
|
||||
|
||||
export {
|
||||
serializeHex,
|
||||
serializeHex8,
|
||||
serializeRgb,
|
||||
serializeHsl,
|
||||
formatHex,
|
||||
formatHex8,
|
||||
formatRgb,
|
||||
formatHsl,
|
||||
formatCss
|
||||
} from './formatter.js';
|
||||
|
||||
export { default as colorsNamed } from './colors/named.js';
|
||||
export { default as blend } from './blend.js';
|
||||
export { default as random } from './random.js';
|
||||
|
||||
export {
|
||||
fixupHueShorter,
|
||||
fixupHueLonger,
|
||||
fixupHueIncreasing,
|
||||
fixupHueDecreasing
|
||||
} from './fixup/hue.js';
|
||||
|
||||
export { fixupAlpha } from './fixup/alpha.js';
|
||||
|
||||
export {
|
||||
mapper,
|
||||
mapAlphaMultiply,
|
||||
mapAlphaDivide,
|
||||
mapTransferLinear,
|
||||
mapTransferGamma
|
||||
} from './map.js';
|
||||
|
||||
export { average, averageAngle, averageNumber } from './average.js';
|
||||
|
||||
export { default as round } from './round.js';
|
||||
export {
|
||||
interpolate,
|
||||
interpolateWith,
|
||||
interpolateWithPremultipliedAlpha
|
||||
} from './interpolate/interpolate.js';
|
||||
|
||||
export { interpolatorLinear } from './interpolate/linear.js';
|
||||
|
||||
export { interpolatorPiecewise } from './interpolate/piecewise.js';
|
||||
|
||||
export {
|
||||
interpolatorSplineBasis,
|
||||
interpolatorSplineBasisClosed
|
||||
} from './interpolate/splineBasis.js';
|
||||
|
||||
export {
|
||||
interpolatorSplineNatural,
|
||||
interpolatorSplineNaturalClosed
|
||||
} from './interpolate/splineNatural.js';
|
||||
|
||||
export {
|
||||
interpolatorSplineMonotone,
|
||||
interpolatorSplineMonotone2,
|
||||
interpolatorSplineMonotoneClosed
|
||||
} from './interpolate/splineMonotone.js';
|
||||
|
||||
export { lerp, unlerp, blerp, trilerp } from './interpolate/lerp.js';
|
||||
export { default as samples } from './samples.js';
|
||||
export {
|
||||
displayable,
|
||||
inGamut,
|
||||
clampRgb,
|
||||
clampChroma,
|
||||
clampGamut,
|
||||
toGamut
|
||||
} from './clamp.js';
|
||||
export { default as nearest } from './nearest.js';
|
||||
export { useMode, getMode, useParser, removeParser } from './modes.js';
|
||||
export { default as parse } from './parse.js';
|
||||
|
||||
export {
|
||||
differenceEuclidean,
|
||||
differenceCie76,
|
||||
differenceCie94,
|
||||
differenceCiede2000,
|
||||
differenceCmc,
|
||||
differenceHyab,
|
||||
differenceHueSaturation,
|
||||
differenceHueChroma,
|
||||
differenceHueNaive,
|
||||
differenceKotsarenkoRamos
|
||||
} from './difference.js';
|
||||
|
||||
export {
|
||||
filterBrightness,
|
||||
filterContrast,
|
||||
filterSepia,
|
||||
filterInvert,
|
||||
filterSaturate,
|
||||
filterGrayscale,
|
||||
filterHueRotate
|
||||
} from './filter.js';
|
||||
|
||||
export {
|
||||
filterDeficiencyProt,
|
||||
filterDeficiencyDeuter,
|
||||
filterDeficiencyTrit
|
||||
} from './deficiency.js';
|
||||
|
||||
// Easings
|
||||
export { default as easingMidpoint } from './easing/midpoint.js';
|
||||
export {
|
||||
easingSmoothstep,
|
||||
easingSmoothstepInverse
|
||||
} from './easing/smoothstep.js';
|
||||
export { default as easingSmootherstep } from './easing/smootherstep.js';
|
||||
export { default as easingInOutSine } from './easing/inOutSine.js';
|
||||
export { default as easingGamma } from './easing/gamma.js';
|
||||
|
||||
export {
|
||||
luminance as wcagLuminance,
|
||||
contrast as wcagContrast
|
||||
} from './wcag.js';
|
||||
|
||||
export { default as parseHsl } from './hsl/parseHsl.js';
|
||||
export { default as parseHwb } from './hwb/parseHwb.js';
|
||||
export { default as parseLab } from './lab/parseLab.js';
|
||||
export { default as parseLch } from './lch/parseLch.js';
|
||||
export { default as parseNamed } from './rgb/parseNamed.js';
|
||||
export { default as parseTransparent } from './rgb/parseTransparent.js';
|
||||
export { default as parseHex } from './rgb/parseHex.js';
|
||||
export { default as parseRgb } from './rgb/parseRgb.js';
|
||||
export { default as parseHslLegacy } from './hsl/parseHslLegacy.js';
|
||||
export { default as parseRgbLegacy } from './rgb/parseRgbLegacy.js';
|
||||
export { default as parseOklab } from './oklab/parseOklab.js';
|
||||
export { default as parseOklch } from './oklch/parseOklch.js';
|
||||
|
||||
export { default as convertA98ToXyz65 } from './a98/convertA98ToXyz65.js';
|
||||
export { default as convertCubehelixToRgb } from './cubehelix/convertCubehelixToRgb.js';
|
||||
export { default as convertDlchToLab65 } from './dlch/convertDlchToLab65.js';
|
||||
export { default as convertHsiToRgb } from './hsi/convertHsiToRgb.js';
|
||||
export { default as convertHslToRgb } from './hsl/convertHslToRgb.js';
|
||||
export { default as convertHsvToRgb } from './hsv/convertHsvToRgb.js';
|
||||
export { default as convertHwbToRgb } from './hwb/convertHwbToRgb.js';
|
||||
export { default as convertJabToJch } from './jch/convertJabToJch.js';
|
||||
export { default as convertJabToRgb } from './jab/convertJabToRgb.js';
|
||||
export { default as convertJabToXyz65 } from './jab/convertJabToXyz65.js';
|
||||
export { default as convertJchToJab } from './jch/convertJchToJab.js';
|
||||
export { default as convertLab65ToDlch } from './dlch/convertLab65ToDlch.js';
|
||||
export { default as convertLab65ToRgb } from './lab65/convertLab65ToRgb.js';
|
||||
export { default as convertLab65ToXyz65 } from './lab65/convertLab65ToXyz65.js';
|
||||
export { default as convertLabToLch } from './lch/convertLabToLch.js';
|
||||
export { default as convertLabToRgb } from './lab/convertLabToRgb.js';
|
||||
export { default as convertLabToXyz50 } from './lab/convertLabToXyz50.js';
|
||||
export { default as convertLchToLab } from './lch/convertLchToLab.js';
|
||||
export { default as convertLchuvToLuv } from './lchuv/convertLchuvToLuv.js';
|
||||
export { default as convertLrgbToOklab } from './oklab/convertLrgbToOklab.js';
|
||||
export { default as convertLrgbToRgb } from './lrgb/convertLrgbToRgb.js';
|
||||
export { default as convertLuvToLchuv } from './lchuv/convertLuvToLchuv.js';
|
||||
export { default as convertLuvToXyz50 } from './luv/convertLuvToXyz50.js';
|
||||
export { default as convertOkhslToOklab } from './okhsl/convertOkhslToOklab.js';
|
||||
export { default as convertOkhsvToOklab } from './okhsv/convertOkhsvToOklab.js';
|
||||
export { default as convertOklabToLrgb } from './oklab/convertOklabToLrgb.js';
|
||||
export { default as convertOklabToOkhsl } from './okhsl/convertOklabToOkhsl.js';
|
||||
export { default as convertOklabToOkhsv } from './okhsv/convertOklabToOkhsv.js';
|
||||
export { default as convertOklabToRgb } from './oklab/convertOklabToRgb.js';
|
||||
export { default as convertP3ToXyz65 } from './p3/convertP3ToXyz65.js';
|
||||
export { default as convertProphotoToXyz50 } from './prophoto/convertProphotoToXyz50.js';
|
||||
export { default as convertRec2020ToXyz65 } from './rec2020/convertRec2020ToXyz65.js';
|
||||
export { default as convertRgbToCubehelix } from './cubehelix/convertRgbToCubehelix.js';
|
||||
export { default as convertRgbToHsi } from './hsi/convertRgbToHsi.js';
|
||||
export { default as convertRgbToHsl } from './hsl/convertRgbToHsl.js';
|
||||
export { default as convertRgbToHsv } from './hsv/convertRgbToHsv.js';
|
||||
export { default as convertRgbToHwb } from './hwb/convertRgbToHwb.js';
|
||||
export { default as convertRgbToJab } from './jab/convertRgbToJab.js';
|
||||
export { default as convertRgbToLab } from './lab/convertRgbToLab.js';
|
||||
export { default as convertRgbToLab65 } from './lab65/convertRgbToLab65.js';
|
||||
export { default as convertRgbToLrgb } from './lrgb/convertRgbToLrgb.js';
|
||||
export { default as convertRgbToOklab } from './oklab/convertRgbToOklab.js';
|
||||
export { default as convertRgbToXyz50 } from './xyz50/convertRgbToXyz50.js';
|
||||
export { default as convertRgbToXyz65 } from './xyz65/convertRgbToXyz65.js';
|
||||
export { default as convertRgbToYiq } from './yiq/convertRgbToYiq.js';
|
||||
export { default as convertRgbToXyb } from './xyb/convertRgbToXyb.js';
|
||||
export { default as convertXybToRgb } from './xyb/convertXybToRgb.js';
|
||||
export { default as convertXyz65ToA98 } from './a98/convertXyz65ToA98.js';
|
||||
export { default as convertXyz65ToJab } from './jab/convertXyz65ToJab.js';
|
||||
export { default as convertXyz65ToLab65 } from './lab65/convertXyz65ToLab65.js';
|
||||
export { default as convertXyz65ToP3 } from './p3/convertXyz65ToP3.js';
|
||||
export { default as convertXyz65ToRec2020 } from './rec2020/convertXyz65ToRec2020.js';
|
||||
export { default as convertXyz65ToRgb } from './xyz65/convertXyz65ToRgb.js';
|
||||
export { default as convertXyz65ToXyz50 } from './xyz65/convertXyz65ToXyz50.js';
|
||||
export { default as convertXyz50ToLab } from './lab/convertXyz50ToLab.js';
|
||||
export { default as convertXyz50ToLuv } from './luv/convertXyz50ToLuv.js';
|
||||
export { default as convertXyz50ToProphoto } from './prophoto/convertXyz50ToProphoto.js';
|
||||
export { default as convertXyz50ToRgb } from './xyz50/convertXyz50ToRgb.js';
|
||||
export { default as convertXyz50ToXyz65 } from './xyz65/convertXyz50ToXyz65.js';
|
||||
export { default as convertYiqToRgb } from './yiq/convertYiqToRgb.js';
|
289
node_modules/culori/src/index.js
generated
vendored
Normal file
289
node_modules/culori/src/index.js
generated
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
// Color space definitions
|
||||
import modeA98 from './a98/definition.js';
|
||||
import modeCubehelix from './cubehelix/definition.js';
|
||||
import modeDlab from './dlab/definition.js';
|
||||
import modeDlch from './dlch/definition.js';
|
||||
import modeHsi from './hsi/definition.js';
|
||||
import modeHsl from './hsl/definition.js';
|
||||
import modeHsv from './hsv/definition.js';
|
||||
import modeHwb from './hwb/definition.js';
|
||||
import modeJab from './jab/definition.js';
|
||||
import modeJch from './jch/definition.js';
|
||||
import modeLab from './lab/definition.js';
|
||||
import modeLab65 from './lab65/definition.js';
|
||||
import modeLch from './lch/definition.js';
|
||||
import modeLch65 from './lch65/definition.js';
|
||||
import modeLchuv from './lchuv/definition.js';
|
||||
import modeLrgb from './lrgb/definition.js';
|
||||
import modeLuv from './luv/definition.js';
|
||||
import modeOkhsl from './okhsl/modeOkhsl.js';
|
||||
import modeOkhsv from './okhsv/modeOkhsv.js';
|
||||
import modeOklab from './oklab/definition.js';
|
||||
import modeOklch from './oklch/definition.js';
|
||||
import modeP3 from './p3/definition.js';
|
||||
import modeProphoto from './prophoto/definition.js';
|
||||
import modeRec2020 from './rec2020/definition.js';
|
||||
import modeRgb from './rgb/definition.js';
|
||||
import modeXyb from './xyb/definition.js';
|
||||
import modeXyz50 from './xyz50/definition.js';
|
||||
import modeXyz65 from './xyz65/definition.js';
|
||||
import modeYiq from './yiq/definition.js';
|
||||
import { useMode } from './modes.js';
|
||||
|
||||
export { default as converter } from './converter.js';
|
||||
|
||||
export {
|
||||
serializeHex,
|
||||
serializeHex8,
|
||||
serializeRgb,
|
||||
serializeHsl,
|
||||
formatHex,
|
||||
formatHex8,
|
||||
formatRgb,
|
||||
formatHsl,
|
||||
formatCss
|
||||
} from './formatter.js';
|
||||
|
||||
export { default as colorsNamed } from './colors/named.js';
|
||||
export { default as blend } from './blend.js';
|
||||
export { default as random } from './random.js';
|
||||
|
||||
export {
|
||||
fixupHueShorter,
|
||||
fixupHueLonger,
|
||||
fixupHueIncreasing,
|
||||
fixupHueDecreasing
|
||||
} from './fixup/hue.js';
|
||||
|
||||
export { fixupAlpha } from './fixup/alpha.js';
|
||||
|
||||
export {
|
||||
mapper,
|
||||
mapAlphaMultiply,
|
||||
mapAlphaDivide,
|
||||
mapTransferLinear,
|
||||
mapTransferGamma
|
||||
} from './map.js';
|
||||
|
||||
export { average, averageAngle, averageNumber } from './average.js';
|
||||
|
||||
export { default as round } from './round.js';
|
||||
export {
|
||||
interpolate,
|
||||
interpolateWith,
|
||||
interpolateWithPremultipliedAlpha
|
||||
} from './interpolate/interpolate.js';
|
||||
|
||||
export { interpolatorLinear } from './interpolate/linear.js';
|
||||
|
||||
export { interpolatorPiecewise } from './interpolate/piecewise.js';
|
||||
|
||||
export {
|
||||
interpolatorSplineBasis,
|
||||
interpolatorSplineBasisClosed
|
||||
} from './interpolate/splineBasis.js';
|
||||
|
||||
export {
|
||||
interpolatorSplineNatural,
|
||||
interpolatorSplineNaturalClosed
|
||||
} from './interpolate/splineNatural.js';
|
||||
|
||||
export {
|
||||
interpolatorSplineMonotone,
|
||||
interpolatorSplineMonotone2,
|
||||
interpolatorSplineMonotoneClosed
|
||||
} from './interpolate/splineMonotone.js';
|
||||
|
||||
export { lerp, unlerp, blerp, trilerp } from './interpolate/lerp.js';
|
||||
export { default as samples } from './samples.js';
|
||||
export {
|
||||
displayable,
|
||||
inGamut,
|
||||
clampRgb,
|
||||
clampChroma,
|
||||
clampGamut,
|
||||
toGamut
|
||||
} from './clamp.js';
|
||||
export { default as nearest } from './nearest.js';
|
||||
export { useMode, getMode, useParser, removeParser } from './modes.js';
|
||||
export { default as parse } from './parse.js';
|
||||
|
||||
export {
|
||||
differenceEuclidean,
|
||||
differenceCie76,
|
||||
differenceCie94,
|
||||
differenceCiede2000,
|
||||
differenceCmc,
|
||||
differenceHyab,
|
||||
differenceHueSaturation,
|
||||
differenceHueChroma,
|
||||
differenceHueNaive,
|
||||
differenceKotsarenkoRamos
|
||||
} from './difference.js';
|
||||
|
||||
export {
|
||||
filterBrightness,
|
||||
filterContrast,
|
||||
filterSepia,
|
||||
filterInvert,
|
||||
filterSaturate,
|
||||
filterGrayscale,
|
||||
filterHueRotate
|
||||
} from './filter.js';
|
||||
|
||||
export {
|
||||
filterDeficiencyProt,
|
||||
filterDeficiencyDeuter,
|
||||
filterDeficiencyTrit
|
||||
} from './deficiency.js';
|
||||
|
||||
// Easings
|
||||
export { default as easingMidpoint } from './easing/midpoint.js';
|
||||
export {
|
||||
easingSmoothstep,
|
||||
easingSmoothstepInverse
|
||||
} from './easing/smoothstep.js';
|
||||
export { default as easingSmootherstep } from './easing/smootherstep.js';
|
||||
export { default as easingInOutSine } from './easing/inOutSine.js';
|
||||
export { default as easingGamma } from './easing/gamma.js';
|
||||
|
||||
export {
|
||||
luminance as wcagLuminance,
|
||||
contrast as wcagContrast
|
||||
} from './wcag.js';
|
||||
|
||||
export { default as parseHsl } from './hsl/parseHsl.js';
|
||||
export { default as parseHwb } from './hwb/parseHwb.js';
|
||||
export { default as parseLab } from './lab/parseLab.js';
|
||||
export { default as parseLch } from './lch/parseLch.js';
|
||||
export { default as parseNamed } from './rgb/parseNamed.js';
|
||||
export { default as parseTransparent } from './rgb/parseTransparent.js';
|
||||
export { default as parseHex } from './rgb/parseHex.js';
|
||||
export { default as parseRgb } from './rgb/parseRgb.js';
|
||||
export { default as parseHslLegacy } from './hsl/parseHslLegacy.js';
|
||||
export { default as parseRgbLegacy } from './rgb/parseRgbLegacy.js';
|
||||
export { default as parseOklab } from './oklab/parseOklab.js';
|
||||
export { default as parseOklch } from './oklch/parseOklch.js';
|
||||
|
||||
export { default as convertA98ToXyz65 } from './a98/convertA98ToXyz65.js';
|
||||
export { default as convertCubehelixToRgb } from './cubehelix/convertCubehelixToRgb.js';
|
||||
export { default as convertDlchToLab65 } from './dlch/convertDlchToLab65.js';
|
||||
export { default as convertHsiToRgb } from './hsi/convertHsiToRgb.js';
|
||||
export { default as convertHslToRgb } from './hsl/convertHslToRgb.js';
|
||||
export { default as convertHsvToRgb } from './hsv/convertHsvToRgb.js';
|
||||
export { default as convertHwbToRgb } from './hwb/convertHwbToRgb.js';
|
||||
export { default as convertJabToJch } from './jch/convertJabToJch.js';
|
||||
export { default as convertJabToRgb } from './jab/convertJabToRgb.js';
|
||||
export { default as convertJabToXyz65 } from './jab/convertJabToXyz65.js';
|
||||
export { default as convertJchToJab } from './jch/convertJchToJab.js';
|
||||
export { default as convertLab65ToDlch } from './dlch/convertLab65ToDlch.js';
|
||||
export { default as convertLab65ToRgb } from './lab65/convertLab65ToRgb.js';
|
||||
export { default as convertLab65ToXyz65 } from './lab65/convertLab65ToXyz65.js';
|
||||
export { default as convertLabToLch } from './lch/convertLabToLch.js';
|
||||
export { default as convertLabToRgb } from './lab/convertLabToRgb.js';
|
||||
export { default as convertLabToXyz50 } from './lab/convertLabToXyz50.js';
|
||||
export { default as convertLchToLab } from './lch/convertLchToLab.js';
|
||||
export { default as convertLchuvToLuv } from './lchuv/convertLchuvToLuv.js';
|
||||
export { default as convertLrgbToOklab } from './oklab/convertLrgbToOklab.js';
|
||||
export { default as convertLrgbToRgb } from './lrgb/convertLrgbToRgb.js';
|
||||
export { default as convertLuvToLchuv } from './lchuv/convertLuvToLchuv.js';
|
||||
export { default as convertLuvToXyz50 } from './luv/convertLuvToXyz50.js';
|
||||
export { default as convertOkhslToOklab } from './okhsl/convertOkhslToOklab.js';
|
||||
export { default as convertOkhsvToOklab } from './okhsv/convertOkhsvToOklab.js';
|
||||
export { default as convertOklabToLrgb } from './oklab/convertOklabToLrgb.js';
|
||||
export { default as convertOklabToOkhsl } from './okhsl/convertOklabToOkhsl.js';
|
||||
export { default as convertOklabToOkhsv } from './okhsv/convertOklabToOkhsv.js';
|
||||
export { default as convertOklabToRgb } from './oklab/convertOklabToRgb.js';
|
||||
export { default as convertP3ToXyz65 } from './p3/convertP3ToXyz65.js';
|
||||
export { default as convertProphotoToXyz50 } from './prophoto/convertProphotoToXyz50.js';
|
||||
export { default as convertRec2020ToXyz65 } from './rec2020/convertRec2020ToXyz65.js';
|
||||
export { default as convertRgbToCubehelix } from './cubehelix/convertRgbToCubehelix.js';
|
||||
export { default as convertRgbToHsi } from './hsi/convertRgbToHsi.js';
|
||||
export { default as convertRgbToHsl } from './hsl/convertRgbToHsl.js';
|
||||
export { default as convertRgbToHsv } from './hsv/convertRgbToHsv.js';
|
||||
export { default as convertRgbToHwb } from './hwb/convertRgbToHwb.js';
|
||||
export { default as convertRgbToJab } from './jab/convertRgbToJab.js';
|
||||
export { default as convertRgbToLab } from './lab/convertRgbToLab.js';
|
||||
export { default as convertRgbToLab65 } from './lab65/convertRgbToLab65.js';
|
||||
export { default as convertRgbToLrgb } from './lrgb/convertRgbToLrgb.js';
|
||||
export { default as convertRgbToOklab } from './oklab/convertRgbToOklab.js';
|
||||
export { default as convertRgbToXyb } from './xyb/convertRgbToXyb.js';
|
||||
export { default as convertRgbToXyz50 } from './xyz50/convertRgbToXyz50.js';
|
||||
export { default as convertRgbToXyz65 } from './xyz65/convertRgbToXyz65.js';
|
||||
export { default as convertRgbToYiq } from './yiq/convertRgbToYiq.js';
|
||||
export { default as convertXybToRgb } from './xyb/convertXybToRgb.js';
|
||||
export { default as convertXyz50ToLab } from './lab/convertXyz50ToLab.js';
|
||||
export { default as convertXyz50ToLuv } from './luv/convertXyz50ToLuv.js';
|
||||
export { default as convertXyz50ToProphoto } from './prophoto/convertXyz50ToProphoto.js';
|
||||
export { default as convertXyz50ToRgb } from './xyz50/convertXyz50ToRgb.js';
|
||||
export { default as convertXyz50ToXyz65 } from './xyz65/convertXyz50ToXyz65.js';
|
||||
export { default as convertXyz65ToA98 } from './a98/convertXyz65ToA98.js';
|
||||
export { default as convertXyz65ToJab } from './jab/convertXyz65ToJab.js';
|
||||
export { default as convertXyz65ToLab65 } from './lab65/convertXyz65ToLab65.js';
|
||||
export { default as convertXyz65ToP3 } from './p3/convertXyz65ToP3.js';
|
||||
export { default as convertXyz65ToRec2020 } from './rec2020/convertXyz65ToRec2020.js';
|
||||
export { default as convertXyz65ToRgb } from './xyz65/convertXyz65ToRgb.js';
|
||||
export { default as convertXyz65ToXyz50 } from './xyz65/convertXyz65ToXyz50.js';
|
||||
export { default as convertYiqToRgb } from './yiq/convertYiqToRgb.js';
|
||||
|
||||
export {
|
||||
modeA98,
|
||||
modeCubehelix,
|
||||
modeDlab,
|
||||
modeDlch,
|
||||
modeHsi,
|
||||
modeHsl,
|
||||
modeHsv,
|
||||
modeHwb,
|
||||
modeJab,
|
||||
modeJch,
|
||||
modeLab,
|
||||
modeLab65,
|
||||
modeLch,
|
||||
modeLch65,
|
||||
modeLchuv,
|
||||
modeLrgb,
|
||||
modeLuv,
|
||||
modeOkhsl,
|
||||
modeOkhsv,
|
||||
modeOklab,
|
||||
modeOklch,
|
||||
modeP3,
|
||||
modeProphoto,
|
||||
modeRec2020,
|
||||
modeRgb,
|
||||
modeXyb,
|
||||
modeXyz50,
|
||||
modeXyz65,
|
||||
modeYiq
|
||||
};
|
||||
|
||||
export const a98 = useMode(modeA98);
|
||||
export const cubehelix = useMode(modeCubehelix);
|
||||
export const dlab = useMode(modeDlab);
|
||||
export const dlch = useMode(modeDlch);
|
||||
export const hsi = useMode(modeHsi);
|
||||
export const hsl = useMode(modeHsl);
|
||||
export const hsv = useMode(modeHsv);
|
||||
export const hwb = useMode(modeHwb);
|
||||
export const jab = useMode(modeJab);
|
||||
export const jch = useMode(modeJch);
|
||||
export const lab = useMode(modeLab);
|
||||
export const lab65 = useMode(modeLab65);
|
||||
export const lch = useMode(modeLch);
|
||||
export const lch65 = useMode(modeLch65);
|
||||
export const lchuv = useMode(modeLchuv);
|
||||
export const lrgb = useMode(modeLrgb);
|
||||
export const luv = useMode(modeLuv);
|
||||
export const okhsl = useMode(modeOkhsl);
|
||||
export const okhsv = useMode(modeOkhsv);
|
||||
export const oklab = useMode(modeOklab);
|
||||
export const oklch = useMode(modeOklch);
|
||||
export const p3 = useMode(modeP3);
|
||||
export const prophoto = useMode(modeProphoto);
|
||||
export const rec2020 = useMode(modeRec2020);
|
||||
export const rgb = useMode(modeRgb);
|
||||
export const xyb = useMode(modeXyb);
|
||||
export const xyz50 = useMode(modeXyz50);
|
||||
export const xyz65 = useMode(modeXyz65);
|
||||
export const yiq = useMode(modeYiq);
|
155
node_modules/culori/src/interpolate/interpolate.js
generated
vendored
Normal file
155
node_modules/culori/src/interpolate/interpolate.js
generated
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
import converter from '../converter.js';
|
||||
import { getMode } from '../modes.js';
|
||||
import normalizePositions from '../util/normalizePositions.js';
|
||||
import easingMidpoint from '../easing/midpoint.js';
|
||||
import { mapper, mapAlphaMultiply, mapAlphaDivide } from '../map.js';
|
||||
|
||||
const isfn = o => typeof o === 'function';
|
||||
const isobj = o => o && typeof o === 'object';
|
||||
const isnum = o => typeof o === 'number';
|
||||
|
||||
const interpolate_fn = (colors, mode = 'rgb', overrides, premap) => {
|
||||
let def = getMode(mode);
|
||||
let conv = converter(mode);
|
||||
|
||||
let conv_colors = [];
|
||||
let positions = [];
|
||||
let fns = {};
|
||||
|
||||
colors.forEach(val => {
|
||||
if (Array.isArray(val)) {
|
||||
conv_colors.push(conv(val[0]));
|
||||
positions.push(val[1]);
|
||||
} else if (isnum(val) || isfn(val)) {
|
||||
// Color interpolation hint or easing function
|
||||
fns[positions.length] = val;
|
||||
} else {
|
||||
conv_colors.push(conv(val));
|
||||
positions.push(undefined);
|
||||
}
|
||||
});
|
||||
|
||||
normalizePositions(positions);
|
||||
|
||||
// override the default interpolators
|
||||
// from the color space definition with any custom ones
|
||||
let fixed = def.channels.reduce((res, ch) => {
|
||||
let ffn;
|
||||
if (isobj(overrides) && isobj(overrides[ch]) && overrides[ch].fixup) {
|
||||
ffn = overrides[ch].fixup;
|
||||
} else if (isobj(def.interpolate[ch]) && def.interpolate[ch].fixup) {
|
||||
ffn = def.interpolate[ch].fixup;
|
||||
} else {
|
||||
ffn = v => v;
|
||||
}
|
||||
res[ch] = ffn(conv_colors.map(color => color[ch]));
|
||||
return res;
|
||||
}, {});
|
||||
|
||||
if (premap) {
|
||||
let ccolors = conv_colors.map((color, idx) => {
|
||||
return def.channels.reduce(
|
||||
(c, ch) => {
|
||||
c[ch] = fixed[ch][idx];
|
||||
return c;
|
||||
},
|
||||
{ mode }
|
||||
);
|
||||
});
|
||||
fixed = def.channels.reduce((res, ch) => {
|
||||
res[ch] = ccolors.map(c => {
|
||||
let v = premap(c[ch], ch, c, mode);
|
||||
return isNaN(v) ? undefined : v;
|
||||
});
|
||||
return res;
|
||||
}, {});
|
||||
}
|
||||
|
||||
let interpolators = def.channels.reduce((res, ch) => {
|
||||
let ifn;
|
||||
if (isfn(overrides)) {
|
||||
ifn = overrides;
|
||||
} else if (isobj(overrides) && isfn(overrides[ch])) {
|
||||
ifn = overrides[ch];
|
||||
} else if (
|
||||
isobj(overrides) &&
|
||||
isobj(overrides[ch]) &&
|
||||
overrides[ch].use
|
||||
) {
|
||||
ifn = overrides[ch].use;
|
||||
} else if (isfn(def.interpolate[ch])) {
|
||||
ifn = def.interpolate[ch];
|
||||
} else if (isobj(def.interpolate[ch])) {
|
||||
ifn = def.interpolate[ch].use;
|
||||
}
|
||||
|
||||
res[ch] = ifn(fixed[ch]);
|
||||
return res;
|
||||
}, {});
|
||||
|
||||
let n = conv_colors.length - 1;
|
||||
|
||||
return t => {
|
||||
// clamp t to the [0, 1] interval
|
||||
t = Math.min(Math.max(0, t), 1);
|
||||
|
||||
if (t <= positions[0]) {
|
||||
return conv_colors[0];
|
||||
}
|
||||
|
||||
if (t > positions[n]) {
|
||||
return conv_colors[n];
|
||||
}
|
||||
|
||||
// Convert `t` from [0, 1] to `t0` between the appropriate two colors.
|
||||
// First, look for the two colors between which `t` is located.
|
||||
// Note: this can be optimized by searching for the index
|
||||
// through bisection instead of start-to-end.
|
||||
let idx = 0;
|
||||
while (positions[idx] < t) idx++;
|
||||
let start = positions[idx - 1];
|
||||
let delta = positions[idx] - start;
|
||||
|
||||
let P = (t - start) / delta;
|
||||
|
||||
// use either the local easing, or the global easing, if any
|
||||
let fn = fns[idx] || fns[0];
|
||||
if (fn !== undefined) {
|
||||
if (isnum(fn)) {
|
||||
fn = easingMidpoint((fn - start) / delta);
|
||||
}
|
||||
P = fn(P);
|
||||
}
|
||||
|
||||
let t0 = (idx - 1 + P) / n;
|
||||
|
||||
return def.channels.reduce(
|
||||
(res, channel) => {
|
||||
let val = interpolators[channel](t0);
|
||||
if (val !== undefined) {
|
||||
res[channel] = val;
|
||||
}
|
||||
return res;
|
||||
},
|
||||
{ mode }
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
const interpolate = (colors, mode = 'rgb', overrides) =>
|
||||
interpolate_fn(colors, mode, overrides);
|
||||
|
||||
const interpolateWith =
|
||||
(premap, postmap) =>
|
||||
(colors, mode = 'rgb', overrides) => {
|
||||
let post = postmap ? mapper(postmap, mode) : undefined;
|
||||
let it = interpolate_fn(colors, mode, overrides, premap);
|
||||
return post ? t => post(it(t)) : it;
|
||||
};
|
||||
|
||||
const interpolateWithPremultipliedAlpha = interpolateWith(
|
||||
mapAlphaMultiply,
|
||||
mapAlphaDivide
|
||||
);
|
||||
|
||||
export { interpolate, interpolateWith, interpolateWithPremultipliedAlpha };
|
28
node_modules/culori/src/interpolate/lerp.js
generated
vendored
Normal file
28
node_modules/culori/src/interpolate/lerp.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
const lerp = (a, b, t) => a + t * (b - a);
|
||||
const unlerp = (a, b, v) => (v - a) / (b - a);
|
||||
|
||||
const blerp = (a00, a01, a10, a11, tx, ty) => {
|
||||
return lerp(lerp(a00, a01, tx), lerp(a10, a11, tx), ty);
|
||||
};
|
||||
|
||||
const trilerp = (
|
||||
a000,
|
||||
a010,
|
||||
a100,
|
||||
a110,
|
||||
a001,
|
||||
a011,
|
||||
a101,
|
||||
a111,
|
||||
tx,
|
||||
ty,
|
||||
tz
|
||||
) => {
|
||||
return lerp(
|
||||
blerp(a000, a010, a100, a110, tx, ty),
|
||||
blerp(a001, a011, a101, a111, tx, ty),
|
||||
tz
|
||||
);
|
||||
};
|
||||
|
||||
export { lerp, blerp, trilerp, unlerp };
|
4
node_modules/culori/src/interpolate/linear.js
generated
vendored
Normal file
4
node_modules/culori/src/interpolate/linear.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import { lerp } from './lerp.js';
|
||||
import { interpolatorPiecewise } from './piecewise.js';
|
||||
|
||||
export const interpolatorLinear = interpolatorPiecewise(lerp);
|
29
node_modules/culori/src/interpolate/piecewise.js
generated
vendored
Normal file
29
node_modules/culori/src/interpolate/piecewise.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
const get_classes = arr => {
|
||||
let classes = [];
|
||||
for (let i = 0; i < arr.length - 1; i++) {
|
||||
let a = arr[i];
|
||||
let b = arr[i + 1];
|
||||
if (a === undefined && b === undefined) {
|
||||
classes.push(undefined);
|
||||
} else if (a !== undefined && b !== undefined) {
|
||||
classes.push([a, b]);
|
||||
} else {
|
||||
classes.push(a !== undefined ? [a, a] : [b, b]);
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
};
|
||||
|
||||
const interpolatorPiecewise = interpolator => arr => {
|
||||
let classes = get_classes(arr);
|
||||
return t => {
|
||||
let cls = t * classes.length;
|
||||
let idx = t >= 1 ? classes.length - 1 : Math.max(Math.floor(cls), 0);
|
||||
let pair = classes[idx];
|
||||
return pair === undefined
|
||||
? undefined
|
||||
: interpolator(pair[0], pair[1], cls - idx);
|
||||
};
|
||||
};
|
||||
|
||||
export { interpolatorPiecewise };
|
58
node_modules/culori/src/interpolate/splineBasis.js
generated
vendored
Normal file
58
node_modules/culori/src/interpolate/splineBasis.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Basis spline
|
||||
------------
|
||||
|
||||
Given control points V0...Vn (our values)
|
||||
|
||||
S0 = V0
|
||||
...
|
||||
Si = 1/6 * Vi-1 + 2/3 * Vi + 1/6 * Vi+1
|
||||
...
|
||||
Sn = Vn
|
||||
|
||||
The Bézier curve has control points:
|
||||
|
||||
Bi = Si-1, 2/3 * Vi-1 + 1/3 * Vi, 1/3 * Vi-1 + 2/3 * Vi, Si
|
||||
|
||||
Which we can then factor into the Bezier's explicit form:
|
||||
|
||||
B(t) = (1-t)^3 * P0 + 3 * (1-t)^2 * t * P1 + (1-t) * t^2 * P2 + t^3 * P3
|
||||
|
||||
*/
|
||||
const mod = (v, l) => (v + l) % l;
|
||||
|
||||
const bspline = (Vim2, Vim1, Vi, Vip1, t) => {
|
||||
let t2 = t * t;
|
||||
let t3 = t2 * t;
|
||||
return (
|
||||
((1 - 3 * t + 3 * t2 - t3) * Vim2 +
|
||||
(4 - 6 * t2 + 3 * t3) * Vim1 +
|
||||
(1 + 3 * t + 3 * t2 - 3 * t3) * Vi +
|
||||
t3 * Vip1) /
|
||||
6
|
||||
);
|
||||
};
|
||||
|
||||
export const interpolatorSplineBasis = arr => t => {
|
||||
let classes = arr.length - 1;
|
||||
let i = t >= 1 ? classes - 1 : Math.max(0, Math.floor(t * classes));
|
||||
return bspline(
|
||||
i > 0 ? arr[i - 1] : 2 * arr[i] - arr[i + 1],
|
||||
arr[i],
|
||||
arr[i + 1],
|
||||
i < classes - 1 ? arr[i + 2] : 2 * arr[i + 1] - arr[i],
|
||||
(t - i / classes) * classes
|
||||
);
|
||||
};
|
||||
|
||||
export const interpolatorSplineBasisClosed = arr => t => {
|
||||
const classes = arr.length - 1;
|
||||
const i = Math.floor(t * classes);
|
||||
return bspline(
|
||||
arr[mod(i - 1, arr.length)],
|
||||
arr[mod(i, arr.length)],
|
||||
arr[mod(i + 1, arr.length)],
|
||||
arr[mod(i + 2, arr.length)],
|
||||
(t - i / classes) * classes
|
||||
);
|
||||
};
|
128
node_modules/culori/src/interpolate/splineMonotone.js
generated
vendored
Normal file
128
node_modules/culori/src/interpolate/splineMonotone.js
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
import { interpolatorLinear } from './linear.js';
|
||||
|
||||
/*
|
||||
Monotone spline
|
||||
---------------
|
||||
|
||||
Based on:
|
||||
|
||||
Steffen, M.
|
||||
"A simple method for monotonic interpolation in one dimension."
|
||||
in Astronomy and Astrophysics, Vol. 239, p. 443-450 (Nov. 1990),
|
||||
Provided by the SAO/NASA Astrophysics Data System.
|
||||
|
||||
https://ui.adsabs.harvard.edu/abs/1990A&A...239..443S
|
||||
|
||||
(Reference thanks to `d3/d3-shape`)
|
||||
*/
|
||||
|
||||
const sgn = Math.sign;
|
||||
const min = Math.min;
|
||||
const abs = Math.abs;
|
||||
|
||||
const mono = arr => {
|
||||
let n = arr.length - 1;
|
||||
let s = [];
|
||||
let p = [];
|
||||
let yp = [];
|
||||
for (let i = 0; i < n; i++) {
|
||||
s.push((arr[i + 1] - arr[i]) * n);
|
||||
p.push(i > 0 ? 0.5 * (arr[i + 1] - arr[i - 1]) * n : undefined);
|
||||
yp.push(
|
||||
i > 0
|
||||
? (sgn(s[i - 1]) + sgn(s[i])) *
|
||||
min(abs(s[i - 1]), abs(s[i]), 0.5 * abs(p[i]))
|
||||
: undefined
|
||||
);
|
||||
}
|
||||
return [s, p, yp];
|
||||
};
|
||||
|
||||
const interpolator = (arr, yp, s) => {
|
||||
let n = arr.length - 1;
|
||||
let n2 = n * n;
|
||||
return t => {
|
||||
let i;
|
||||
if (t >= 1) {
|
||||
i = n - 1;
|
||||
} else {
|
||||
i = Math.max(0, Math.floor(t * n));
|
||||
}
|
||||
let t1 = t - i / n;
|
||||
let t2 = t1 * t1;
|
||||
let t3 = t2 * t1;
|
||||
return (
|
||||
(yp[i] + yp[i + 1] - 2 * s[i]) * n2 * t3 +
|
||||
(3 * s[i] - 2 * yp[i] - yp[i + 1]) * n * t2 +
|
||||
yp[i] * t1 +
|
||||
arr[i]
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
A monotone spline which uses one-sided finite differences
|
||||
at the boundaries.
|
||||
*/
|
||||
export const interpolatorSplineMonotone = arr => {
|
||||
if (arr.length < 3) {
|
||||
return interpolatorLinear(arr);
|
||||
}
|
||||
let n = arr.length - 1;
|
||||
let [s, , yp] = mono(arr);
|
||||
yp[0] = s[0];
|
||||
yp[n] = s[n - 1];
|
||||
return interpolator(arr, yp, s);
|
||||
};
|
||||
|
||||
/*
|
||||
The clamped monotone spline derives the values of y'
|
||||
at the boundary points by tracing a parabola
|
||||
through the first/last three points.
|
||||
|
||||
For arrays of fewer than three values, we fall back to
|
||||
linear interpolation.
|
||||
*/
|
||||
|
||||
export const interpolatorSplineMonotone2 = arr => {
|
||||
if (arr.length < 3) {
|
||||
return interpolatorLinear(arr);
|
||||
}
|
||||
let n = arr.length - 1;
|
||||
let [s, p, yp] = mono(arr);
|
||||
p[0] = (arr[1] * 2 - arr[0] * 1.5 - arr[2] * 0.5) * n;
|
||||
p[n] = (arr[n] * 1.5 - arr[n - 1] * 2 + arr[n - 2] * 0.5) * n;
|
||||
yp[0] = p[0] * s[0] <= 0 ? 0 : abs(p[0]) > 2 * abs(s[0]) ? 2 * s[0] : p[0];
|
||||
yp[n] =
|
||||
p[n] * s[n - 1] <= 0
|
||||
? 0
|
||||
: abs(p[n]) > 2 * abs(s[n - 1])
|
||||
? 2 * s[n - 1]
|
||||
: p[n];
|
||||
return interpolator(arr, yp, s);
|
||||
};
|
||||
|
||||
/*
|
||||
The closed monotone spline considers
|
||||
the array to be periodic:
|
||||
|
||||
arr[-1] = arr[arr.length - 1]
|
||||
arr[arr.length] = arr[0]
|
||||
|
||||
...and so on.
|
||||
*/
|
||||
export const interpolatorSplineMonotoneClosed = arr => {
|
||||
let n = arr.length - 1;
|
||||
let [s, p, yp] = mono(arr);
|
||||
// boundary conditions
|
||||
p[0] = 0.5 * (arr[1] - arr[n]) * n;
|
||||
p[n] = 0.5 * (arr[0] - arr[n - 1]) * n;
|
||||
let s_m1 = (arr[0] - arr[n]) * n;
|
||||
let s_n = s_m1;
|
||||
yp[0] =
|
||||
(sgn(s_m1) + sgn(s[0])) * min(abs(s_m1), abs(s[0]), 0.5 * abs(p[0]));
|
||||
yp[n] =
|
||||
(sgn(s[n - 1]) + sgn(s_n)) *
|
||||
min(abs(s[n - 1]), abs(s_n), 0.5 * abs(p[n]));
|
||||
return interpolator(arr, yp, s);
|
||||
};
|
37
node_modules/culori/src/interpolate/splineNatural.js
generated
vendored
Normal file
37
node_modules/culori/src/interpolate/splineNatural.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import {
|
||||
interpolatorSplineBasisClosed,
|
||||
interpolatorSplineBasis
|
||||
} from './splineBasis.js';
|
||||
|
||||
const solve = v => {
|
||||
let i;
|
||||
let n = v.length - 1;
|
||||
let c = new Array(n);
|
||||
let _v = new Array(n);
|
||||
let sol = new Array(n);
|
||||
|
||||
c[1] = 1 / 4;
|
||||
_v[1] = (6 * v[1] - v[0]) / 4;
|
||||
|
||||
for (i = 2; i < n; ++i) {
|
||||
c[i] = 1 / (4 - c[i - 1]);
|
||||
_v[i] = (6 * v[i] - (i == n - 1 ? v[n] : 0) - _v[i - 1]) * c[i];
|
||||
}
|
||||
|
||||
sol[0] = v[0];
|
||||
sol[n] = v[n];
|
||||
if (n - 1 > 0) {
|
||||
sol[n - 1] = _v[n - 1];
|
||||
}
|
||||
|
||||
for (i = n - 2; i > 0; --i) {
|
||||
sol[i] = _v[i] - c[i] * sol[i + 1];
|
||||
}
|
||||
|
||||
return sol;
|
||||
};
|
||||
|
||||
export const interpolatorSplineNatural = arr =>
|
||||
interpolatorSplineBasis(solve(arr));
|
||||
export const interpolatorSplineNaturalClosed = arr =>
|
||||
interpolatorSplineBasisClosed(solve(arr));
|
6
node_modules/culori/src/jab/convertJabToRgb.js
generated
vendored
Normal file
6
node_modules/culori/src/jab/convertJabToRgb.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';
|
||||
import convertJabToXyz65 from './convertJabToXyz65.js';
|
||||
|
||||
const convertJabToRgb = color => convertXyz65ToRgb(convertJabToXyz65(color));
|
||||
|
||||
export default convertJabToRgb;
|
45
node_modules/culori/src/jab/convertJabToXyz65.js
generated
vendored
Normal file
45
node_modules/culori/src/jab/convertJabToXyz65.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
const n = 0.1593017578125; // = 2610 / Math.pow(2, 14);
|
||||
const p = 134.03437499999998; // = 1.7 * 2523 / Math.pow(2, 5);
|
||||
const c1 = 0.8359375; // = 3424 / Math.pow(2, 12);
|
||||
const c2 = 18.8515625; // = 2413 / Math.pow(2, 7);
|
||||
const c3 = 18.6875; // = 2392 / Math.pow(2, 7);
|
||||
const d0 = 1.6295499532821566e-11;
|
||||
|
||||
/* `v` may be negative, in which case return 0 instead of NaN */
|
||||
const pq_inv = v => {
|
||||
let vp = Math.pow(v, 1 / p);
|
||||
return 10000 * Math.pow((c1 - vp) / (c3 * vp - c2), 1 / n) || 0;
|
||||
};
|
||||
|
||||
const rel = v => v / 203;
|
||||
|
||||
const convertJabToXyz65 = ({ j, a, b, alpha }) => {
|
||||
let i = (j + d0) / (0.44 + 0.56 * (j + d0));
|
||||
|
||||
let l = pq_inv(i + 0.13860504 * a + 0.058047316 * b);
|
||||
let m = pq_inv(i - 0.13860504 * a - 0.058047316 * b);
|
||||
let s = pq_inv(i - 0.096019242 * a - 0.8118919 * b);
|
||||
|
||||
let res = {
|
||||
mode: 'xyz65',
|
||||
x: rel(
|
||||
1.661373024652174 * l -
|
||||
0.914523081304348 * m +
|
||||
0.23136208173913045 * s
|
||||
),
|
||||
y: rel(
|
||||
-0.3250758611844533 * l +
|
||||
1.571847026732543 * m -
|
||||
0.21825383453227928 * s
|
||||
),
|
||||
z: rel(-0.090982811 * l - 0.31272829 * m + 1.5227666 * s)
|
||||
};
|
||||
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertJabToXyz65;
|
19
node_modules/culori/src/jab/convertRgbToJab.js
generated
vendored
Normal file
19
node_modules/culori/src/jab/convertRgbToJab.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Convert sRGB to JzAzBz.
|
||||
|
||||
For achromatic sRGB colors, adjust the equivalent JzAzBz color
|
||||
to be achromatic as well, insteading of having a very slight chroma.
|
||||
*/
|
||||
|
||||
import convertXyz65ToJab from './convertXyz65ToJab.js';
|
||||
import convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';
|
||||
|
||||
const convertRgbToJab = rgb => {
|
||||
let res = convertXyz65ToJab(convertRgbToXyz65(rgb));
|
||||
if (rgb.r === rgb.b && rgb.b === rgb.g) {
|
||||
res.a = res.b = 0;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertRgbToJab;
|
45
node_modules/culori/src/jab/convertXyz65ToJab.js
generated
vendored
Normal file
45
node_modules/culori/src/jab/convertXyz65ToJab.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
const n = 0.1593017578125; // = 2610 / Math.pow(2, 14);
|
||||
const p = 134.03437499999998; // = 1.7 * 2523 / Math.pow(2, 5);
|
||||
const c1 = 0.8359375; // = 3424 / Math.pow(2, 12);
|
||||
const c2 = 18.8515625; // = 2413 / Math.pow(2, 7);
|
||||
const c3 = 18.6875; // = 2392 / Math.pow(2, 7);
|
||||
const d0 = 1.6295499532821566e-11;
|
||||
|
||||
/* `v` may be negative, in which case return 0 instead of NaN */
|
||||
const pq = v => {
|
||||
let vn = Math.pow(v / 10000, n);
|
||||
return Math.pow((c1 + c2 * vn) / (1 + c3 * vn), p) || 0;
|
||||
};
|
||||
|
||||
// Convert to Absolute XYZ
|
||||
const abs = v => Math.max(v * 203, 0);
|
||||
|
||||
const convertXyz65ToJab = ({ x, y, z, alpha }) => {
|
||||
x = abs(x);
|
||||
y = abs(y);
|
||||
z = abs(z);
|
||||
|
||||
let xp = 1.15 * x - 0.15 * z;
|
||||
let yp = 0.66 * y + 0.34 * x;
|
||||
|
||||
let l = pq(0.41478972 * xp + 0.579999 * yp + 0.014648 * z);
|
||||
let m = pq(-0.20151 * xp + 1.120649 * yp + 0.0531008 * z);
|
||||
let s = pq(-0.0166008 * xp + 0.2648 * yp + 0.6684799 * z);
|
||||
|
||||
let i = (l + m) / 2;
|
||||
|
||||
let res = {
|
||||
mode: 'jab',
|
||||
j: (0.44 * i) / (1 - 0.56 * i) - d0,
|
||||
a: 3.524 * l - 4.066708 * m + 0.542708 * s,
|
||||
b: 0.199076 * l + 1.096799 * m - 1.295875 * s
|
||||
};
|
||||
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertXyz65ToJab;
|
53
node_modules/culori/src/jab/definition.js
generated
vendored
Normal file
53
node_modules/culori/src/jab/definition.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
The JzAzBz color space.
|
||||
|
||||
Based on:
|
||||
|
||||
Muhammad Safdar, Guihua Cui, Youn Jin Kim, and Ming Ronnier Luo,
|
||||
"Perceptually uniform color space for image signals
|
||||
including high dynamic range and wide gamut,"
|
||||
Opt. Express 25, 15131-15151 (2017)
|
||||
|
||||
https://doi.org/10.1364/OE.25.015131
|
||||
*/
|
||||
|
||||
import convertXyz65ToJab from './convertXyz65ToJab.js';
|
||||
import convertJabToXyz65 from './convertJabToXyz65.js';
|
||||
import convertRgbToJab from './convertRgbToJab.js';
|
||||
import convertJabToRgb from './convertJabToRgb.js';
|
||||
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'jab',
|
||||
channels: ['j', 'a', 'b', 'alpha'],
|
||||
|
||||
parse: ['--jzazbz'],
|
||||
serialize: '--jzazbz',
|
||||
|
||||
fromMode: {
|
||||
rgb: convertRgbToJab,
|
||||
xyz65: convertXyz65ToJab
|
||||
},
|
||||
|
||||
toMode: {
|
||||
rgb: convertJabToRgb,
|
||||
xyz65: convertJabToXyz65
|
||||
},
|
||||
|
||||
ranges: {
|
||||
j: [0, 0.222],
|
||||
a: [-0.109, 0.129],
|
||||
b: [-0.185, 0.134]
|
||||
},
|
||||
|
||||
interpolate: {
|
||||
j: interpolatorLinear,
|
||||
a: interpolatorLinear,
|
||||
b: interpolatorLinear,
|
||||
alpha: { use: interpolatorLinear, fixup: fixupAlpha }
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
19
node_modules/culori/src/jch/convertJabToJch.js
generated
vendored
Normal file
19
node_modules/culori/src/jch/convertJabToJch.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import normalizeHue from '../util/normalizeHue.js';
|
||||
|
||||
const convertJabToJch = ({ j, a, b, alpha }) => {
|
||||
let c = Math.sqrt(a * a + b * b);
|
||||
let res = {
|
||||
mode: 'jch',
|
||||
j,
|
||||
c
|
||||
};
|
||||
if (c) {
|
||||
res.h = normalizeHue((Math.atan2(b, a) * 180) / Math.PI);
|
||||
}
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertJabToJch;
|
12
node_modules/culori/src/jch/convertJchToJab.js
generated
vendored
Normal file
12
node_modules/culori/src/jch/convertJchToJab.js
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
const convertJchToJab = ({ j, c, h, alpha }) => {
|
||||
let res = {
|
||||
mode: 'jab',
|
||||
j,
|
||||
a: c ? c * Math.cos((h / 180) * Math.PI) : 0,
|
||||
b: c ? c * Math.sin((h / 180) * Math.PI) : 0
|
||||
};
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertJchToJab;
|
52
node_modules/culori/src/jch/definition.js
generated
vendored
Normal file
52
node_modules/culori/src/jch/definition.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
import convertJabToJch from './convertJabToJch.js';
|
||||
import convertJchToJab from './convertJchToJab.js';
|
||||
import convertJabToRgb from '../jab/convertJabToRgb.js';
|
||||
import convertRgbToJab from '../jab/convertRgbToJab.js';
|
||||
|
||||
import { fixupHueShorter } from '../fixup/hue.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { differenceHueChroma } from '../difference.js';
|
||||
import { averageAngle } from '../average.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'jch',
|
||||
|
||||
parse: ['--jzczhz'],
|
||||
serialize: '--jzczhz',
|
||||
|
||||
toMode: {
|
||||
jab: convertJchToJab,
|
||||
rgb: c => convertJabToRgb(convertJchToJab(c))
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
rgb: c => convertJabToJch(convertRgbToJab(c)),
|
||||
jab: convertJabToJch
|
||||
},
|
||||
|
||||
channels: ['j', 'c', 'h', 'alpha'],
|
||||
|
||||
ranges: {
|
||||
j: [0, 0.221],
|
||||
c: [0, 0.19],
|
||||
h: [0, 360]
|
||||
},
|
||||
|
||||
interpolate: {
|
||||
h: { use: interpolatorLinear, fixup: fixupHueShorter },
|
||||
c: interpolatorLinear,
|
||||
j: interpolatorLinear,
|
||||
alpha: { use: interpolatorLinear, fixup: fixupAlpha }
|
||||
},
|
||||
|
||||
difference: {
|
||||
h: differenceHueChroma
|
||||
},
|
||||
|
||||
average: {
|
||||
h: averageAngle
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
6
node_modules/culori/src/lab/convertLabToRgb.js
generated
vendored
Normal file
6
node_modules/culori/src/lab/convertLabToRgb.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import convertLabToXyz50 from './convertLabToXyz50.js';
|
||||
import convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';
|
||||
|
||||
const convertLabToRgb = lab => convertXyz50ToRgb(convertLabToXyz50(lab));
|
||||
|
||||
export default convertLabToRgb;
|
25
node_modules/culori/src/lab/convertLabToXyz50.js
generated
vendored
Normal file
25
node_modules/culori/src/lab/convertLabToXyz50.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import { k, e } from '../xyz50/constants.js';
|
||||
import { D50 } from '../constants.js';
|
||||
|
||||
let fn = v => (Math.pow(v, 3) > e ? Math.pow(v, 3) : (116 * v - 16) / k);
|
||||
|
||||
const convertLabToXyz50 = ({ l, a, b, alpha }) => {
|
||||
let fy = (l + 16) / 116;
|
||||
let fx = a / 500 + fy;
|
||||
let fz = fy - b / 200;
|
||||
|
||||
let res = {
|
||||
mode: 'xyz50',
|
||||
x: fn(fx) * D50.X,
|
||||
y: fn(fy) * D50.Y,
|
||||
z: fn(fz) * D50.Z
|
||||
};
|
||||
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertLabToXyz50;
|
16
node_modules/culori/src/lab/convertRgbToLab.js
generated
vendored
Normal file
16
node_modules/culori/src/lab/convertRgbToLab.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';
|
||||
import convertXyz50ToLab from './convertXyz50ToLab.js';
|
||||
|
||||
const convertRgbToLab = rgb => {
|
||||
let res = convertXyz50ToLab(convertRgbToXyz50(rgb));
|
||||
|
||||
// Fixes achromatic RGB colors having a _slight_ chroma due to floating-point errors
|
||||
// and approximated computations in sRGB <-> CIELab.
|
||||
// See: https://github.com/d3/d3-color/pull/46
|
||||
if (rgb.r === rgb.b && rgb.b === rgb.g) {
|
||||
res.a = res.b = 0;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertRgbToLab;
|
25
node_modules/culori/src/lab/convertXyz50ToLab.js
generated
vendored
Normal file
25
node_modules/culori/src/lab/convertXyz50ToLab.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import { k, e } from '../xyz50/constants.js';
|
||||
import { D50 } from '../constants.js';
|
||||
|
||||
const f = value => (value > e ? Math.cbrt(value) : (k * value + 16) / 116);
|
||||
|
||||
const convertXyz50ToLab = ({ x, y, z, alpha }) => {
|
||||
let f0 = f(x / D50.X);
|
||||
let f1 = f(y / D50.Y);
|
||||
let f2 = f(z / D50.Z);
|
||||
|
||||
let res = {
|
||||
mode: 'lab',
|
||||
l: 116 * f1 - 16,
|
||||
a: 500 * (f0 - f1),
|
||||
b: 200 * (f1 - f2)
|
||||
};
|
||||
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertXyz50ToLab;
|
46
node_modules/culori/src/lab/definition.js
generated
vendored
Normal file
46
node_modules/culori/src/lab/definition.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import convertLabToRgb from './convertLabToRgb.js';
|
||||
import convertLabToXyz50 from './convertLabToXyz50.js';
|
||||
import convertRgbToLab from './convertRgbToLab.js';
|
||||
import convertXyz50ToLab from './convertXyz50ToLab.js';
|
||||
import parseLab from './parseLab.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'lab',
|
||||
|
||||
toMode: {
|
||||
xyz50: convertLabToXyz50,
|
||||
rgb: convertLabToRgb
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
xyz50: convertXyz50ToLab,
|
||||
rgb: convertRgbToLab
|
||||
},
|
||||
|
||||
channels: ['l', 'a', 'b', 'alpha'],
|
||||
|
||||
ranges: {
|
||||
l: [0, 100],
|
||||
a: [-100, 100],
|
||||
b: [-100, 100]
|
||||
},
|
||||
|
||||
parse: [parseLab],
|
||||
serialize: c =>
|
||||
`lab(${c.l !== undefined ? c.l : 'none'} ${
|
||||
c.a !== undefined ? c.a : 'none'
|
||||
} ${c.b !== undefined ? c.b : 'none'}${
|
||||
c.alpha < 1 ? ` / ${c.alpha}` : ''
|
||||
})`,
|
||||
|
||||
interpolate: {
|
||||
l: interpolatorLinear,
|
||||
a: interpolatorLinear,
|
||||
b: interpolatorLinear,
|
||||
alpha: { use: interpolatorLinear, fixup: fixupAlpha }
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
28
node_modules/culori/src/lab/parseLab.js
generated
vendored
Normal file
28
node_modules/culori/src/lab/parseLab.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Tok } from '../parse.js';
|
||||
|
||||
function parseLab(color, parsed) {
|
||||
if (!parsed || parsed[0] !== 'lab') {
|
||||
return undefined;
|
||||
}
|
||||
const res = { mode: 'lab' };
|
||||
const [, l, a, b, alpha] = parsed;
|
||||
if (l.type === Tok.Hue || a.type === Tok.Hue || b.type === Tok.Hue) {
|
||||
return undefined;
|
||||
}
|
||||
if (l.type !== Tok.None) {
|
||||
res.l = l.value;
|
||||
}
|
||||
if (a.type !== Tok.None) {
|
||||
res.a = a.type === Tok.Number ? a.value : (a.value * 125) / 100;
|
||||
}
|
||||
if (b.type !== Tok.None) {
|
||||
res.b = b.type === Tok.Number ? b.value : (b.value * 125) / 100;
|
||||
}
|
||||
if (alpha.type !== Tok.None) {
|
||||
res.alpha = alpha.type === Tok.Number ? alpha.value : alpha.value / 100;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
export default parseLab;
|
6
node_modules/culori/src/lab65/convertLab65ToRgb.js
generated
vendored
Normal file
6
node_modules/culori/src/lab65/convertLab65ToRgb.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
import convertLab65ToXyz65 from './convertLab65ToXyz65.js';
|
||||
import convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';
|
||||
|
||||
const convertLab65ToRgb = lab => convertXyz65ToRgb(convertLab65ToXyz65(lab));
|
||||
|
||||
export default convertLab65ToRgb;
|
25
node_modules/culori/src/lab65/convertLab65ToXyz65.js
generated
vendored
Normal file
25
node_modules/culori/src/lab65/convertLab65ToXyz65.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import { k, e } from '../xyz65/constants.js';
|
||||
import { D65 } from '../constants.js';
|
||||
|
||||
let fn = v => (Math.pow(v, 3) > e ? Math.pow(v, 3) : (116 * v - 16) / k);
|
||||
|
||||
const convertLab65ToXyz65 = ({ l, a, b, alpha }) => {
|
||||
let fy = (l + 16) / 116;
|
||||
let fx = a / 500 + fy;
|
||||
let fz = fy - b / 200;
|
||||
|
||||
let res = {
|
||||
mode: 'xyz65',
|
||||
x: fn(fx) * D65.X,
|
||||
y: fn(fy) * D65.Y,
|
||||
z: fn(fz) * D65.Z
|
||||
};
|
||||
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertLab65ToXyz65;
|
16
node_modules/culori/src/lab65/convertRgbToLab65.js
generated
vendored
Normal file
16
node_modules/culori/src/lab65/convertRgbToLab65.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';
|
||||
import convertXyz65ToLab65 from './convertXyz65ToLab65.js';
|
||||
|
||||
const convertRgbToLab65 = rgb => {
|
||||
let res = convertXyz65ToLab65(convertRgbToXyz65(rgb));
|
||||
|
||||
// Fixes achromatic RGB colors having a _slight_ chroma due to floating-point errors
|
||||
// and approximated computations in sRGB <-> CIELab.
|
||||
// See: https://github.com/d3/d3-color/pull/46
|
||||
if (rgb.r === rgb.b && rgb.b === rgb.g) {
|
||||
res.a = res.b = 0;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertRgbToLab65;
|
25
node_modules/culori/src/lab65/convertXyz65ToLab65.js
generated
vendored
Normal file
25
node_modules/culori/src/lab65/convertXyz65ToLab65.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import { k, e } from '../xyz65/constants.js';
|
||||
import { D65 } from '../constants.js';
|
||||
|
||||
const f = value => (value > e ? Math.cbrt(value) : (k * value + 16) / 116);
|
||||
|
||||
const convertXyz65ToLab65 = ({ x, y, z, alpha }) => {
|
||||
let f0 = f(x / D65.X);
|
||||
let f1 = f(y / D65.Y);
|
||||
let f2 = f(z / D65.Z);
|
||||
|
||||
let res = {
|
||||
mode: 'lab65',
|
||||
l: 116 * f1 - 16,
|
||||
a: 500 * (f0 - f1),
|
||||
b: 200 * (f1 - f2)
|
||||
};
|
||||
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertXyz65ToLab65;
|
31
node_modules/culori/src/lab65/definition.js
generated
vendored
Normal file
31
node_modules/culori/src/lab65/definition.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import convertLab65ToRgb from './convertLab65ToRgb.js';
|
||||
import convertLab65ToXyz65 from './convertLab65ToXyz65.js';
|
||||
import convertRgbToLab65 from './convertRgbToLab65.js';
|
||||
import convertXyz65ToLab65 from './convertXyz65ToLab65.js';
|
||||
import lab from '../lab/definition.js';
|
||||
|
||||
const definition = {
|
||||
...lab,
|
||||
mode: 'lab65',
|
||||
|
||||
parse: ['--lab-d65'],
|
||||
serialize: '--lab-d65',
|
||||
|
||||
toMode: {
|
||||
xyz65: convertLab65ToXyz65,
|
||||
rgb: convertLab65ToRgb
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
xyz65: convertXyz65ToLab65,
|
||||
rgb: convertRgbToLab65
|
||||
},
|
||||
|
||||
ranges: {
|
||||
l: [0, 100],
|
||||
a: [-86.182, 98.234],
|
||||
b: [-107.86, 94.477]
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
16
node_modules/culori/src/lch/convertLabToLch.js
generated
vendored
Normal file
16
node_modules/culori/src/lch/convertLabToLch.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import normalizeHue from '../util/normalizeHue.js';
|
||||
|
||||
/*
|
||||
References:
|
||||
* https://drafts.csswg.org/css-color/#lab-to-lch
|
||||
* https://drafts.csswg.org/css-color/#color-conversion-code
|
||||
*/
|
||||
const convertLabToLch = ({ l, a, b, alpha }, mode = 'lch') => {
|
||||
let c = Math.sqrt(a * a + b * b);
|
||||
let res = { mode, l, c };
|
||||
if (c) res.h = normalizeHue((Math.atan2(b, a) * 180) / Math.PI);
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertLabToLch;
|
17
node_modules/culori/src/lch/convertLchToLab.js
generated
vendored
Normal file
17
node_modules/culori/src/lch/convertLchToLab.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
References:
|
||||
* https://drafts.csswg.org/css-color/#lch-to-lab
|
||||
* https://drafts.csswg.org/css-color/#color-conversion-code
|
||||
*/
|
||||
const convertLchToLab = ({ l, c, h, alpha }, mode = 'lab') => {
|
||||
let res = {
|
||||
mode,
|
||||
l,
|
||||
a: c ? c * Math.cos((h / 180) * Math.PI) : 0,
|
||||
b: c ? c * Math.sin((h / 180) * Math.PI) : 0
|
||||
};
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertLchToLab;
|
55
node_modules/culori/src/lch/definition.js
generated
vendored
Normal file
55
node_modules/culori/src/lch/definition.js
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import convertLabToLch from './convertLabToLch.js';
|
||||
import convertLchToLab from './convertLchToLab.js';
|
||||
import convertLabToRgb from '../lab/convertLabToRgb.js';
|
||||
import convertRgbToLab from '../lab/convertRgbToLab.js';
|
||||
import parseLch from './parseLch.js';
|
||||
import { fixupHueShorter } from '../fixup/hue.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { differenceHueChroma } from '../difference.js';
|
||||
import { averageAngle } from '../average.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'lch',
|
||||
|
||||
toMode: {
|
||||
lab: convertLchToLab,
|
||||
rgb: c => convertLabToRgb(convertLchToLab(c))
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
rgb: c => convertLabToLch(convertRgbToLab(c)),
|
||||
lab: convertLabToLch
|
||||
},
|
||||
|
||||
channels: ['l', 'c', 'h', 'alpha'],
|
||||
|
||||
ranges: {
|
||||
l: [0, 100],
|
||||
c: [0, 150],
|
||||
h: [0, 360]
|
||||
},
|
||||
|
||||
parse: [parseLch],
|
||||
serialize: c =>
|
||||
`lch(${c.l !== undefined ? c.l : 'none'} ${
|
||||
c.c !== undefined ? c.c : 'none'
|
||||
} ${c.h || 0}${c.alpha < 1 ? ` / ${c.alpha}` : ''})`,
|
||||
|
||||
interpolate: {
|
||||
h: { use: interpolatorLinear, fixup: fixupHueShorter },
|
||||
c: interpolatorLinear,
|
||||
l: interpolatorLinear,
|
||||
alpha: { use: interpolatorLinear, fixup: fixupAlpha }
|
||||
},
|
||||
|
||||
difference: {
|
||||
h: differenceHueChroma
|
||||
},
|
||||
|
||||
average: {
|
||||
h: averageAngle
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
34
node_modules/culori/src/lch/parseLch.js
generated
vendored
Normal file
34
node_modules/culori/src/lch/parseLch.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import { Tok } from '../parse.js';
|
||||
|
||||
function parseLch(color, parsed) {
|
||||
if (!parsed || parsed[0] !== 'lch') {
|
||||
return undefined;
|
||||
}
|
||||
const res = { mode: 'lch' };
|
||||
const [, l, c, h, alpha] = parsed;
|
||||
if (l.type !== Tok.None) {
|
||||
if (l.type === Tok.Hue) {
|
||||
return undefined;
|
||||
}
|
||||
res.l = l.value;
|
||||
}
|
||||
if (c.type !== Tok.None) {
|
||||
res.c = Math.max(
|
||||
0,
|
||||
c.type === Tok.Number ? c.value : (c.value * 150) / 100
|
||||
);
|
||||
}
|
||||
if (h.type !== Tok.None) {
|
||||
if (h.type === Tok.Percentage) {
|
||||
return undefined;
|
||||
}
|
||||
res.h = h.value;
|
||||
}
|
||||
if (alpha.type !== Tok.None) {
|
||||
res.alpha = alpha.type === Tok.Number ? alpha.value : alpha.value / 100;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
export default parseLch;
|
31
node_modules/culori/src/lch65/definition.js
generated
vendored
Normal file
31
node_modules/culori/src/lch65/definition.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import convertLabToLch from '../lch/convertLabToLch.js';
|
||||
import convertLchToLab from '../lch/convertLchToLab.js';
|
||||
import convertLab65ToRgb from '../lab65/convertLab65ToRgb.js';
|
||||
import convertRgbToLab65 from '../lab65/convertRgbToLab65.js';
|
||||
import lch from '../lch/definition.js';
|
||||
|
||||
const definition = {
|
||||
...lch,
|
||||
mode: 'lch65',
|
||||
|
||||
parse: ['--lch-d65'],
|
||||
serialize: '--lch-d65',
|
||||
|
||||
toMode: {
|
||||
lab65: c => convertLchToLab(c, 'lab65'),
|
||||
rgb: c => convertLab65ToRgb(convertLchToLab(c, 'lab65'))
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
rgb: c => convertLabToLch(convertRgbToLab65(c), 'lch65'),
|
||||
lab65: c => convertLabToLch(c, 'lch65')
|
||||
},
|
||||
|
||||
ranges: {
|
||||
l: [0, 100],
|
||||
c: [0, 133.807],
|
||||
h: [0, 360]
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
14
node_modules/culori/src/lchuv/convertLchuvToLuv.js
generated
vendored
Normal file
14
node_modules/culori/src/lchuv/convertLchuvToLuv.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
const convertLchuvToLuv = ({ l, c, h, alpha }) => {
|
||||
let res = {
|
||||
mode: 'luv',
|
||||
l: l,
|
||||
u: c ? c * Math.cos((h / 180) * Math.PI) : 0,
|
||||
v: c ? c * Math.sin((h / 180) * Math.PI) : 0
|
||||
};
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertLchuvToLuv;
|
19
node_modules/culori/src/lchuv/convertLuvToLchuv.js
generated
vendored
Normal file
19
node_modules/culori/src/lchuv/convertLuvToLchuv.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import normalizeHue from '../util/normalizeHue.js';
|
||||
|
||||
const convertLuvToLchuv = ({ l, u, v, alpha }) => {
|
||||
let c = Math.sqrt(u * u + v * v);
|
||||
let res = {
|
||||
mode: 'lchuv',
|
||||
l: l,
|
||||
c: c
|
||||
};
|
||||
if (c) {
|
||||
res.h = normalizeHue((Math.atan2(v, u) * 180) / Math.PI);
|
||||
}
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertLuvToLchuv;
|
68
node_modules/culori/src/lchuv/definition.js
generated
vendored
Normal file
68
node_modules/culori/src/lchuv/definition.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
CIELChuv color space
|
||||
--------------------
|
||||
|
||||
Reference:
|
||||
|
||||
https://en.wikipedia.org/wiki/CIELUV
|
||||
*/
|
||||
|
||||
import convertLuvToLchuv from './convertLuvToLchuv.js';
|
||||
import convertLchuvToLuv from './convertLchuvToLuv.js';
|
||||
import convertXyz50ToLuv from '../luv/convertXyz50ToLuv.js';
|
||||
import convertLuvToXyz50 from '../luv/convertLuvToXyz50.js';
|
||||
import convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';
|
||||
import convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';
|
||||
|
||||
import { fixupHueShorter } from '../fixup/hue.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { differenceHueChroma } from '../difference.js';
|
||||
import { averageAngle } from '../average.js';
|
||||
|
||||
const convertRgbToLchuv = rgb =>
|
||||
convertLuvToLchuv(convertXyz50ToLuv(convertRgbToXyz50(rgb)));
|
||||
const convertLchuvToRgb = lchuv =>
|
||||
convertXyz50ToRgb(convertLuvToXyz50(convertLchuvToLuv(lchuv)));
|
||||
|
||||
const definition = {
|
||||
mode: 'lchuv',
|
||||
|
||||
toMode: {
|
||||
luv: convertLchuvToLuv,
|
||||
rgb: convertLchuvToRgb
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
rgb: convertRgbToLchuv,
|
||||
luv: convertLuvToLchuv
|
||||
},
|
||||
|
||||
channels: ['l', 'c', 'h', 'alpha'],
|
||||
|
||||
parse: ['--lchuv'],
|
||||
serialize: '--lchuv',
|
||||
|
||||
ranges: {
|
||||
l: [0, 100],
|
||||
c: [0, 176.956],
|
||||
h: [0, 360]
|
||||
},
|
||||
|
||||
interpolate: {
|
||||
h: { use: interpolatorLinear, fixup: fixupHueShorter },
|
||||
c: interpolatorLinear,
|
||||
l: interpolatorLinear,
|
||||
alpha: { use: interpolatorLinear, fixup: fixupAlpha }
|
||||
},
|
||||
|
||||
difference: {
|
||||
h: differenceHueChroma
|
||||
},
|
||||
|
||||
average: {
|
||||
h: averageAngle
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
20
node_modules/culori/src/lrgb/convertLrgbToRgb.js
generated
vendored
Normal file
20
node_modules/culori/src/lrgb/convertLrgbToRgb.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
const fn = c => {
|
||||
const abs = Math.abs(c);
|
||||
if (abs > 0.0031308) {
|
||||
return (Math.sign(c) || 1) * (1.055 * Math.pow(abs, 1 / 2.4) - 0.055);
|
||||
}
|
||||
return c * 12.92;
|
||||
};
|
||||
|
||||
const convertLrgbToRgb = ({ r, g, b, alpha }, mode = 'rgb') => {
|
||||
let res = {
|
||||
mode,
|
||||
r: fn(r),
|
||||
g: fn(g),
|
||||
b: fn(b)
|
||||
};
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertLrgbToRgb;
|
20
node_modules/culori/src/lrgb/convertRgbToLrgb.js
generated
vendored
Normal file
20
node_modules/culori/src/lrgb/convertRgbToLrgb.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
const fn = c => {
|
||||
const abs = Math.abs(c);
|
||||
if (abs <= 0.04045) {
|
||||
return c / 12.92;
|
||||
}
|
||||
return (Math.sign(c) || 1) * Math.pow((abs + 0.055) / 1.055, 2.4);
|
||||
};
|
||||
|
||||
const convertRgbToLrgb = ({ r, g, b, alpha }) => {
|
||||
let res = {
|
||||
mode: 'lrgb',
|
||||
r: fn(r),
|
||||
g: fn(g),
|
||||
b: fn(b)
|
||||
};
|
||||
if (alpha !== undefined) res.alpha = alpha;
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertRgbToLrgb;
|
21
node_modules/culori/src/lrgb/definition.js
generated
vendored
Normal file
21
node_modules/culori/src/lrgb/definition.js
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import rgb from '../rgb/definition.js';
|
||||
import convertRgbToLrgb from './convertRgbToLrgb.js';
|
||||
import convertLrgbToRgb from './convertLrgbToRgb.js';
|
||||
|
||||
const definition = {
|
||||
...rgb,
|
||||
mode: 'lrgb',
|
||||
|
||||
toMode: {
|
||||
rgb: convertLrgbToRgb
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
rgb: convertRgbToLrgb
|
||||
},
|
||||
|
||||
parse: ['srgb-linear'],
|
||||
serialize: 'srgb-linear'
|
||||
};
|
||||
|
||||
export default definition;
|
25
node_modules/culori/src/luv/convertLuvToXyz50.js
generated
vendored
Normal file
25
node_modules/culori/src/luv/convertLuvToXyz50.js
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import { k } from '../xyz50/constants.js';
|
||||
import { D50 } from '../constants.js';
|
||||
|
||||
export const u_fn = (x, y, z) => (4 * x) / (x + 15 * y + 3 * z);
|
||||
export const v_fn = (x, y, z) => (9 * y) / (x + 15 * y + 3 * z);
|
||||
|
||||
export const un = u_fn(D50.X, D50.Y, D50.Z);
|
||||
export const vn = v_fn(D50.X, D50.Y, D50.Z);
|
||||
|
||||
const convertLuvToXyz50 = ({ l, u, v, alpha }) => {
|
||||
let up = u / (13 * l) + un;
|
||||
let vp = v / (13 * l) + vn;
|
||||
let y = D50.Y * (l <= 8 ? l / k : Math.pow((l + 16) / 116, 3));
|
||||
let x = (y * (9 * up)) / (4 * vp);
|
||||
let z = (y * (12 - 3 * up - 20 * vp)) / (4 * vp);
|
||||
|
||||
let res = { mode: 'xyz50', x, y, z };
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertLuvToXyz50;
|
39
node_modules/culori/src/luv/convertXyz50ToLuv.js
generated
vendored
Normal file
39
node_modules/culori/src/luv/convertXyz50ToLuv.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
import { k, e } from '../xyz50/constants.js';
|
||||
import { D50 } from '../constants.js';
|
||||
|
||||
export const u_fn = (x, y, z) => (4 * x) / (x + 15 * y + 3 * z);
|
||||
export const v_fn = (x, y, z) => (9 * y) / (x + 15 * y + 3 * z);
|
||||
|
||||
export const un = u_fn(D50.X, D50.Y, D50.Z);
|
||||
export const vn = v_fn(D50.X, D50.Y, D50.Z);
|
||||
|
||||
const l_fn = value => (value <= e ? k * value : 116 * Math.cbrt(value) - 16);
|
||||
|
||||
const convertXyz50ToLuv = ({ x, y, z, alpha }) => {
|
||||
let l = l_fn(y / D50.Y);
|
||||
let u = u_fn(x, y, z);
|
||||
let v = v_fn(x, y, z);
|
||||
|
||||
// guard against NaNs produced by `xyz(0 0 0)` black
|
||||
if (!isFinite(u) || !isFinite(v)) {
|
||||
l = u = v = 0;
|
||||
} else {
|
||||
u = 13 * l * (u - un);
|
||||
v = 13 * l * (v - vn);
|
||||
}
|
||||
|
||||
let res = {
|
||||
mode: 'luv',
|
||||
l,
|
||||
u,
|
||||
v
|
||||
};
|
||||
|
||||
if (alpha !== undefined) {
|
||||
res.alpha = alpha;
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export default convertXyz50ToLuv;
|
50
node_modules/culori/src/luv/definition.js
generated
vendored
Normal file
50
node_modules/culori/src/luv/definition.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
CIELUV color space
|
||||
------------------
|
||||
|
||||
Reference:
|
||||
|
||||
https://en.wikipedia.org/wiki/CIELUV
|
||||
*/
|
||||
|
||||
import convertXyz50ToLuv from './convertXyz50ToLuv.js';
|
||||
import convertLuvToXyz50 from './convertLuvToXyz50.js';
|
||||
import convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';
|
||||
import convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';
|
||||
|
||||
import { interpolatorLinear } from '../interpolate/linear.js';
|
||||
import { fixupAlpha } from '../fixup/alpha.js';
|
||||
|
||||
const definition = {
|
||||
mode: 'luv',
|
||||
|
||||
toMode: {
|
||||
xyz50: convertLuvToXyz50,
|
||||
rgb: luv => convertXyz50ToRgb(convertLuvToXyz50(luv))
|
||||
},
|
||||
|
||||
fromMode: {
|
||||
xyz50: convertXyz50ToLuv,
|
||||
rgb: rgb => convertXyz50ToLuv(convertRgbToXyz50(rgb))
|
||||
},
|
||||
|
||||
channels: ['l', 'u', 'v', 'alpha'],
|
||||
|
||||
parse: ['--luv'],
|
||||
serialize: '--luv',
|
||||
|
||||
ranges: {
|
||||
l: [0, 100],
|
||||
u: [-84.936, 175.042],
|
||||
v: [-125.882, 87.243]
|
||||
},
|
||||
|
||||
interpolate: {
|
||||
l: interpolatorLinear,
|
||||
u: interpolatorLinear,
|
||||
v: interpolatorLinear,
|
||||
alpha: { use: interpolatorLinear, fixup: fixupAlpha }
|
||||
}
|
||||
};
|
||||
|
||||
export default definition;
|
72
node_modules/culori/src/map.js
generated
vendored
Normal file
72
node_modules/culori/src/map.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import converter from './converter.js';
|
||||
import prepare from './_prepare.js';
|
||||
import { getMode } from './modes.js';
|
||||
|
||||
const mapper = (fn, mode = 'rgb', preserve_mode = false) => {
|
||||
let channels = mode ? getMode(mode).channels : null;
|
||||
let conv = mode ? converter(mode) : prepare;
|
||||
return color => {
|
||||
let conv_color = conv(color);
|
||||
if (!conv_color) {
|
||||
return undefined;
|
||||
}
|
||||
let res = (channels || getMode(conv_color.mode).channels).reduce(
|
||||
(res, ch) => {
|
||||
let v = fn(conv_color[ch], ch, conv_color, mode);
|
||||
if (v !== undefined && !isNaN(v)) {
|
||||
res[ch] = v;
|
||||
}
|
||||
return res;
|
||||
},
|
||||
{ mode: conv_color.mode }
|
||||
);
|
||||
if (!preserve_mode) {
|
||||
return res;
|
||||
}
|
||||
let prep = prepare(color);
|
||||
if (prep && prep.mode !== res.mode) {
|
||||
return converter(prep.mode)(res);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
};
|
||||
|
||||
const mapAlphaMultiply = (v, ch, c) => {
|
||||
if (ch !== 'alpha') {
|
||||
return (v || 0) * (c.alpha !== undefined ? c.alpha : 1);
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
const mapAlphaDivide = (v, ch, c) => {
|
||||
if (ch !== 'alpha' && c.alpha !== 0) {
|
||||
return (v || 0) / (c.alpha !== undefined ? c.alpha : 1);
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
const mapTransferLinear =
|
||||
(slope = 1, intercept = 0) =>
|
||||
(v, ch) => {
|
||||
if (ch !== 'alpha') {
|
||||
return v * slope + intercept;
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
const mapTransferGamma =
|
||||
(amplitude = 1, exponent = 1, offset = 0) =>
|
||||
(v, ch) => {
|
||||
if (ch !== 'alpha') {
|
||||
return amplitude * Math.pow(v, exponent) + offset;
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
export {
|
||||
mapper,
|
||||
mapAlphaMultiply,
|
||||
mapAlphaDivide,
|
||||
mapTransferLinear,
|
||||
mapTransferGamma
|
||||
};
|
96
node_modules/culori/src/modes.js
generated
vendored
Normal file
96
node_modules/culori/src/modes.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
import converter from './converter.js';
|
||||
|
||||
const converters = {};
|
||||
const modes = {};
|
||||
|
||||
const parsers = [];
|
||||
const colorProfiles = {};
|
||||
|
||||
const identity = v => v;
|
||||
|
||||
const useMode = definition => {
|
||||
converters[definition.mode] = {
|
||||
...converters[definition.mode],
|
||||
...definition.toMode
|
||||
};
|
||||
|
||||
Object.keys(definition.fromMode || {}).forEach(k => {
|
||||
if (!converters[k]) {
|
||||
converters[k] = {};
|
||||
}
|
||||
converters[k][definition.mode] = definition.fromMode[k];
|
||||
});
|
||||
|
||||
// Color space channel ranges
|
||||
if (!definition.ranges) {
|
||||
definition.ranges = {};
|
||||
}
|
||||
|
||||
if (!definition.difference) {
|
||||
definition.difference = {};
|
||||
}
|
||||
|
||||
definition.channels.forEach(channel => {
|
||||
// undefined channel ranges default to the [0, 1] interval
|
||||
if (definition.ranges[channel] === undefined) {
|
||||
definition.ranges[channel] = [0, 1];
|
||||
}
|
||||
|
||||
if (!definition.interpolate[channel]) {
|
||||
throw new Error(`Missing interpolator for: ${channel}`);
|
||||
}
|
||||
|
||||
if (typeof definition.interpolate[channel] === 'function') {
|
||||
definition.interpolate[channel] = {
|
||||
use: definition.interpolate[channel]
|
||||
};
|
||||
}
|
||||
|
||||
if (!definition.interpolate[channel].fixup) {
|
||||
definition.interpolate[channel].fixup = identity;
|
||||
}
|
||||
});
|
||||
|
||||
modes[definition.mode] = definition;
|
||||
(definition.parse || []).forEach(parser => {
|
||||
useParser(parser, definition.mode);
|
||||
});
|
||||
|
||||
return converter(definition.mode);
|
||||
};
|
||||
|
||||
const getMode = mode => modes[mode];
|
||||
|
||||
const useParser = (parser, mode) => {
|
||||
if (typeof parser === 'string') {
|
||||
if (!mode) {
|
||||
throw new Error(`'mode' required when 'parser' is a string`);
|
||||
}
|
||||
colorProfiles[parser] = mode;
|
||||
} else if (typeof parser === 'function') {
|
||||
if (parsers.indexOf(parser) < 0) {
|
||||
parsers.push(parser);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const removeParser = parser => {
|
||||
if (typeof parser === 'string') {
|
||||
delete colorProfiles[parser];
|
||||
} else if (typeof parser === 'function') {
|
||||
const idx = parsers.indexOf(parser);
|
||||
if (idx > 0) {
|
||||
parsers.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
useMode,
|
||||
getMode,
|
||||
useParser,
|
||||
removeParser,
|
||||
converters,
|
||||
parsers,
|
||||
colorProfiles
|
||||
};
|
30
node_modules/culori/src/nearest.js
generated
vendored
Normal file
30
node_modules/culori/src/nearest.js
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import { differenceEuclidean } from './difference.js';
|
||||
|
||||
/*
|
||||
This works linearly right now, but we might get better performance
|
||||
with a V-P Tree (Vantage Point Tree).
|
||||
|
||||
Reference:
|
||||
* http://pnylab.com/papers/vptree/main.html
|
||||
*/
|
||||
|
||||
const nearest = (colors, metric = differenceEuclidean(), accessor = d => d) => {
|
||||
let arr = colors.map((c, idx) => ({ color: accessor(c), i: idx }));
|
||||
return (color, n = 1, τ = Infinity) => {
|
||||
if (isFinite(n)) {
|
||||
n = Math.max(1, Math.min(n, arr.length - 1));
|
||||
}
|
||||
|
||||
arr.forEach(c => {
|
||||
c.d = metric(color, c.color);
|
||||
});
|
||||
|
||||
return arr
|
||||
.sort((a, b) => a.d - b.d)
|
||||
.slice(0, n)
|
||||
.filter(c => c.d < τ)
|
||||
.map(c => colors[c.i]);
|
||||
};
|
||||
};
|
||||
|
||||
export default nearest;
|
19
node_modules/culori/src/okhsl/LICENSE
generated
vendored
Normal file
19
node_modules/culori/src/okhsl/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2021 Björn Ottosson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
62
node_modules/culori/src/okhsl/convertOkhslToOklab.js
generated
vendored
Normal file
62
node_modules/culori/src/okhsl/convertOkhslToOklab.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Adapted from code by Björn Ottosson,
|
||||
released under the MIT license:
|
||||
|
||||
Copyright (c) 2021 Björn Ottosson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import { toe_inv, get_Cs } from './helpers.js';
|
||||
|
||||
export default function convertOkhslToOklab(hsl) {
|
||||
let l = toe_inv(hsl.l);
|
||||
|
||||
const ret = { mode: 'oklab', l };
|
||||
|
||||
if (hsl.alpha !== undefined) {
|
||||
ret.alpha = hsl.alpha;
|
||||
}
|
||||
|
||||
if (!hsl.s || hsl.l === 1) {
|
||||
ret.a = ret.b = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
let a_ = Math.cos((hsl.h / 180) * Math.PI);
|
||||
let b_ = Math.sin((hsl.h / 180) * Math.PI);
|
||||
let [C_0, C_mid, C_max] = get_Cs(l, a_, b_);
|
||||
let t, k_0, k_1, k_2;
|
||||
if (hsl.s < 0.8) {
|
||||
t = 1.25 * hsl.s;
|
||||
k_0 = 0;
|
||||
k_1 = 0.8 * C_0;
|
||||
k_2 = 1 - k_1 / C_mid;
|
||||
} else {
|
||||
t = 5 * (hsl.s - 0.8);
|
||||
k_0 = C_mid;
|
||||
k_1 = (0.2 * C_mid * C_mid * 1.25 * 1.25) / C_0;
|
||||
k_2 = 1 - k_1 / (C_max - C_mid);
|
||||
}
|
||||
let C = k_0 + (t * k_1) / (1 - k_2 * t);
|
||||
ret.a = C * a_;
|
||||
ret.b = C * b_;
|
||||
|
||||
return ret;
|
||||
}
|
60
node_modules/culori/src/okhsl/convertOklabToOkhsl.js
generated
vendored
Normal file
60
node_modules/culori/src/okhsl/convertOklabToOkhsl.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Adapted from code by Björn Ottosson,
|
||||
released under the MIT license:
|
||||
|
||||
Copyright (c) 2021 Björn Ottosson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import normalizeHue from '../util/normalizeHue.js';
|
||||
import { get_Cs, toe } from './helpers.js';
|
||||
|
||||
export default function convertOklabToOkhsl(lab) {
|
||||
const ret = { mode: 'okhsl', l: toe(lab.l) };
|
||||
|
||||
if (lab.alpha !== undefined) {
|
||||
ret.alpha = lab.alpha;
|
||||
}
|
||||
let c = Math.sqrt(lab.a * lab.a + lab.b * lab.b);
|
||||
if (!c) {
|
||||
ret.s = 0;
|
||||
return ret;
|
||||
}
|
||||
let [C_0, C_mid, C_max] = get_Cs(lab.l, lab.a / c, lab.b / c);
|
||||
let s;
|
||||
if (c < C_mid) {
|
||||
let k_0 = 0;
|
||||
let k_1 = 0.8 * C_0;
|
||||
let k_2 = 1 - k_1 / C_mid;
|
||||
let t = (c - k_0) / (k_1 + k_2 * (c - k_0));
|
||||
s = t * 0.8;
|
||||
} else {
|
||||
let k_0 = C_mid;
|
||||
let k_1 = (0.2 * C_mid * C_mid * 1.25 * 1.25) / C_0;
|
||||
let k_2 = 1 - k_1 / (C_max - C_mid);
|
||||
let t = (c - k_0) / (k_1 + k_2 * (c - k_0));
|
||||
s = 0.8 + 0.2 * t;
|
||||
}
|
||||
if (s) {
|
||||
ret.s = s;
|
||||
ret.h = normalizeHue((Math.atan2(lab.b, lab.a) * 180) / Math.PI);
|
||||
}
|
||||
return ret;
|
||||
}
|
348
node_modules/culori/src/okhsl/helpers.js
generated
vendored
Normal file
348
node_modules/culori/src/okhsl/helpers.js
generated
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
Adapted from code by Björn Ottosson,
|
||||
released under the MIT license:
|
||||
|
||||
Copyright (c) 2021 Björn Ottosson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import convertOklabToLrgb from '../oklab/convertOklabToLrgb.js';
|
||||
|
||||
export function toe(x) {
|
||||
const k_1 = 0.206;
|
||||
const k_2 = 0.03;
|
||||
const k_3 = (1 + k_1) / (1 + k_2);
|
||||
return (
|
||||
0.5 *
|
||||
(k_3 * x -
|
||||
k_1 +
|
||||
Math.sqrt((k_3 * x - k_1) * (k_3 * x - k_1) + 4 * k_2 * k_3 * x))
|
||||
);
|
||||
}
|
||||
|
||||
export function toe_inv(x) {
|
||||
const k_1 = 0.206;
|
||||
const k_2 = 0.03;
|
||||
const k_3 = (1 + k_1) / (1 + k_2);
|
||||
return (x * x + k_1 * x) / (k_3 * (x + k_2));
|
||||
}
|
||||
|
||||
// Finds the maximum saturation possible for a given hue that fits in sRGB
|
||||
// Saturation here is defined as S = C/L
|
||||
// a and b must be normalized so a^2 + b^2 == 1
|
||||
function compute_max_saturation(a, b) {
|
||||
// Max saturation will be when one of r, g or b goes below zero.
|
||||
|
||||
// Select different coefficients depending on which component goes below zero first
|
||||
let k0, k1, k2, k3, k4, wl, wm, ws;
|
||||
|
||||
if (-1.88170328 * a - 0.80936493 * b > 1) {
|
||||
// Red component
|
||||
k0 = +1.19086277;
|
||||
k1 = +1.76576728;
|
||||
k2 = +0.59662641;
|
||||
k3 = +0.75515197;
|
||||
k4 = +0.56771245;
|
||||
wl = +4.0767416621;
|
||||
wm = -3.3077115913;
|
||||
ws = +0.2309699292;
|
||||
} else if (1.81444104 * a - 1.19445276 * b > 1) {
|
||||
// Green component
|
||||
k0 = +0.73956515;
|
||||
k1 = -0.45954404;
|
||||
k2 = +0.08285427;
|
||||
k3 = +0.1254107;
|
||||
k4 = +0.14503204;
|
||||
wl = -1.2684380046;
|
||||
wm = +2.6097574011;
|
||||
ws = -0.3413193965;
|
||||
} else {
|
||||
// Blue component
|
||||
k0 = +1.35733652;
|
||||
k1 = -0.00915799;
|
||||
k2 = -1.1513021;
|
||||
k3 = -0.50559606;
|
||||
k4 = +0.00692167;
|
||||
wl = -0.0041960863;
|
||||
wm = -0.7034186147;
|
||||
ws = +1.707614701;
|
||||
}
|
||||
|
||||
// Approximate max saturation using a polynomial:
|
||||
let S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;
|
||||
|
||||
// Do one step Halley's method to get closer
|
||||
// this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite
|
||||
// this should be sufficient for most applications, otherwise do two/three steps
|
||||
|
||||
let k_l = +0.3963377774 * a + 0.2158037573 * b;
|
||||
let k_m = -0.1055613458 * a - 0.0638541728 * b;
|
||||
let k_s = -0.0894841775 * a - 1.291485548 * b;
|
||||
|
||||
{
|
||||
let l_ = 1 + S * k_l;
|
||||
let m_ = 1 + S * k_m;
|
||||
let s_ = 1 + S * k_s;
|
||||
|
||||
let l = l_ * l_ * l_;
|
||||
let m = m_ * m_ * m_;
|
||||
let s = s_ * s_ * s_;
|
||||
|
||||
let l_dS = 3 * k_l * l_ * l_;
|
||||
let m_dS = 3 * k_m * m_ * m_;
|
||||
let s_dS = 3 * k_s * s_ * s_;
|
||||
|
||||
let l_dS2 = 6 * k_l * k_l * l_;
|
||||
let m_dS2 = 6 * k_m * k_m * m_;
|
||||
let s_dS2 = 6 * k_s * k_s * s_;
|
||||
|
||||
let f = wl * l + wm * m + ws * s;
|
||||
let f1 = wl * l_dS + wm * m_dS + ws * s_dS;
|
||||
let f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2;
|
||||
|
||||
S = S - (f * f1) / (f1 * f1 - 0.5 * f * f2);
|
||||
}
|
||||
|
||||
return S;
|
||||
}
|
||||
|
||||
export function find_cusp(a, b) {
|
||||
// First, find the maximum saturation (saturation S = C/L)
|
||||
let S_cusp = compute_max_saturation(a, b);
|
||||
|
||||
// Convert to linear sRGB to find the first point where at least one of r,g or b >= 1:
|
||||
let rgb = convertOklabToLrgb({ l: 1, a: S_cusp * a, b: S_cusp * b });
|
||||
let L_cusp = Math.cbrt(1 / Math.max(rgb.r, rgb.g, rgb.b));
|
||||
let C_cusp = L_cusp * S_cusp;
|
||||
|
||||
return [L_cusp, C_cusp];
|
||||
}
|
||||
|
||||
// Finds intersection of the line defined by
|
||||
// L = L0 * (1 - t) + t * L1;
|
||||
// C = t * C1;
|
||||
// a and b must be normalized so a^2 + b^2 == 1
|
||||
function find_gamut_intersection(a, b, L1, C1, L0, cusp = null) {
|
||||
if (!cusp) {
|
||||
// Find the cusp of the gamut triangle
|
||||
cusp = find_cusp(a, b);
|
||||
}
|
||||
|
||||
// Find the intersection for upper and lower half seprately
|
||||
let t;
|
||||
if ((L1 - L0) * cusp[1] - (cusp[0] - L0) * C1 <= 0) {
|
||||
// Lower half
|
||||
|
||||
t = (cusp[1] * L0) / (C1 * cusp[0] + cusp[1] * (L0 - L1));
|
||||
} else {
|
||||
// Upper half
|
||||
|
||||
// First intersect with triangle
|
||||
t = (cusp[1] * (L0 - 1)) / (C1 * (cusp[0] - 1) + cusp[1] * (L0 - L1));
|
||||
|
||||
// Then one step Halley's method
|
||||
{
|
||||
let dL = L1 - L0;
|
||||
let dC = C1;
|
||||
|
||||
let k_l = +0.3963377774 * a + 0.2158037573 * b;
|
||||
let k_m = -0.1055613458 * a - 0.0638541728 * b;
|
||||
let k_s = -0.0894841775 * a - 1.291485548 * b;
|
||||
|
||||
let l_dt = dL + dC * k_l;
|
||||
let m_dt = dL + dC * k_m;
|
||||
let s_dt = dL + dC * k_s;
|
||||
|
||||
// If higher accuracy is required, 2 or 3 iterations of the following block can be used:
|
||||
{
|
||||
let L = L0 * (1 - t) + t * L1;
|
||||
let C = t * C1;
|
||||
|
||||
let l_ = L + C * k_l;
|
||||
let m_ = L + C * k_m;
|
||||
let s_ = L + C * k_s;
|
||||
|
||||
let l = l_ * l_ * l_;
|
||||
let m = m_ * m_ * m_;
|
||||
let s = s_ * s_ * s_;
|
||||
|
||||
let ldt = 3 * l_dt * l_ * l_;
|
||||
let mdt = 3 * m_dt * m_ * m_;
|
||||
let sdt = 3 * s_dt * s_ * s_;
|
||||
|
||||
let ldt2 = 6 * l_dt * l_dt * l_;
|
||||
let mdt2 = 6 * m_dt * m_dt * m_;
|
||||
let sdt2 = 6 * s_dt * s_dt * s_;
|
||||
|
||||
let r =
|
||||
4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s - 1;
|
||||
let r1 =
|
||||
4.0767416621 * ldt -
|
||||
3.3077115913 * mdt +
|
||||
0.2309699292 * sdt;
|
||||
let r2 =
|
||||
4.0767416621 * ldt2 -
|
||||
3.3077115913 * mdt2 +
|
||||
0.2309699292 * sdt2;
|
||||
|
||||
let u_r = r1 / (r1 * r1 - 0.5 * r * r2);
|
||||
let t_r = -r * u_r;
|
||||
|
||||
let g =
|
||||
-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s - 1;
|
||||
let g1 =
|
||||
-1.2684380046 * ldt +
|
||||
2.6097574011 * mdt -
|
||||
0.3413193965 * sdt;
|
||||
let g2 =
|
||||
-1.2684380046 * ldt2 +
|
||||
2.6097574011 * mdt2 -
|
||||
0.3413193965 * sdt2;
|
||||
|
||||
let u_g = g1 / (g1 * g1 - 0.5 * g * g2);
|
||||
let t_g = -g * u_g;
|
||||
|
||||
let b =
|
||||
-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s - 1;
|
||||
let b1 =
|
||||
-0.0041960863 * ldt -
|
||||
0.7034186147 * mdt +
|
||||
1.707614701 * sdt;
|
||||
let b2 =
|
||||
-0.0041960863 * ldt2 -
|
||||
0.7034186147 * mdt2 +
|
||||
1.707614701 * sdt2;
|
||||
|
||||
let u_b = b1 / (b1 * b1 - 0.5 * b * b2);
|
||||
let t_b = -b * u_b;
|
||||
|
||||
t_r = u_r >= 0 ? t_r : 10e5;
|
||||
t_g = u_g >= 0 ? t_g : 10e5;
|
||||
t_b = u_b >= 0 ? t_b : 10e5;
|
||||
|
||||
t += Math.min(t_r, Math.min(t_g, t_b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
export function get_ST_max(a_, b_, cusp = null) {
|
||||
if (!cusp) {
|
||||
cusp = find_cusp(a_, b_);
|
||||
}
|
||||
let L = cusp[0];
|
||||
let C = cusp[1];
|
||||
return [C / L, C / (1 - L)];
|
||||
}
|
||||
|
||||
export function get_ST_mid(a_, b_) {
|
||||
let S =
|
||||
0.11516993 +
|
||||
1 /
|
||||
(+7.4477897 +
|
||||
4.1590124 * b_ +
|
||||
a_ *
|
||||
(-2.19557347 +
|
||||
1.75198401 * b_ +
|
||||
a_ *
|
||||
(-2.13704948 -
|
||||
10.02301043 * b_ +
|
||||
a_ *
|
||||
(-4.24894561 +
|
||||
5.38770819 * b_ +
|
||||
4.69891013 * a_))));
|
||||
|
||||
let T =
|
||||
0.11239642 +
|
||||
1 /
|
||||
(+1.6132032 -
|
||||
0.68124379 * b_ +
|
||||
a_ *
|
||||
(+0.40370612 +
|
||||
0.90148123 * b_ +
|
||||
a_ *
|
||||
(-0.27087943 +
|
||||
0.6122399 * b_ +
|
||||
a_ *
|
||||
(+0.00299215 -
|
||||
0.45399568 * b_ -
|
||||
0.14661872 * a_))));
|
||||
|
||||
return [S, T];
|
||||
}
|
||||
|
||||
export function get_Cs(L, a_, b_) {
|
||||
let cusp = find_cusp(a_, b_);
|
||||
|
||||
let C_max = find_gamut_intersection(a_, b_, L, 1, L, cusp);
|
||||
let ST_max = get_ST_max(a_, b_, cusp);
|
||||
|
||||
let S_mid =
|
||||
0.11516993 +
|
||||
1 /
|
||||
(+7.4477897 +
|
||||
4.1590124 * b_ +
|
||||
a_ *
|
||||
(-2.19557347 +
|
||||
1.75198401 * b_ +
|
||||
a_ *
|
||||
(-2.13704948 -
|
||||
10.02301043 * b_ +
|
||||
a_ *
|
||||
(-4.24894561 +
|
||||
5.38770819 * b_ +
|
||||
4.69891013 * a_))));
|
||||
|
||||
let T_mid =
|
||||
0.11239642 +
|
||||
1 /
|
||||
(+1.6132032 -
|
||||
0.68124379 * b_ +
|
||||
a_ *
|
||||
(+0.40370612 +
|
||||
0.90148123 * b_ +
|
||||
a_ *
|
||||
(-0.27087943 +
|
||||
0.6122399 * b_ +
|
||||
a_ *
|
||||
(+0.00299215 -
|
||||
0.45399568 * b_ -
|
||||
0.14661872 * a_))));
|
||||
|
||||
let k = C_max / Math.min(L * ST_max[0], (1 - L) * ST_max[1]);
|
||||
|
||||
let C_a = L * S_mid;
|
||||
let C_b = (1 - L) * T_mid;
|
||||
let C_mid =
|
||||
0.9 *
|
||||
k *
|
||||
Math.sqrt(
|
||||
Math.sqrt(
|
||||
1 / (1 / (C_a * C_a * C_a * C_a) + 1 / (C_b * C_b * C_b * C_b))
|
||||
)
|
||||
);
|
||||
|
||||
C_a = L * 0.4;
|
||||
C_b = (1 - L) * 0.8;
|
||||
let C_0 = Math.sqrt(1 / (1 / (C_a * C_a) + 1 / (C_b * C_b)));
|
||||
return [C_0, C_mid, C_max];
|
||||
}
|
24
node_modules/culori/src/okhsl/modeOkhsl.js
generated
vendored
Normal file
24
node_modules/culori/src/okhsl/modeOkhsl.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import convertRgbToOklab from '../oklab/convertRgbToOklab.js';
|
||||
import convertOklabToRgb from '../oklab/convertOklabToRgb.js';
|
||||
import convertOklabToOkhsl from './convertOklabToOkhsl.js';
|
||||
import convertOkhslToOklab from './convertOkhslToOklab.js';
|
||||
|
||||
import modeHsl from '../hsl/definition.js';
|
||||
|
||||
const modeOkhsl = {
|
||||
...modeHsl,
|
||||
mode: 'okhsl',
|
||||
channels: ['h', 's', 'l', 'alpha'],
|
||||
parse: ['--okhsl'],
|
||||
serialize: '--okhsl',
|
||||
fromMode: {
|
||||
oklab: convertOklabToOkhsl,
|
||||
rgb: c => convertOklabToOkhsl(convertRgbToOklab(c))
|
||||
},
|
||||
toMode: {
|
||||
oklab: convertOkhslToOklab,
|
||||
rgb: c => convertOklabToRgb(convertOkhslToOklab(c))
|
||||
}
|
||||
};
|
||||
|
||||
export default modeOkhsl;
|
63
node_modules/culori/src/okhsv/convertOkhsvToOklab.js
generated
vendored
Normal file
63
node_modules/culori/src/okhsv/convertOkhsvToOklab.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright (c) 2021 Björn Ottosson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import convertOklabToLrgb from '../oklab/convertOklabToLrgb.js';
|
||||
import { get_ST_max, toe_inv } from '../okhsl/helpers.js';
|
||||
|
||||
export default function convertOkhsvToOklab(hsv) {
|
||||
const ret = { mode: 'oklab' };
|
||||
if (hsv.alpha !== undefined) {
|
||||
ret.alpha = hsv.alpha;
|
||||
}
|
||||
|
||||
// Hue may be missing for achromatic colors
|
||||
const h = hsv.h || 0;
|
||||
|
||||
const a_ = Math.cos((h / 180) * Math.PI);
|
||||
const b_ = Math.sin((h / 180) * Math.PI);
|
||||
|
||||
const [S_max, T] = get_ST_max(a_, b_);
|
||||
const S_0 = 0.5;
|
||||
const k = 1 - S_0 / S_max;
|
||||
const L_v = 1 - (hsv.s * S_0) / (S_0 + T - T * k * hsv.s);
|
||||
const C_v = (hsv.s * T * S_0) / (S_0 + T - T * k * hsv.s);
|
||||
|
||||
const L_vt = toe_inv(L_v);
|
||||
const C_vt = (C_v * L_vt) / L_v;
|
||||
const rgb_scale = convertOklabToLrgb({
|
||||
l: L_vt,
|
||||
a: a_ * C_vt,
|
||||
b: b_ * C_vt
|
||||
});
|
||||
const scale_L = Math.cbrt(
|
||||
1 / Math.max(rgb_scale.r, rgb_scale.g, rgb_scale.b, 0)
|
||||
);
|
||||
|
||||
const L_new = toe_inv(hsv.v * L_v);
|
||||
const C = (C_v * L_new) / L_v;
|
||||
|
||||
ret.l = L_new * scale_L;
|
||||
ret.a = C * a_ * scale_L;
|
||||
ret.b = C * b_ * scale_L;
|
||||
|
||||
return ret;
|
||||
}
|
70
node_modules/culori/src/okhsv/convertOklabToOkhsv.js
generated
vendored
Normal file
70
node_modules/culori/src/okhsv/convertOklabToOkhsv.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Adapted from code by Björn Ottosson,
|
||||
released under the MIT license:
|
||||
|
||||
Copyright (c) 2021 Björn Ottosson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
import normalizeHue from '../util/normalizeHue.js';
|
||||
import convertOklabToLrgb from '../oklab/convertOklabToLrgb.js';
|
||||
import { get_ST_max, toe_inv, toe } from '../okhsl/helpers.js';
|
||||
|
||||
export default function convertOklabToOkhsv(lab) {
|
||||
let c = Math.sqrt(lab.a * lab.a + lab.b * lab.b);
|
||||
|
||||
let l = lab.l;
|
||||
// TODO: c = 0
|
||||
let a_ = c ? lab.a / c : 1;
|
||||
let b_ = c ? lab.b / c : 1;
|
||||
|
||||
let [S_max, T] = get_ST_max(a_, b_);
|
||||
let S_0 = 0.5;
|
||||
let k = 1 - S_0 / S_max;
|
||||
|
||||
let t = T / (c + l * T);
|
||||
let L_v = t * l;
|
||||
let C_v = t * c;
|
||||
|
||||
let L_vt = toe_inv(L_v);
|
||||
let C_vt = (C_v * L_vt) / L_v;
|
||||
|
||||
let rgb_scale = convertOklabToLrgb({ l: L_vt, a: a_ * C_vt, b: b_ * C_vt });
|
||||
let scale_L = Math.cbrt(
|
||||
1 / Math.max(rgb_scale.r, rgb_scale.g, rgb_scale.b, 0)
|
||||
);
|
||||
|
||||
l = l / scale_L;
|
||||
c = ((c / scale_L) * toe(l)) / l;
|
||||
l = toe(l);
|
||||
|
||||
const ret = {
|
||||
mode: 'okhsv',
|
||||
s: c ? ((S_0 + T) * C_v) / (T * S_0 + T * k * C_v) : 0,
|
||||
v: l ? l / L_v : 0
|
||||
};
|
||||
if (ret.s) {
|
||||
ret.h = normalizeHue((Math.atan2(lab.b, lab.a) * 180) / Math.PI);
|
||||
}
|
||||
if (lab.alpha !== undefined) {
|
||||
ret.alpha = lab.alpha;
|
||||
}
|
||||
return ret;
|
||||
}
|
24
node_modules/culori/src/okhsv/modeOkhsv.js
generated
vendored
Normal file
24
node_modules/culori/src/okhsv/modeOkhsv.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
import convertRgbToOklab from '../oklab/convertRgbToOklab.js';
|
||||
import convertOklabToRgb from '../oklab/convertOklabToRgb.js';
|
||||
import convertOklabToOkhsv from './convertOklabToOkhsv.js';
|
||||
import convertOkhsvToOklab from './convertOkhsvToOklab.js';
|
||||
|
||||
import modeHsv from '../hsv/definition.js';
|
||||
|
||||
const modeOkhsv = {
|
||||
...modeHsv,
|
||||
mode: 'okhsv',
|
||||
channels: ['h', 's', 'v', 'alpha'],
|
||||
parse: ['--okhsv'],
|
||||
serialize: '--okhsv',
|
||||
fromMode: {
|
||||
oklab: convertOklabToOkhsv,
|
||||
rgb: c => convertOklabToOkhsv(convertRgbToOklab(c))
|
||||
},
|
||||
toMode: {
|
||||
oklab: convertOkhsvToOklab,
|
||||
rgb: c => convertOklabToRgb(convertOkhsvToOklab(c))
|
||||
}
|
||||
};
|
||||
|
||||
export default modeOkhsv;
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user