Skip to content

Instantly share code, notes, and snippets.

@vahidk
Last active January 10, 2024 13:36
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save vahidk/05184faf3d92a0aa1b46aeaa93b07786 to your computer and use it in GitHub Desktop.
Save vahidk/05184faf3d92a0aa1b46aeaa93b07786 to your computer and use it in GitHub Desktop.
Convert RGB to HSL and vice versa in Javascript.
// This code is based on https://en.wikipedia.org/wiki/HSL_and_HSV
// Free to use for any purpose. No attribution needed.
function rgbToHsl(r, g, b) {
r /= 255; g /= 255; b /= 255;
let max = Math.max(r, g, b);
let min = Math.min(r, g, b);
let d = max - min;
let h;
if (d === 0) h = 0;
else if (max === r) h = (g - b) / d % 6;
else if (max === g) h = (b - r) / d + 2;
else if (max === b) h = (r - g) / d + 4;
let l = (min + max) / 2;
let s = d === 0 ? 0 : d / (1 - Math.abs(2 * l - 1));
return [h * 60, s, l];
}
function hslToRgb(h, s, l) {
let c = (1 - Math.abs(2 * l - 1)) * s;
let hp = h / 60.0;
let x = c * (1 - Math.abs((hp % 2) - 1));
let rgb1;
if (isNaN(h)) rgb1 = [0, 0, 0];
else if (hp <= 1) rgb1 = [c, x, 0];
else if (hp <= 2) rgb1 = [x, c, 0];
else if (hp <= 3) rgb1 = [0, c, x];
else if (hp <= 4) rgb1 = [0, x, c];
else if (hp <= 5) rgb1 = [x, 0, c];
else if (hp <= 6) rgb1 = [c, 0, x];
let m = l - c * 0.5;
return [
Math.round(255 * (rgb1[0] + m)),
Math.round(255 * (rgb1[1] + m)),
Math.round(255 * (rgb1[2] + m))];
}
@rvaiya
Copy link

rvaiya commented Dec 11, 2020

Thanks, this snippet spared me some toil :P. I believe that

  else if (max === r) h = (g - b) / d % 6;

should be

  else if (max === r) h = ((((g - b) / d) % 6)+6)%6;

since the javascript modulo operator handles negative numbers differently than most other languages (The code breaks on some edge cases without it).

@brumasribera
Copy link

This worked for me like a charm :)

type HslType = { h: number; s: number; l: number }

const hslToRgb = (hsl: HslType): RgbType => {
  let { h, s, l } = hsl

  // IMPORTANT if s and l between 0,1 remove the next two lines:
  s /= 100
  l /= 100

  const k = (n: number) => (n + h / 30) % 12
  const a = s * Math.min(l, 1 - l)
  const f = (n: number) =>
    l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))
  return {
    r: Math.round(255 * f(0)),
    g: Math.round(255 * f(8)),
    b: Math.round(255 * f(4)),
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment