color-rs
color-rs copied to clipboard
Consider a way to represent color spaces
We need a way to represent color spaces. It may be desirable to have color spaces defined independantly of color formats, ideally allowing us to have color types defined as a combination of channel type, color format and color space, such as:
// color channels
trait Channel { .. }
// color spaces
enum Linear {}
enum sRGB {}
trait ColorSpace { .. }
impl ColorSpace for Linear { .. }
impl ColorSpace for SRGB { .. }
// color formats
struct RGB<T: Channel, S: ColorSpace> { r: T, g: T, b: T }
// color types
trait Color<T: Channel, S: ColorSpace> { .. }
impl<T: Channel, S: ColorSpace> Color<T, S> for RGB<T, S> { .. }
// possible color types: RGB<u8, sRGB>, RGB<f32, Linear>, etc
However, this may not work well in practice since color spaces are often tied to their own color formats.
there is another color library that has them: retep998/colors-rs
also there’s rudimentary color structs in PistonDevelopers/image
I’d love to see this stuff unified! Maybe use this (colors, channels, alpha-channel) as a basis without much bloat and base both PistonDevelopers/image and a new color-conversion library on top of it.
gtaylor/python-colormath has pretty complete support of all this, we can use it as orientation (note gtaylor/python-colormath#43, though)
Here’s a small bit of python-colormath expressed in rust + japaric/linalg
use linalg::{Mat, RowVec};
pub trait Illuminant {
fn illuminant(self) -> RowVec<f32>;
}
#[derive(Copy,Show)]
pub enum Illuminants2 { A, B, C, D50, D55, D65, D75, E, F2, F7, F11 }
#[derive(Copy,Show)]
pub enum Illuminants10 { D50, D55, D65, D75 }
impl Illuminant for Illuminants2 {
fn illuminant(self) -> RowVec<f32> {
match self {
Illuminants2::A => mat![1.09850, 1., 0.35585],
Illuminants2::B => mat![0.99072, 1., 0.85223],
Illuminants2::C => mat![0.98074, 1., 1.18232],
Illuminants2::D50 => mat![0.96422, 1., 0.82521],
Illuminants2::D55 => mat![0.95682, 1., 0.92149],
Illuminants2::D65 => mat![0.95047, 1., 1.08883],
Illuminants2::D75 => mat![0.94972, 1., 1.22638],
Illuminants2::E => mat![1.00000, 1., 1.00000],
Illuminants2::F2 => mat![0.99186, 1., 0.67393],
Illuminants2::F7 => mat![0.95041, 1., 1.08747],
Illuminants2::F11 => mat![1.00962, 1., 0.64350],
}
}
}
impl Illuminant for Illuminants10 {
fn illuminant(self) -> RowVec<f32> {
match self {
Illuminants10::D50 => mat![0.96720, 1., 0.8143],
Illuminants10::D55 => mat![0.95800, 1., 0.9093],
Illuminants10::D65 => mat![0.94810, 1., 1.0730],
Illuminants10::D75 => mat![0.94416, 1., 1.2064],
}
}
}
#[derive(Copy,Show)]
pub enum AdaptionMatrices { XYZScaling, Bradford, VonKries }
impl AdaptionMatrices {
pub fn adaption_matrix(self) -> Mat<f32> {
match self {
AdaptionMatrices::XYZScaling => mat![
1.0, 0.0, 0.0;
0.0, 1.0, 0.0;
0.0, 0.0, 1.0;
],
AdaptionMatrices::Bradford => mat![
0.8951, 0.2664, -0.1614;
-0.7502, 1.7135, 0.0367;
0.0389, -0.0685, 1.0296;
],
AdaptionMatrices::VonKries => mat![
0.40024, 0.70760, -0.08081;
-0.22630, 1.16532, 0.04570;
0.00000, 0.00000, 0.91822;
],
}
}
}
I'll support any initiative to have a standard way of working with colors and colorspaces, as long as it is done well.
You're free to rip any code you want from colors-rs
.
do you have any opinions on #24?
Awesome! I am just finishing up a massive cleanup of noise-rs with the help of others, and I think it is well time for color-rs to get some love. I'll see what is in colors-rs and am happy to work with you to improve it.
since this is an info dump as well as an discussion: this project makes advanced use of color models (not in rust).
i think if we could elegantly support that use case, we’re set.