Skip to content

Instantly share code, notes, and snippets.

@emilk
Created January 21, 2021 09:45
Show Gist options
  • Select an option

  • Save emilk/68a753df82771eaef5168beac1a5f835 to your computer and use it in GitHub Desktop.

Select an option

Save emilk/68a753df82771eaef5168beac1a5f835 to your computer and use it in GitHub Desktop.

Revisions

  1. emilk created this gist Jan 21, 2021.
    62 changes: 62 additions & 0 deletions oklab.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,62 @@
    //! https://bottosson.github.io/posts/oklab/
    /// oklab from linear rgb (0-1 ranges)
    pub fn lab_from_rgb([r, g, b]: [f32; 3]) -> (f32, f32, f32) {
    let x = 0.4121656120 * r + 0.5362752080 * g + 0.0514575653 * b;
    let y = 0.2118591070 * r + 0.6807189584 * g + 0.1074065790 * b;
    let z = 0.0883097947 * r + 0.2818474174 * g + 0.6302613616 * b;

    let x = x.cbrt();
    let y = y.cbrt();
    let z = z.cbrt();

    (
    0.2104542553 * x + 0.7936177850 * y - 0.0040720468 * z,
    1.9779984951 * x - 2.4285922050 * y + 0.4505937099 * z,
    0.0259040371 * x + 0.7827717662 * y - 0.8086757660 * z,
    )
    }

    /// linear rgb from oklab (0-1 ranges)
    pub fn rgb_from_lab((l, a, b): (f32, f32, f32)) -> [f32; 3] {
    let x = l + 0.3963377774 * a + 0.2158037573 * b;
    let y = l - 0.1055613458 * a - 0.0638541728 * b;
    let z = l - 0.0894841775 * a - 1.2914855480 * b;

    let x = x.powi(3);
    let y = y.powi(3);
    let z = z.powi(3);

    [
    4.0767245293 * x - 3.3072168827 * y + 0.2307590544 * z,
    -1.2681437731 * x + 2.6093323231 * y - 0.3411344290 * z,
    -0.0041119885 * x - 0.7034763098 * y + 1.7068625689 * z,
    ]
    }

    /// 0-1 normalized lch from oklab.
    pub fn lch_from_lab((l, a, b): (f32, f32, f32)) -> (f32, f32, f32) {
    use std::f32::consts::TAU;
    let c = a.hypot(b);
    let h = (b.atan2(a) + TAU) % TAU / TAU;
    (l, c, h)
    }

    /// Oklab from 0-1 normalized lch.
    pub fn lab_from_lch((l, c, h): (f32, f32, f32)) -> (f32, f32, f32) {
    use std::f32::consts::TAU;
    let (sin_h, cos_h) = (h * TAU).sin_cos();
    let a = c * cos_h;
    let b = c * sin_h;
    (l, a, b)
    }

    /// 0-1 normalized lch from linear rgb
    pub fn lch_from_rgb(rgb: [f32; 3]) -> (f32, f32, f32) {
    lch_from_lab(lab_from_rgb(rgb))
    }

    /// linear rgb from 0-1 normalized lch
    pub fn rgb_from_lch(lch: (f32, f32, f32)) -> [f32; 3] {
    rgb_from_lab(lab_from_lch(lch))
    }