Skip to content

Commit

Permalink
remove halley in computeMaxSaturation
Browse files Browse the repository at this point in the history
  • Loading branch information
uffoltzl committed Nov 24, 2023
1 parent d5eaa52 commit eef941d
Showing 1 changed file with 17 additions and 60 deletions.
77 changes: 17 additions & 60 deletions src/gamut/rgb/oklab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,76 +113,33 @@ export abstract class OkLabInterpolateGamutMapping extends OkLabGamutMapping {
// Max saturation will be when one of r, g or b goes below zero.

// Select different coefficients depending on which component goes below zero first
let k0: number, k1: number, k2: number, k3: number, k4: number, wl: number, wm: number, ws: number;
let k0: number, k1: number, k2: number, k3: number, k4: number;

if (-1.8817030993265862 * a - 0.8093650129914288 * b > 1) {
// Red component goes under zero first
k0 = +1.4324033467840624;
k1 = +2.2781278435823524;
k2 = +0.7618497882679983;
k3 = +1.0260341945433478;
k4 = +0.7617909881094428;
wl = +4.0767416360759592;
wm = -3.3077115392580625;
ws = +0.2309699031821046;
k0 = +0.94190725;
k1 = +1.25611386;
k2 = +0.41951247;
k3 = +0.49514579;
k4 = +0.36308792;
} else if (1.8144407988011 * a - 1.1944526678052367 * b > 1) {
// Green component goes under zero first
k0 = +0.7379402524434013;
k1 = -0.4573974268862046;
k2 = +0.0815143817557270;
k3 = +0.1248577516844205;
k4 = -0.1434403763698065;
wl = -1.2684379732850315;
wm = +2.6097573492876882;
ws = -0.3413193760026572;
k0 = +0.73601075;
k1 = -0.44740025;
k2 = +0.08048903;
k3 = +0.11651011;
k4 = -0.14055292;
} else {
// Blue component goes under zero first
k0 = +1.3195478056858045;
k1 = -0.0002163824563852;
k2 = -1.1134545687345891;
k3 = -0.4851285430136246;
k4 = -0.0035353711153529;
wl = -0.0041960761386755;
wm = -0.7034186179359361;
ws = +1.7076146940746113;
k0 = +1.2373596;
k1 = -0.00419136;
k2 = -1.03212593;
k3 = -0.4339162;
k4 = +0.00108953;
}

// Approximate max saturation using a polynomial
let maxSaturation = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;

// Do one step Halley's method to get closer
// this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite
// this should be sufficient for most applications, otherwise do two/three steps

let k_l = +0.3963377773761749 * a + 0.2158037573099136 * b;
let k_m = -0.1055613458156586 * a - 0.0638541728258133 * b;
let k_s = -0.0894841775298119 * a - 1.2914855480194092 * b;

const halleyStep = () => {
let l_ = 1 + maxSaturation * k_l;
let m_ = 1 + maxSaturation * k_m;
let s_ = 1 + maxSaturation * k_s;

let l = l_ ** 3;
let m = m_ ** 3;
let s = s_ ** 3;

let l_dS = 3 * k_l * l_ * l_;
let m_dS = 3 * k_m * m_ * m_;
let s_dS = 3 * k_s * s_ * s_;

let l_dS2 = 6 * k_l * k_l * l_;
let m_dS2 = 6 * k_m * k_m * m_;
let s_dS2 = 6 * k_s * k_s * s_;

let f = wl * l + wm * m + ws * s;
let f_dS = wl * l_dS + wm * m_dS + ws * s_dS;
let f_dS2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2;

maxSaturation = maxSaturation - (f * f_dS) / (f_dS * f_dS - 0.5 * f * f_dS2);
};

repeat(halleyStep, OkLabInterpolateGamutMapping.HALLEY_STEPS_NB);
const maxSaturation = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;

return maxSaturation;
}
Expand Down

0 comments on commit eef941d

Please sign in to comment.