Skip to content

Instantly share code, notes, and snippets.

@stephencweiss
Last active December 26, 2018 16:24
Show Gist options
  • Save stephencweiss/eab510dabb2ba50652434372e46b5980 to your computer and use it in GitHub Desktop.
Save stephencweiss/eab510dabb2ba50652434372e46b5980 to your computer and use it in GitHub Desktop.
Color conversion algorithms for HSV, HSL, and RGB in Javascript
/**
* This gist covers the conversion of color values.
* It includes:
* 1) hsvFromRGB
* 2) rgbFromHSV
* 3) hslFromRGB
* 4) rgbFromHSL
* 5) hexFromRGB
* 6) rgbFromHex
*
* The primary inspiration for this was the work done by https://gist.github.com/mjackson/5311256
* Source I found helpful for understanding the details and deriving the values include:
* [Wikipedia: HSL and HSV](https://en.wikipedia.org/wiki/HSL_and_HSV)
* [CS StackExchange: Convert HSV to RGB Colors](https://cs.stackexchange.com/questions/64549/convert-hsv-to-rgb-colors)
* [Rapid Tables](https://www.rapidtables.com/)
* [MDN: parseInt()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt)
* [MDN: toString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toString)
*/
function hsvFromRGB(r, g, b) {
/**
* I: Three arguments, red (r), green (g), blue (b), all ∈ [0, 255]
* O: An array of three elements hue (h) ∈ [0, 360], and saturation (s) and value (v) which are both ∈ [0, 1]
*/
r /= 255, g /= 255, b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const diff = max - min;
let h, s;
// Value
const v = max;
// Saturation
s = (max === 0) ? 0 : (diff / max);
// Hue
if (diff === 0) {
h = 0;
} else {
// 1/6 is equivalent to 60 degrees
if (max === r) { h = 1/6 * (0 + ((g - b) / diff)) };
if (max === g) { h = 1/6 * (2 + ((b - r) / diff)) };
if (max === b) { h = 1/6 * (4 + ((r - g) / diff)) };
}
h = Math.round(h * 360)
return [h, s, v];
}
function rgbFromHSV(h, s, v) {
/**
* I: Three elements hue (h) ∈ [0, 360], and saturation (s) and value (v) which are both ∈ [0, 1]
* O: An array of red (r), green (g), blue (b), all ∈ [0, 255]
*/
hprime = h / 60;
const c = v * s;
const x = c * (1 - Math.abs(hprime % 2 - 1));
const m = v - c;
let rPrime, gPrime, bPrime;
if (!hprime) {rPrime = 0; gPrime = 0; bPrime = 0; }
if (hprime >= 0 && hprime < 1) { rPrime = c; gPrime = x; bPrime = 0}
if (hprime >= 1 && hprime < 2) { rPrime = x; gPrime = c; bPrime = 0}
if (hprime >= 2 && hprime < 3) { rPrime = 0; gPrime = c; bPrime = x}
if (hprime >= 3 && hprime < 4) { rPrime = 0; gPrime = x; bPrime = c}
if (hprime >= 4 && hprime < 5) { rPrime = x; gPrime = 0; bPrime = c}
if (hprime >= 5 && hprime < 6) { rPrime = c; gPrime = 0; bPrime = x}
const r = Math.round( (rPrime + m)* 255);
const g = Math.round( (gPrime + m)* 255);
const b = Math.round( (bPrime + m)* 255);
return [r, g, b]
}
function rgbFromHSL(h, s, l) {
/**
* I: Three elements hue (h) ∈ [0, 360], and saturation (s) and lightness (l) which are both ∈ [0, 1]
* O: An array of red (r), green (g), blue (b), all ∈ [0, 255]
*/
const hprime = h / 60;
const c = (1 - Math.abs(2 * l - 1)) * s;
const x = c * (1 - Math.abs((hprime % 2) - 1));
const m = l - (c / 2);
let rPrime, gPrime, bPrime;
if (h >= 0 && h < 60) { rPrime = c; gPrime = x; bPrime = 0}
if (h >= 60 && h < 120) { rPrime = x; gPrime = c; bPrime = 0}
if (h >= 120 && h < 180) { rPrime = 0; gPrime = c; bPrime = x}
if (h >= 180 && h < 240) { rPrime = 0; gPrime = x; bPrime = c}
if (h >= 240 && h < 300) { rPrime = x; gPrime = 0; bPrime = c}
if (h >= 300 && h < 360) { rPrime = c; gPrime = 0; bPrime = x}
const r = Math.round( (rPrime + m)* 255);
const g = Math.round( (gPrime + m)* 255);
const b = Math.round( (bPrime + m)* 255);
return [r, g, b]
}
function hslFromRGB(r, g, b) {
/**
* I: Three arguments, red (r), green (g), blue (b), all ∈ [0, 255]
* O: An array of three elements hue (h) ∈ [0, 360], and saturation (s) and lightness (l) which are both ∈ [0, 1]
*/
r /= 255, g /= 255, b /= 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const diff = max - min;
let h, s;
//Lightness
const l = (max + min) / 2;
//Saturation
s = (diff === 0) ? 0 : diff / (1 - Math.abs((2 * l) - 1));;
//Hue
if (diff === 0) {
h = 0;
} else {
// 1/6 is equivalent to 60 degrees
if (max === r) { h = 1/6 * (0 + ((g - b) / diff)) };
if (max === g) { h = 1/6 * (2 + ((b - r) / diff)) };
if (max === b) { h = 1/6 * (4 + ((r - g) / diff)) };
}
h = Math.round(h * 360)
return [h, s, l];
}
function baseTenToHex(c) {
/**
* I: A number
* O: A string representation of the number in base 16
*/
let hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
function hexFromRGB(r, g, b) {
/**
* I: Three arguments, red (r), green (g), blue (b), all ∈ [0, 255]
* O: A hexidecimal representation of the three numbers, concatenated as one string.
*/
return "#" + baseTenToHex(r) + baseTenToHex(g) + baseTenToHex(b);
}
function baseHexToTen(c) {
/**
* I: A string of a number in base 16
* O: A number representation of the string in base 10
*/
return parseInt(c, 16)
}
function rgbFromHex(hexValue) {
/**
* I: A single hexidecimal value (without a leading `#`);
* O: An array of red (r), green (g), blue (b), all ∈ [0, 255]
*/
debugger;
const r = baseHexToTen(hexValue.slice(0, 2))
const g = baseHexToTen(hexValue.slice(2, 4))
const b = baseHexToTen(hexValue.slice(4, 6))
return [r, g, b]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment