Skip to content

Instantly share code, notes, and snippets.

@tlindig
Last active November 21, 2016 16:24
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tlindig/9392075 to your computer and use it in GitHub Desktop.
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.
/*!
* 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