rgb to hsl code example

Example: code to convert rgb to hsl color

// see: https://en.wikipedia.org/wiki/RGB_color_model
// see: https://en.wikipedia.org/wiki/HSL_and_HSV

// expects R, G, B, Cmax and chroma to be in number interval [0, 1]
// returns undefined if chroma is 0, or a number interval [0, 360] degrees
function hue(R, G, B, Cmax, chroma) {
  let H;
  if (chroma === 0) {
    return H;
  }
  if (Cmax === R) {
    H = ((G - B) / chroma) % 6;
  } else if (Cmax === G) {
    H = ((B - R) / chroma) + 2;
  } else if (Cmax === B) {
    H = ((R - G) / chroma) + 4;
  }
  H *= 60;
  return H < 0 ? H + 360 : H;
}

// returns the average of the supplied number arguments
function average(...theArgs) {
  return theArgs.length ? theArgs.reduce((p, c) => p + c, 0) / theArgs.length : 0;
}

// expects R, G, B, Cmin, Cmax and chroma to be in number interval [0, 1]
// type is by default 'bi-hexcone' equation
// set 'luma601' or 'luma709' for alternatives
// see: https://en.wikipedia.org/wiki/Luma_(video)
// returns a number interval [0, 1]
function lightness(R, G, B, Cmin, Cmax, type = 'bi-hexcone') {
  if (type === 'luma601') {
    return (0.299 * R) + (0.587 * G) + (0.114 * B);
  }
  if (type === 'luma709') {
    return (0.2126 * R) + (0.7152 * G) + (0.0772 * B);
  }
  return average(Cmin, Cmax);
}

// expects L and chroma to be in number interval [0, 1]
// returns a number interval [0, 1]
function saturation(L, chroma) {
  return chroma === 0 ? 0 : chroma / (1 - Math.abs(2 * L - 1));
}

// returns the value to a fixed number of digits
function toFixed(value, digits) {
  return Number.isFinite(value) && Number.isFinite(digits) ? value.toFixed(digits) : value;
}

// expects R, G, and B to be in number interval [0, 1]
// returns a Map of H, S and L in the appropriate interval and digits
function RGB2HSL(R, G, B, fixed = true) {
  const Cmin = Math.min(R, G, B);
  const Cmax = Math.max(R, G, B);
  const chroma = Cmax - Cmin;
  // default 'bi-hexcone' equation
  const L = lightness(R, G, B, Cmin, Cmax);
  // H in degrees interval [0, 360]
  // L and S in interval [0, 1]
  return new Map([
    ['H', toFixed(hue(R, G, B, Cmax, chroma), fixed && 1)],
    ['S', toFixed(saturation(L, chroma), fixed && 3)],
    ['L', toFixed(L, fixed && 3)]
  ]);
}

// expects value to be number in interval [0, 255]
// returns normalised value as a number interval [0, 1]
function colourRange(value) {
  return value / 255;
};

// expects R, G, and B to be in number interval [0, 255]
function RGBdec2HSL(R, G, B) {
  return RGB2HSL(colourRange(R), colourRange(G), colourRange(B));
}

// converts a hexidecimal string into a decimal number
function hex2dec(value) {
  return parseInt(value, 16);
}

// slices a string into an array of paired characters
function pairSlicer(value) {
  return value.match(/../g);
}

// prepend '0's to the start of a string and make specific length
function prePad(value, count) {
  return ('0'.repeat(count) + value).slice(-count);
}

// format hex pair string from value
function hexPair(value) {
  return hex2dec(prePad(value, 2));
}

// expects R, G, and B to be hex string in interval ['00', 'FF']
// without a leading '#' character
function RGBhex2HSL(R, G, B) {
  return RGBdec2HSL(hexPair(R), hexPair(G), hexPair(B));
}

// expects RGB to be a hex string in interval ['000000', 'FFFFFF']
// with or without a leading '#' character
function RGBstr2HSL(RGB) {
  const hex = prePad(RGB.charAt(0) === '#' ? RGB.slice(1) : RGB, 6);
  return RGBhex2HSL(...pairSlicer(hex).slice(0, 3));
}

// expects value to be a Map object
function logIt(value) {
  console.log(value);
  document.getElementById('out').textContent += JSON.stringify([...value]) + '\n';
};

logIt(RGBstr2HSL('000000'));
logIt(RGBstr2HSL('#808080'));
logIt(RGB2HSL(0, 0, 0));
logIt(RGB2HSL(1, 1, 1));
logIt(RGBdec2HSL(0, 0, 0));
logIt(RGBdec2HSL(255, 255, 254));
logIt(RGBhex2HSL('BF', 'BF', '00'));
logIt(RGBstr2HSL('008000'));
logIt(RGBstr2HSL('80FFFF'));
logIt(RGBstr2HSL('8080FF'));
logIt(RGBstr2HSL('BF40BF'));
logIt(RGBstr2HSL('A0A424'));
logIt(RGBstr2HSL('411BEA'));
logIt(RGBstr2HSL('1EAC41'));
logIt(RGBstr2HSL('F0C80E'));
logIt(RGBstr2HSL('B430E5'));
logIt(RGBstr2HSL('ED7651'));
logIt(RGBstr2HSL('FEF888'));
logIt(RGBstr2HSL('19CB97'));
logIt(RGBstr2HSL('362698'));
logIt(RGBstr2HSL('7E7EB8'));