@ctrl/tinycolor
Version:
Fast, small color manipulation and conversion for JavaScript
293 lines (292 loc) • 8.61 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.numberInputToObject = exports.parseIntFromHex = exports.convertHexToDecimal = exports.convertDecimalToHex = exports.rgbToCmyk = exports.cmykToRgb = exports.rgbaToArgbHex = exports.rgbaToHex = exports.rgbToHex = exports.hsvToRgb = exports.rgbToHsv = exports.hslToRgb = exports.rgbToHsl = exports.rgbToRgb = void 0;
const util_js_1 = require("./util.js");
// `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]
*/
function rgbToRgb(r, g, b) {
return {
r: (0, util_js_1.bound01)(r, 255) * 255,
g: (0, util_js_1.bound01)(g, 255) * 255,
b: (0, util_js_1.bound01)(b, 255) * 255,
};
}
exports.rgbToRgb = rgbToRgb;
/**
* 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]
*/
function rgbToHsl(r, g, b) {
r = (0, util_js_1.bound01)(r, 255);
g = (0, util_js_1.bound01)(g, 255);
b = (0, util_js_1.bound01)(b, 255);
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h = 0;
let s = 0;
const l = (max + min) / 2;
if (max === min) {
s = 0;
h = 0; // achromatic
}
else {
const 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, s, l };
}
exports.rgbToHsl = rgbToHsl;
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]
*/
function hslToRgb(h, s, l) {
let r;
let g;
let b;
h = (0, util_js_1.bound01)(h, 360);
s = (0, util_js_1.bound01)(s, 100);
l = (0, util_js_1.bound01)(l, 100);
if (s === 0) {
// achromatic
g = l;
b = l;
r = l;
}
else {
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const 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 };
}
exports.hslToRgb = hslToRgb;
/**
* 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]
*/
function rgbToHsv(r, g, b) {
r = (0, util_js_1.bound01)(r, 255);
g = (0, util_js_1.bound01)(g, 255);
b = (0, util_js_1.bound01)(b, 255);
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h = 0;
const v = max;
const d = max - min;
const 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, s, v };
}
exports.rgbToHsv = rgbToHsv;
/**
* 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]
*/
function hsvToRgb(h, s, v) {
h = (0, util_js_1.bound01)(h, 360) * 6;
s = (0, util_js_1.bound01)(s, 100);
v = (0, util_js_1.bound01)(v, 100);
const i = Math.floor(h);
const f = h - i;
const p = v * (1 - s);
const q = v * (1 - f * s);
const t = v * (1 - (1 - f) * s);
const mod = i % 6;
const r = [v, q, p, p, t, v][mod];
const g = [t, v, v, q, p, p][mod];
const b = [p, p, t, v, v, q][mod];
return { r: r * 255, g: g * 255, b: b * 255 };
}
exports.hsvToRgb = hsvToRgb;
/**
* 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
*/
function rgbToHex(r, g, b, allow3Char) {
const hex = [
(0, util_js_1.pad2)(Math.round(r).toString(16)),
(0, util_js_1.pad2)(Math.round(g).toString(16)),
(0, util_js_1.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('');
}
exports.rgbToHex = rgbToHex;
/**
* 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
function rgbaToHex(r, g, b, a, allow4Char) {
const hex = [
(0, util_js_1.pad2)(Math.round(r).toString(16)),
(0, util_js_1.pad2)(Math.round(g).toString(16)),
(0, util_js_1.pad2)(Math.round(b).toString(16)),
(0, util_js_1.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('');
}
exports.rgbaToHex = rgbaToHex;
/**
* Converts an RGBA color to an ARGB Hex8 string
* Rarely used, but required for "toFilter()"
*
* *Assumes:* r, g, b are contained in the set [0, 255] and a in [0, 1]
* *Returns:* a 8 character argb hex
*/
function rgbaToArgbHex(r, g, b, a) {
const hex = [
(0, util_js_1.pad2)(convertDecimalToHex(a)),
(0, util_js_1.pad2)(Math.round(r).toString(16)),
(0, util_js_1.pad2)(Math.round(g).toString(16)),
(0, util_js_1.pad2)(Math.round(b).toString(16)),
];
return hex.join('');
}
exports.rgbaToArgbHex = rgbaToArgbHex;
/**
* Converts CMYK to RBG
* Assumes c, m, y, k are in the set [0, 100]
*/
function cmykToRgb(c, m, y, k) {
const cConv = c / 100;
const mConv = m / 100;
const yConv = y / 100;
const kConv = k / 100;
const r = 255 * (1 - cConv) * (1 - kConv);
const g = 255 * (1 - mConv) * (1 - kConv);
const b = 255 * (1 - yConv) * (1 - kConv);
return { r, g, b };
}
exports.cmykToRgb = cmykToRgb;
function rgbToCmyk(r, g, b) {
let c = 1 - r / 255;
let m = 1 - g / 255;
let y = 1 - b / 255;
let k = Math.min(c, m, y);
if (k === 1) {
c = 0;
m = 0;
y = 0;
}
else {
c = ((c - k) / (1 - k)) * 100;
m = ((m - k) / (1 - k)) * 100;
y = ((y - k) / (1 - k)) * 100;
}
k *= 100;
return {
c: Math.round(c),
m: Math.round(m),
y: Math.round(y),
k: Math.round(k),
};
}
exports.rgbToCmyk = rgbToCmyk;
/** Converts a decimal to a hex value */
function convertDecimalToHex(d) {
return Math.round(parseFloat(d) * 255).toString(16);
}
exports.convertDecimalToHex = convertDecimalToHex;
/** Converts a hex value to a decimal */
function convertHexToDecimal(h) {
return parseIntFromHex(h) / 255;
}
exports.convertHexToDecimal = convertHexToDecimal;
/** Parse a base-16 hex value into a base-10 integer */
function parseIntFromHex(val) {
return parseInt(val, 16);
}
exports.parseIntFromHex = parseIntFromHex;
function numberInputToObject(color) {
return {
r: color >> 16,
g: (color & 0xff00) >> 8,
b: color & 0xff,
};
}
exports.numberInputToObject = numberInputToObject;
;