Last active
March 22, 2020 07:31
-
-
Save btd/702da3372f1424c1f7f9862b4166c87e to your computer and use it in GitHub Desktop.
Color space conversions, RGB, XYZ, CIE Lab
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class RGB { | |
constructor(r, g, b, a) { | |
this.r = r; | |
this.g = g; | |
this.b = b; | |
this.a = a; | |
} | |
} | |
function pivotRgb(n) { | |
return (n > 0.04045 ? Math.pow((n + 0.055) / 1.055, 2.4) : n / 12.92) * 100.0; | |
} | |
export function RGBtoXYZ(color) { | |
let r = pivotRgb(color.r / 255.0); | |
let g = pivotRgb(color.g / 255.0); | |
let b = pivotRgb(color.b / 255.0); | |
// Observer. = 2°, Illuminant = D65 | |
let x = r * 0.4124 + g * 0.3576 + b * 0.1805; | |
let y = r * 0.2126 + g * 0.7152 + b * 0.0722; | |
let z = r * 0.0193 + g * 0.1192 + b * 0.9505; | |
return new XYZ(x, y, z); | |
} | |
export class XYZ { | |
constructor(x, y, z) { | |
this.x = x; | |
this.y = y; | |
this.z = z; | |
} | |
} | |
const EPS = 0.008856; // Intent is 216/24389 | |
const KAPPA = 903.3; // Intent is 24389/27 | |
function cubicRoot(n) { | |
return Math.pow(n, 1.0 / 3.0); | |
} | |
function pivotXyz(n) { | |
return n > EPS ? cubicRoot(n) : (KAPPA * n + 16) / 116; | |
} | |
const whiteXYZ = new XYZ( | |
95.047, | |
100.000, | |
108.883 | |
); | |
export function XYZtoCIELAB(color) { | |
let x = pivotXyz(color.x / whiteXYZ.x); | |
let y = pivotXyz(color.y / whiteXYZ.y); | |
let z = pivotXyz(color.z / whiteXYZ.z); | |
let L = Math.max(0, 116 * y - 16); | |
let a = 500 * (x - y); | |
let b = 200 * (y - z); | |
return new Lab(L, a, b); | |
} | |
export function RGBtoCIELAB(color) { | |
return XYZtoCIELAB(RGBtoXYZ(color)); | |
} | |
export class Lab { | |
constructor(L, a, b) { | |
this.L = L; | |
this.a = a; | |
this.b = b; | |
} | |
// deltaE | |
delta(color) { | |
let dL = this.L - color.L; | |
let C1 = Math.sqrt(this.a * this.a + this.b * this.b); | |
let C2 = Math.sqrt(color.a * color.a + color.b * color.b); | |
let dC = C1 - C2; | |
let da = this.a - color.a; | |
let db = this.b - color.b; | |
let dH = Math.sqrt(da * da + db * db - dC * dC); | |
const kL = 1; | |
const K1 = 0.045; | |
const K2 = 0.015; | |
const kC = 1; | |
const kH = 1; | |
let SL = 1; | |
let SC = 1 + K1 * C1; | |
let SH = 1 + K2 * C1; | |
return Math.sqrt( | |
Math.pow(dL/(kL*SL), 2) + | |
Math.pow(dC/(kC*SC), 2) + | |
Math.pow(dH/(kH*SH), 2) | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment