All files / Rindu/utils rgbToOklch.ts

94.44% Statements 17/18
33.33% Branches 1/3
100% Functions 6/6
100% Lines 17/17

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69  12x 12x               4x                       4x                       4x                       4x 4x 4x   4x     8x         4x 4x 4x   4x 4x 4x   4x    
function srgbToLinear(channel: number): number {
  const c = channel / 255;
  return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
}
 
function rgbToLms(
  r: number,
  g: number,
  b: number
): { l: number; m: number; s: number } {
  return {
    l: 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b,
    m: 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b,
    s: 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b,
  };
}
 
function lmsToCubeRoot(lms: { l: number; m: number; s: number }): {
  l_: number;
  m_: number;
  s_: number;
} {
  return {
    l_: Math.cbrt(lms.l),
    m_: Math.cbrt(lms.m),
    s_: Math.cbrt(lms.s),
  };
}
 
function cubeRootLmsToOklab(lms: { l_: number; m_: number; s_: number }): {
  L: number;
  A: number;
  B: number;
} {
  return {
    L: 0.2104542553 * lms.l_ + 0.793617785 * lms.m_ - 0.0040720468 * lms.s_,
    A: 1.9779984951 * lms.l_ - 2.428592205 * lms.m_ + 0.4505937099 * lms.s_,
    B: 0.0259040371 * lms.l_ + 0.7827717662 * lms.m_ - 0.808675766 * lms.s_,
  };
}
 
function oklabToOklch(lab: { L: number; A: number; B: number }): {
  l: number;
  c: number;
  h: number;
} {
  const C = Math.sqrt(lab.A * lab.A + lab.B * lab.B);
  let H = Math.atan2(lab.B, lab.A) * (180 / Math.PI);
  Iif (H < 0) H += 360;
 
  return { l: lab.L, c: C, h: H };
}
 
export function rgbToOklch(
  r: number,
  g: number,
  b: number
): { l: number; c: number; h: number } {
  const linearR = srgbToLinear(r);
  const linearG = srgbToLinear(g);
  const linearB = srgbToLinear(b);
 
  const lms = rgbToLms(linearR, linearG, linearB);
  const lmsCube = lmsToCubeRoot(lms);
  const oklab = cubeRootLmsToOklab(lmsCube);
 
  return oklabToOklch(oklab);
}