use crate::ColorModel;
use crate::chan::{
Ch8, Ch16, Ch32, Channel, Linear, Premultiplied, Srgb, Straight,
};
use crate::el::{Pix, PixRgba, Pixel};
use std::ops::Range;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Cmy {}
impl Cmy {
pub fn cyan<P>(p: P) -> P::Chan
where
P: Pixel<Model = Self>,
{
p.get::<0>()
}
pub fn cyan_mut<P>(p: &mut P) -> &mut P::Chan
where
P: Pixel<Model = Self>,
{
p.get_mut::<0>()
}
pub fn magenta<P>(p: P) -> P::Chan
where
P: Pixel<Model = Self>,
{
p.get::<1>()
}
pub fn magenta_mut<P>(p: &mut P) -> &mut P::Chan
where
P: Pixel<Model = Self>,
{
p.get_mut::<1>()
}
pub fn yellow<P>(p: P) -> P::Chan
where
P: Pixel<Model = Self>,
{
p.get::<2>()
}
pub fn yellow_mut<P>(p: &mut P) -> &mut P::Chan
where
P: Pixel<Model = Self>,
{
p.get_mut::<2>()
}
}
impl ColorModel for Cmy {
const CIRCULAR: Range<usize> = 0..0;
const LINEAR: Range<usize> = 0..3;
const ALPHA: usize = 3;
fn into_rgba<P>(p: P) -> PixRgba<P>
where
P: Pixel<Model = Self>,
{
let red = P::Chan::MAX - Cmy::cyan(p);
let green = P::Chan::MAX - Cmy::magenta(p);
let blue = P::Chan::MAX - Cmy::yellow(p);
PixRgba::<P>::new::<P::Chan>(red, green, blue, p.alpha())
}
fn from_rgba<P>(rgba: PixRgba<P>) -> P
where
P: Pixel<Model = Self>,
{
let chan = rgba.channels();
let cyan = P::Chan::MAX - chan[0];
let magenta = P::Chan::MAX - chan[1];
let yellow = P::Chan::MAX - chan[2];
let alpha = chan[3];
P::from_channels(&[cyan, magenta, yellow, alpha])
}
}
pub type Cmy8 = Pix<3, Ch8, Cmy, Straight, Linear>;
pub type Cmy16 = Pix<3, Ch16, Cmy, Straight, Linear>;
pub type Cmy32 = Pix<3, Ch32, Cmy, Straight, Linear>;
pub type Cmya8 = Pix<4, Ch8, Cmy, Straight, Linear>;
pub type Cmya16 = Pix<4, Ch16, Cmy, Straight, Linear>;
pub type Cmya32 = Pix<4, Ch32, Cmy, Straight, Linear>;
pub type Cmya8p = Pix<4, Ch8, Cmy, Premultiplied, Linear>;
pub type Cmya16p = Pix<4, Ch16, Cmy, Premultiplied, Linear>;
pub type Cmya32p = Pix<4, Ch32, Cmy, Premultiplied, Linear>;
pub type SCmy8 = Pix<3, Ch8, Cmy, Straight, Srgb>;
pub type SCmy16 = Pix<3, Ch16, Cmy, Straight, Srgb>;
pub type SCmy32 = Pix<3, Ch32, Cmy, Straight, Srgb>;
pub type SCmya8 = Pix<4, Ch8, Cmy, Straight, Srgb>;
pub type SCmya16 = Pix<4, Ch16, Cmy, Straight, Srgb>;
pub type SCmya32 = Pix<4, Ch32, Cmy, Straight, Srgb>;
pub type SCmya8p = Pix<4, Ch8, Cmy, Premultiplied, Srgb>;
pub type SCmya16p = Pix<4, Ch16, Cmy, Premultiplied, Srgb>;
pub type SCmya32p = Pix<4, Ch32, Cmy, Premultiplied, Srgb>;
#[cfg(test)]
mod test {
use crate::cmy::*;
use crate::el::Pixel;
use crate::rgb::*;
#[test]
fn cmy_to_rgb() {
assert_eq!(Rgb8::new(255, 1, 2), Cmy8::new(0, 254, 253).convert());
assert_eq!(Rgb8::new(255, 255, 0), Cmy32::new(0.0, 0.0, 1.0).convert(),);
assert_eq!(Rgb8::new(0, 0, 255), Cmy16::new(65535, 65535, 0).convert(),);
}
#[test]
fn rgb_to_cmy() {
assert_eq!(Cmy8::new(0, 255, 127), Rgb8::new(255, 0, 128).convert());
assert_eq!(Cmy32::new(1.0, 0.0, 0.0), Rgb8::new(0, 255, 255).convert(),);
assert_eq!(Cmy16::new(0, 65535, 65535), Rgb8::new(255, 0, 0).convert(),);
}
}