import { bound01, pad2 } from './util';
|
// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
|
// <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
|
/**
|
* Handle bounds / percentage checking to conform to CSS color spec
|
* <http://www.w3.org/TR/css3-color/>
|
* *Assumes:* r, g, b in [0, 255] or [0, 1]
|
* *Returns:* { r, g, b } in [0, 255]
|
*/
|
export function rgbToRgb(r, g, b) {
|
return {
|
r: bound01(r, 255) * 255,
|
g: bound01(g, 255) * 255,
|
b: bound01(b, 255) * 255,
|
};
|
}
|
/**
|
* Converts an RGB color value to HSL.
|
* *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
|
* *Returns:* { h, s, l } in [0,1]
|
*/
|
export function rgbToHsl(r, g, b) {
|
r = bound01(r, 255);
|
g = bound01(g, 255);
|
b = bound01(b, 255);
|
var max = Math.max(r, g, b);
|
var min = Math.min(r, g, b);
|
var h = 0;
|
var s = 0;
|
var l = (max + min) / 2;
|
if (max === min) {
|
s = 0;
|
h = 0; // achromatic
|
}
|
else {
|
var d = max - min;
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
switch (max) {
|
case r:
|
h = (g - b) / d + (g < b ? 6 : 0);
|
break;
|
case g:
|
h = (b - r) / d + 2;
|
break;
|
case b:
|
h = (r - g) / d + 4;
|
break;
|
default:
|
break;
|
}
|
h /= 6;
|
}
|
return { h: h, s: s, l: l };
|
}
|
function hue2rgb(p, q, t) {
|
if (t < 0) {
|
t += 1;
|
}
|
if (t > 1) {
|
t -= 1;
|
}
|
if (t < 1 / 6) {
|
return p + (q - p) * (6 * t);
|
}
|
if (t < 1 / 2) {
|
return q;
|
}
|
if (t < 2 / 3) {
|
return p + (q - p) * (2 / 3 - t) * 6;
|
}
|
return p;
|
}
|
/**
|
* Converts an HSL color value to RGB.
|
*
|
* *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
|
* *Returns:* { r, g, b } in the set [0, 255]
|
*/
|
export function hslToRgb(h, s, l) {
|
var r;
|
var g;
|
var b;
|
h = bound01(h, 360);
|
s = bound01(s, 100);
|
l = bound01(l, 100);
|
if (s === 0) {
|
// achromatic
|
g = l;
|
b = l;
|
r = l;
|
}
|
else {
|
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
var p = 2 * l - q;
|
r = hue2rgb(p, q, h + 1 / 3);
|
g = hue2rgb(p, q, h);
|
b = hue2rgb(p, q, h - 1 / 3);
|
}
|
return { r: r * 255, g: g * 255, b: b * 255 };
|
}
|
/**
|
* Converts an RGB color value to HSV
|
*
|
* *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
|
* *Returns:* { h, s, v } in [0,1]
|
*/
|
export function rgbToHsv(r, g, b) {
|
r = bound01(r, 255);
|
g = bound01(g, 255);
|
b = bound01(b, 255);
|
var max = Math.max(r, g, b);
|
var min = Math.min(r, g, b);
|
var h = 0;
|
var v = max;
|
var d = max - min;
|
var s = max === 0 ? 0 : d / max;
|
if (max === min) {
|
h = 0; // achromatic
|
}
|
else {
|
switch (max) {
|
case r:
|
h = (g - b) / d + (g < b ? 6 : 0);
|
break;
|
case g:
|
h = (b - r) / d + 2;
|
break;
|
case b:
|
h = (r - g) / d + 4;
|
break;
|
default:
|
break;
|
}
|
h /= 6;
|
}
|
return { h: h, s: s, v: v };
|
}
|
/**
|
* Converts an HSV color value to RGB.
|
*
|
* *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
|
* *Returns:* { r, g, b } in the set [0, 255]
|
*/
|
export function hsvToRgb(h, s, v) {
|
h = bound01(h, 360) * 6;
|
s = bound01(s, 100);
|
v = bound01(v, 100);
|
var i = Math.floor(h);
|
var f = h - i;
|
var p = v * (1 - s);
|
var q = v * (1 - f * s);
|
var t = v * (1 - (1 - f) * s);
|
var mod = i % 6;
|
var r = [v, q, p, p, t, v][mod];
|
var g = [t, v, v, q, p, p][mod];
|
var b = [p, p, t, v, v, q][mod];
|
return { r: r * 255, g: g * 255, b: b * 255 };
|
}
|
/**
|
* Converts an RGB color to hex
|
*
|
* Assumes r, g, and b are contained in the set [0, 255]
|
* Returns a 3 or 6 character hex
|
*/
|
export function rgbToHex(r, g, b, allow3Char) {
|
var hex = [
|
pad2(Math.round(r).toString(16)),
|
pad2(Math.round(g).toString(16)),
|
pad2(Math.round(b).toString(16)),
|
];
|
// Return a 3 character hex if possible
|
if (allow3Char &&
|
hex[0].startsWith(hex[0].charAt(1)) &&
|
hex[1].startsWith(hex[1].charAt(1)) &&
|
hex[2].startsWith(hex[2].charAt(1))) {
|
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
|
}
|
return hex.join('');
|
}
|
/**
|
* Converts an RGBA color plus alpha transparency to hex
|
*
|
* Assumes r, g, b are contained in the set [0, 255] and
|
* a in [0, 1]. Returns a 4 or 8 character rgba hex
|
*/
|
// eslint-disable-next-line max-params
|
export function rgbaToHex(r, g, b, a, allow4Char) {
|
var hex = [
|
pad2(Math.round(r).toString(16)),
|
pad2(Math.round(g).toString(16)),
|
pad2(Math.round(b).toString(16)),
|
pad2(convertDecimalToHex(a)),
|
];
|
// Return a 4 character hex if possible
|
if (allow4Char &&
|
hex[0].startsWith(hex[0].charAt(1)) &&
|
hex[1].startsWith(hex[1].charAt(1)) &&
|
hex[2].startsWith(hex[2].charAt(1)) &&
|
hex[3].startsWith(hex[3].charAt(1))) {
|
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
|
}
|
return hex.join('');
|
}
|
/**
|
* Converts an RGBA color to an ARGB Hex8 string
|
* Rarely used, but required for "toFilter()"
|
*/
|
export function rgbaToArgbHex(r, g, b, a) {
|
var hex = [
|
pad2(convertDecimalToHex(a)),
|
pad2(Math.round(r).toString(16)),
|
pad2(Math.round(g).toString(16)),
|
pad2(Math.round(b).toString(16)),
|
];
|
return hex.join('');
|
}
|
/** Converts a decimal to a hex value */
|
export function convertDecimalToHex(d) {
|
return Math.round(parseFloat(d) * 255).toString(16);
|
}
|
/** Converts a hex value to a decimal */
|
export function convertHexToDecimal(h) {
|
return parseIntFromHex(h) / 255;
|
}
|
/** Parse a base-16 hex value into a base-10 integer */
|
export function parseIntFromHex(val) {
|
return parseInt(val, 16);
|
}
|
export function numberInputToObject(color) {
|
return {
|
r: color >> 16,
|
g: (color & 0xff00) >> 8,
|
b: color & 0xff,
|
};
|
}
|