UNPKG

chromatism

Version:

A simple set of utility functions for colours.

142 lines (123 loc) 3.46 kB
import getTransform from '../helpers/get-transform' import bounded from '../helpers/bounded' import fromXYZ from './XYZ' const { lms: fromXYZTolms, cielab: fromXYZTocielab, cieluv: fromXYZTocieluv, xyY: fromXYZToxyY } = fromXYZ const hsl = value => { var r = value['r'] / 255 var g = value['g'] / 255 var b = value['b'] / 255 var rgbOrdered = [ r, g, b ].sort() var l = ((rgbOrdered[0] + rgbOrdered[2]) / 2) * 100 var s, h if (rgbOrdered[0] === rgbOrdered[2]) { s = 0 h = 0 } else { if (l >= 50) { s = ((rgbOrdered[2] - rgbOrdered[0]) / ((2.0 - rgbOrdered[2]) - rgbOrdered[0])) * 100 } else { s = ((rgbOrdered[2] - rgbOrdered[0]) / (rgbOrdered[2] + rgbOrdered[0])) * 100 } if (rgbOrdered[2] === r) { h = ((g - b) / (rgbOrdered[2] - rgbOrdered[0])) * 60 } else if (rgbOrdered[2] === g) { h = (2 + ((b - r) / (rgbOrdered[2] - rgbOrdered[0]))) * 60 } else { h = (4 + ((r - g) / (rgbOrdered[2] - rgbOrdered[0]))) * 60 } if (h < 0) { h += 360 } else if (h > 360) { h = h % 360 } } return { h: h, s: s, l: l } } const cieluv = value => fromXYZTocieluv(XYZ(value)) const XYZ = value => { let normalized = [ value.r, value.g, value.b ].map((v) => v / 255) let linear = normalized.map((V) => { if (V <= 0.04045) { return V / 12.92 } return Math.pow(((V + 0.055) / 1.055), 2.4) }) // Observer is 2° // Whitepoint is D65 // sRGB standard stuff eh! // [ Shamelessly stolen off Wikipedia ] let M = getTransform('SRGB_XYZ') let [ X, Y, Z ] = M.map((m) => { return linear.reduce((acc, v, key) => { return (m[key] * v) + acc }, 0) }).map((o) => o * 100) return { X, Y, Z } } export default { hex: value => { var r = Math.round(value['r']).toString(16) if (r.length === 1) { r = '0' + r } var g = Math.round(value['g']).toString(16) if (g.length === 1) { g = '0' + g } var b = Math.round(value['b']).toString(16) if (b.length === 1) { b = '0' + b } return '#' + r + g + b }, cssrgb: value => 'rgb(' + Math.round(value['r']) + ',' + Math.round(value['g']) + ',' + Math.round(value['b']) + ')', hsl, csshsl: value => { var { h, s, l } = hsl(value) return 'hsl(' + Math.round(h) + ',' + Math.round(s) + '%,' + Math.round(l) + '%)' }, cmyk: value => { var tempR = value['r'] / 255 var tempG = value['g'] / 255 var tempB = value['b'] / 255 var k = 1 - (Math.max(tempR, tempG, tempB)) if (k !== 1) { return { c: ((1 - tempR) - k) / (1 - k), m: ((1 - tempG) - k) / (1 - k), y: ((1 - tempB) - k) / (1 - k), k } } else { return { c: 0, m: 0, y: 0, k } } }, yiq: value => { var y = (0.299 * (value.r / 255)) + (0.587 * (value.g / 255)) + (0.114 * (value.b / 255)) var i = (0.596 * (value.r / 255)) + (-0.274 * (value.g / 255)) + (-0.322 * (value.b / 255)) var q = (0.211 * (value.r / 255)) + (-0.523 * (value.g / 255)) + (0.312 * (value.b / 255)) /* YIQ is not a transformation of RGB, so it's pretty lossy */ i = bounded(i, [ -0.5957, 0.5957 ]) q = bounded(q, [ -0.5226, 0.5226 ]) return { y, i, q } }, XYZ, lms: value => fromXYZTolms(XYZ(value)), cielab: value => fromXYZTocielab(XYZ(value)), cieluv, xyY: value => fromXYZToxyY(XYZ(value)) }