RGB to HSL and RGB to HSV color model conversion algorithms in JavaScript
Here is a set of additive color model conversion algorithms that I found published on Wikipedia and have implemented in JavaScript. It was surprisingly difficult to find these actually implemented anywhere in compact, efficient, and bug-free code, so I wrote my own. These should be easily portable to other programming languages if desired.
/**
* Converts an RGB color value to HSL. Conversion formula adapted from
* http://en.wikipedia.org/wiki/HSL_color_space. Assumes r, g, and b are
* contained in the set [0, 255] and returns h, s, and l in the set [0, 1].
*
* @param {Number} r The red color value
* @param {Number} g The green color value
* @param {Number} b The blue color value
* @return {Array} The HSL representation
*/
var rgbToHsl = function(r, g, b){
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if(max == min){
h = s = 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;
}
h /= 6;
}
return [h, s, l];
};
/**
* Converts an HSL color value to RGB. Conversion formula adapted from
* http://en.wikipedia.org/wiki/HSL_color_space. Assumes h, s, and l are
* contained in the set [0, 1] and returns r, g, and b in the set [0, 255].
*
* @param {Number} h The hue
* @param {Number} s The saturation
* @param {Number} l The lightness
* @return {Array} The RGB representation
*/
var hslToRgb = function(h, s, l){
var r, g, b;
if(s == 0){
r = g = b = l; // achromatic
}else{
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;
};
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 * 255, g * 255, b * 255];
};
/**
* Converts an RGB color value to HSV. Conversion formula adapted from
* http://en.wikipedia.org/wiki/HSV_color_space. Assumes r, g, and b are
* contained in the set [0, 255] and returns h, s, and v in the set [0, 1].
*
* @param {Number} r The red color value
* @param {Number} g The green color value
* @param {Number} b The blue color value
* @return {Array} The HSV representation
*/
var rgbToHsv = function(r, g, b){
r = r/255, g = g/255, b = b/255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, v = max;
var d = max - min;
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;
}
h /= 6;
}
return [h, s, v];
};
/**
* Converts an HSV color value to RGB. Conversion formula adapted from
* http://en.wikipedia.org/wiki/HSV_color_space. Assumes h, s, and v are
* contained in the set [0, 1] and returns r, g, and b in the set [0, 255].
*
* @param {Number} h The hue
* @param {Number} s The saturation
* @param {Number} v The value
* @return {Array} The RGB representation
*/
var hsvToRgb = function(h, s, v){
var r, g, b;
var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
switch(i){
case 0: 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 [r * 255, g * 255, b * 255];
};

If you want to get serious, use the LCh color space instead. The HSL/HSB model does not have much physiological basis. Not important for casual use.
@emre: I’ll have to check that out. Mostly, I just wanted to be able to manipulate colors for the web. Since [CSS3][1] will accept RGB, hex, and HSL, I figured I would stick with those for the present time.
[1]: http://www.w3.org/TR/css3-color/ “CSS3 color module”
I really do appreciate your work, thank you very much for sharing.
In the rgbToHsl line
s = l > 0.5 ? d / (2 - max - min) : d / (max (PLUS) min);The
(2 - max - min)should be(2 - max (PLUS) min).(The preview isn’t showing plus signs, so I just wrote them in.)
Also, for rgbToHsl, shouldn’t you include
h*=360;s*=100;l*=100;before the return statement? Personally, I would also Math.round() each of those.
@Gyrobo: The color conversion algorithms are taken directly from the Wikipedia. In that source, the correct signs are
2 - (max + min)This of course translates to
2 - max - minAs far as your second comment is concerned, the function comment clearly states that the HSL values are returned on [0,1]. This makes sense because the inverse function (hslToRgb) likewise expects those values on the same interval.
Hi, nice work…! i’ve spent ages searching for good straight-forward calculations that would help me produce my own “colour” code. Mainly because, as you’ve said, any code i have found has been hideous in either stature (huge), cleverness (complexity) or unexpected features (bugs).. up until now i had failed entirely to get hold of anything that suited my needs..
Thanks a lot.. really appreciated.. if you have any stipulations for usage please let me know. I do however always mention sources with-in my creations if i have utilised anyone elses code.
While trawling for an RGB to HSV solution I stumbled across your code. I’ve written colour modelling code before so knew what I was aiming for, I just wanted a head start. Having put some code together I noticed one issue you might be interested in. The hsvToRgb() method needs to use
switch(i%6)otherwise it’ll go wrong whenhis 1. This modules is in wikipidia’s formula but has gone astray in your code.I came up with a Colour class to supply the behaviour. I was going to include my code but it wouldn’t fit so here’s an extract. Adding 360 (6 in you case) prevents the hue from going negative…
Cheers