// Copyright 2020 Sergiusz 'q3k' Bazanski // // This file is part of Abrasion. // // Abrasion is free software: you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation, version 3. // // Abrasion is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more // details. // // You should have received a copy of the GNU General Public License along with // Abrasion. If not, see . #[derive(Copy, Clone, Debug)] pub struct XYZ { pub x: f32, pub y: f32, pub z: f32, } impl XYZ { pub fn new(x: f32, y: f32, z: f32) -> Self { Self { x, y, z, } } pub fn from_srgb(r: f32, g: f32, b: f32) -> Self { let (x, y, z) = srgb_to_cie_xyz(r, g, b); Self { x, y, z } } } #[derive(Debug)] pub struct LinearF32 { pub d: f32, } impl LinearF32 { pub fn new(d: f32) -> Self { Self { d, } } } /// Convert sRGB color space (in R8G8B8A8) to XYZ colorspace (floats). pub fn srgb_packed_to_cie_xyz(rgba: u32) -> (f32, f32, f32, f32) { // Unpack RGBA to R, G, B, A 0-255 values. let r = ((rgba >> 24) & 0xff) as f32; let g = ((rgba >> 16) & 0xff) as f32; let b = ((rgba >> 8 ) & 0xff) as f32; let a = ((rgba ) & 0xff) as f32; let r = r/255.0; let g = g/255.0; let b = b/255.0; let (x, y, z) = srgb_to_cie_xyz(r, g, b); (x, y, z, a) } /// Convert sRGB color space (floats) to XYZ colorspace (floats). /// The input are floats in the range 0-1.0. /// The output is a tuple of (X, Y, Z) floats. pub fn srgb_to_cie_xyz(r: f32, g: f32, b: f32) -> (f32, f32, f32) { assert!(r >= 0.0 && r <= 1.0); assert!(g >= 0.0 && g <= 1.0); assert!(b >= 0.0 && b <= 1.0); // Following DIN EN 61966-2-1:2003-09 // (which corresponds to IEC 61966-2-1:1999) // Equations (5) and (6) let eq56 = |v| { if v < 0.004045 { v / 12.92 } else { let v: f32 = (v + 0.055) / (1.055); v.powf(2.4) as f32 } }; let r = eq56(r); let g = eq56(g); let b = eq56(b); // Equation (7) // (unrolled matrix multiplication) let x = 0.4124 * r + 0.3576 * g + 0.1805 * b; let y = 0.2126 * r + 0.7152 * g + 0.0722 * b; let z = 0.0193 * r + 0.1192 * g + 0.9505 * b; (x, y , z) }