Last active
November 21, 2016 16:24
-
-
Save tlindig/9392075 to your computer and use it in GitHub Desktop.
Functions to convert color values. rgb/rgba, hex and hsv/hsva programmatic. Color keyword, hsl/hsla and rgb with percentage values with help of browser.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* color conversion | |
* | |
* Copyright (c) 2014 Tobias Lindig, Germany | |
* http://tlindig.de | |
* License: MIT | |
*/ | |
var __rgx_strictRgbX = /^(?:rgb|rgba)\s*\(\s*(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})(?:,\s*([0|1]|0?\.\d+))?\s*\)/i; // don't accept % values | |
var __rgx_isHex = /^#/; | |
var __rgx_hex3 = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; | |
var __rgx_hex6 = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i; | |
/** | |
* Normalize a css color value to rgba array. invalid color value will be return null. | |
* | |
* @param {string} value - css color value | |
* @return {Array|null} - Array.length === 4, with: | |
* [0] red, {number 0-255} | |
* [1] green, {number 0-255} | |
* [2] blue, {number 0-255} | |
* [3] alpha, {float 0-1} | |
*/ | |
var __normalizeColor = (function() { | |
var _dummyDiv = document.createElement("div"); | |
var _dummyComputedStyle = window.getComputedStyle(_dummyDiv); | |
return function normalizeColor(value) { | |
if(!value) { | |
return null; | |
} | |
if(value === "transparent") { | |
return [0,0,0,0]; | |
} | |
// only as optimization. it should be faster than using computedStyle | |
if(__rgx_isHex.test(value)) { | |
return __parseHex(value); | |
} | |
// to prevent that a colored transparent will become "transparent" | |
// and be able to identify invalid values | |
if(__rgx_strictRgbX.test(value)) { | |
return __parseRgba(value); | |
} | |
// all other shall convert the browser to rgb / rgba | |
_dummyDiv.style.backgroundColor = value; | |
var compColor = _dummyComputedStyle.backgroundColor; | |
if(compColor === "transparent") { | |
return null; //transparent is the default value, so value seams to be invalid | |
} else { | |
return __parseRgba(compColor); | |
} | |
} | |
})(); | |
/** | |
* Serialize a rgba array to 6 letter hex value. | |
* | |
* @param {Array} rgba - Array.length === 4, with: | |
* [0] red, {number 0-255} | |
* [1] green, {number 0-255} | |
* [2] blue, {number 0-255} | |
* [3] alpha, {float 0-1} | |
* @return {string} hex color code, in format "#rrggbb" | |
*/ | |
function __rgba2hex(rgba) { | |
return "#" + (0x1000000 + (rgba[0] << 16) + (rgba[1] << 8) + rgba[2]).toString(16).slice(1); | |
} | |
/** | |
* Parse strict css rgb and rgba color value to rgba array. strict mean no % values. | |
* | |
* @param {string} value - css rgb or rgba value | |
* @return {Array|null} - Array.length === 4, with: | |
* [0] red, {number 0-255} | |
* [1] green, {number 0-255} | |
* [2] blue, {number 0-255} | |
* [3] alpha, {float 0-1} | |
*/ | |
function __parseRgba(value) { | |
var result = __rgx_strictRgbX.exec(value); | |
return result ? [// [0] is the regexp argument | |
parseInt(result[1], 10), // red | |
parseInt(result[2], 10), // green | |
parseInt(result[3], 10), // blue | |
result[4] !== undefined ? parseFloat(result[4]) : 1 // alpha | |
] : null; | |
} | |
/** | |
* Parse and convert css hex color value to rgba array | |
* | |
* @param {string} hex - css hex color value | |
* @param {string|float} alpha - value for alpha channel {float 0-1} | |
* @return {Array|null} - Array.length === 4, with: | |
* [0] red, {number 0-255} | |
* [1] green, {number 0-255} | |
* [2] blue, {number 0-255} | |
* [3] alpha, {float 0-1} | |
*/ | |
function __parseHex(hex, alpha) { | |
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") | |
hex = hex.replace(__rgx_hex3, function(m, r, g, b) { | |
return r + r + g + g + b + b; | |
}); | |
var result = __rgx_hex6.exec(hex); | |
return result ? [ | |
parseInt(result[1], 16), // red | |
parseInt(result[2], 16), // green | |
parseInt(result[3], 16), // blue | |
(alpha !== undefined && alpha !== null) ? parseFloat(alpha) : 1 | |
] : null; | |
} | |
/** | |
* Converts an HSVA color value to RGBA. | |
* | |
* Conversion formula adapted from http://de.wikipedia.org/wiki/HSV-Farbraum. | |
* | |
* @param {Array} Array.length === 4, with: | |
* [0] hue, {float 0-360} | |
* [1] saturation, {float 0-1} | |
* [2] value, {float 0-1} | |
* [3] alpha, {float 0-1} | |
* @return {Array|null} - Array.length === 4, with: | |
* [0] red, {number 0-255} | |
* [1] green, {number 0-255} | |
* [2] blue, {number 0-255} | |
* [3] alpha, {float 0-1} | |
*/ | |
function __hsva2rgba(hsva) { | |
var r, g, b; | |
var h = hsva[0], | |
s = hsva[1], | |
v = hsva[2]; | |
if(s === 0) { | |
r = g = b = v; | |
} else { | |
var i = Math.floor(h / 60); | |
var f = h / 60 - i; | |
var p = v * (1 - s); | |
var q = v * (1 - f * s); | |
var t = v * (1 - s * (1 - f)); | |
switch (i) { | |
case 0: | |
case 6: | |
r = v, g = t, b = p; | |
break; | |
case 1: | |
r = q, g = v, b = p; | |
break; | |
case 2: | |
r = p, g = v, b = t; | |
break; | |
case 3: | |
r = p, g = q, b = v; | |
break; | |
case 4: | |
r = t, g = p, b = v; | |
break; | |
case 5: | |
r = v, g = p, b = q; | |
break; | |
} | |
} | |
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), Math.round(hsva[3] * 1000) / 1000 ]; | |
} | |
/** | |
* Converts an RGBA color value to HSVA. | |
* | |
* Conversion formula adapted from http://de.wikipedia.org/wiki/HSV-Farbraum. | |
* | |
* @param {Array} rgba Array.length === 4, with: | |
* [0] red, {number 0-255} | |
* [1] green, {number 0-255} | |
* [2] blue, {number 0-255} | |
* [3] alpha, {float 0-1} | |
* @return {Array} Array.length === 4, with: | |
* [0] hue, {float 0-360} | |
* [1] saturation, {float 0-1} | |
* [2] value, {float 0-1} | |
* [3] alpha, {float 0-1} | |
*/ | |
function __rgba2hsva(rgba) { | |
var r = rgba[0]/255, | |
g = rgba[1]/255, | |
b = rgba[2]/255; | |
var max = Math.max(r, g, b); | |
var min = Math.min(r, g, b); | |
var delta = max - min; | |
var h = 0; | |
var s = max === 0 ? 0 : delta / max; | |
var v = max; | |
if (max === min) { | |
h = 0; // achromatic | |
} else { | |
switch (max) { | |
case r: h = (g < b ? 6 : 0) + (g - b) / delta; | |
break; | |
case g: h = 2 + (b - r) / delta; | |
break; | |
case b: h = 4 + (r - g) / delta; | |
break; | |
} | |
h *= 60; | |
} | |
return [ h, s, v, rgba[3] ]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment