Skip to content

Instantly share code, notes, and snippets.

@eldh
Last active April 7, 2019 12:22
Show Gist options
  • Select an option

  • Save eldh/40f5b1dca4345d368097b6847ffcc4f6 to your computer and use it in GitHub Desktop.

Select an option

Save eldh/40f5b1dca4345d368097b6847ffcc4f6 to your computer and use it in GitHub Desktop.
LAB <-> RGB in Reason
exception InvalidValue(string);
let toInt = f => (f +. 0.5)->int_of_float;
module Constants = {
let kn = 18;
let xn = 0.950470;
let yn = 1.;
let zn = 1.088830;
let t0 = 0.137931034; // 4 / 29
let t1 = 0.206896552; // 6 / 29
let t2 = 0.12841855; // 3 * t1 * t1
let t3 = 0.008856452; // t1 * t1 * t1
};
let xyz_rgb = r => {
255. *. (r <= 0.00304 ? 12.92 *. r : 1.055 *. r ** (1. /. 2.4) -. 0.055);
};
let lab_xyz = t => {
t > Constants.t1 ? t *. t *. t : Constants.t2 *. (t -. Constants.t0);
};
let toRGB = lab => {
let (l, a, b, alpha) = lab;
let y0 = (l +. 16.) /. 116.;
let x0 = y0 +. a /. 500.;
let z0 = y0 -. b /. 200.;
let y = Constants.yn *. lab_xyz(y0);
let x = Constants.xn *. lab_xyz(x0);
let z = Constants.zn *. lab_xyz(z0);
let r = xyz_rgb(3.2404542 *. x -. 1.5371385 *. y -. 0.4985314 *. z); // D65 -> sRGB
let g = xyz_rgb((-0.9692660) *. x +. 1.8760108 *. y +. 0.0415560 *. z);
let b_ = xyz_rgb(0.0556434 *. x -. 0.2040259 *. y +. 1.0572252 *. z);
(r->toInt, g->toInt, b_->toInt, alpha);
};
let toCssRGB = t => {
let (r, g, b, a) = toRGB(t);
Css.rgba(r, g, b, a);
};
let rgb_xyz = r => {
let r2 = r /. 255.;
if (r2 <= 0.04045) {
r2 /. 12.92;
} else {
((r2 +. 0.055) /. 1.055) ** 2.4;
};
};
let xyz_lab = t =>
if (t > Constants.t3) {
t ** (1. /. 3.);
} else {
t /. Constants.t2 +. Constants.t0;
};
let rgb2xyz = (r_, g_, b_) => {
let r = rgb_xyz(r_->float_of_int);
let g = rgb_xyz(g_->float_of_int);
let b = rgb_xyz(b_->float_of_int);
let x =
xyz_lab(
(0.4124564 *. r +. 0.3575761 *. g +. 0.1804375 *. b) /. Constants.xn,
);
let y =
xyz_lab(
(0.2126729 *. r +. 0.7151522 *. g +. 0.0721750 *. b) /. Constants.yn,
);
let z =
xyz_lab(
(0.0193339 *. r +. 0.1191920 *. g +. 0.9503041 *. b) /. Constants.zn,
);
(x, y, z);
};
let fromRGB = ((r, g, b, alpha)) => {
let (x, y, z) = rgb2xyz(r, g, b);
let l = 116. *. y -. 16.;
(l < 0. ? 0. : l, 500. *. (x -. y), 200. *. (y -. z), alpha);
};
let fromCssRGB = rgb => {
switch (rgb) {
| `rgb(r, g, b) => fromRGB((r, g, b, 1.))
| `rgba(r, g, b, a) => fromRGB((r, g, b, a))
| _ => raise(InvalidValue("Not an rgb value"))
};
};
@leostera
Copy link
Copy Markdown

leostera commented Apr 7, 2019

Do you need the catch all here? The signature should be automatically constrained to the two poly variants you are switching on.

@eldh
Copy link
Copy Markdown
Author

eldh commented Apr 7, 2019

If it's coming from bs-css it might have a different type, I think.

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