use crate::ColorModel;
use crate::chan::{Ch8, Ch16, Ch32, Channel, Linear, Premultiplied, Straight};
use crate::el::{Pix, PixRgba, Pixel};
use std::ops::Range;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct YCbCr {}
impl YCbCr {
pub fn y<P>(p: P) -> P::Chan
where
P: Pixel<Model = Self>,
{
p.get::<0>()
}
pub fn y_mut<P>(p: &mut P) -> &mut P::Chan
where
P: Pixel<Model = Self>,
{
p.get_mut::<0>()
}
pub fn cb<P>(p: P) -> P::Chan
where
P: Pixel<Model = Self>,
{
p.get::<1>()
}
pub fn cb_mut<P>(p: &mut P) -> &mut P::Chan
where
P: Pixel<Model = Self>,
{
p.get_mut::<1>()
}
pub fn cr<P>(p: P) -> P::Chan
where
P: Pixel<Model = Self>,
{
p.get::<2>()
}
pub fn cr_mut<P>(p: &mut P) -> &mut P::Chan
where
P: Pixel<Model = Self>,
{
p.get_mut::<2>()
}
}
impl ColorModel for YCbCr {
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 y = Self::y(p).to_f32();
let cb = Self::cb(p).to_f32();
let cr = Self::cr(p).to_f32();
let red = y + (cr - 0.5) * 1.402;
let green = y - (cb - 0.5) * 0.344_136 - (cr - 0.5) * 0.714_136;
let blue = y + (cb - 0.5) * 1.772;
PixRgba::<P>::new(red, green, blue, p.alpha().to_f32())
}
fn from_rgba<P>(rgba: PixRgba<P>) -> P
where
P: Pixel<Model = Self>,
{
let chan = rgba.channels();
let red = chan[0].to_f32();
let green = chan[1].to_f32();
let blue = chan[2].to_f32();
let alpha = chan[3];
let y = (0.299 * red) + (0.587 * green) + (0.114 * blue);
let cb = 0.5 - (0.168_736 * red) - (0.331_264 * green) + (0.5 * blue);
let cr = 0.5 + (0.5 * red) - (0.418_688 * green) - (0.081_312 * blue);
P::from_channels(&[y.into(), cb.into(), cr.into(), alpha])
}
}
pub type YCbCr8 = Pix<3, Ch8, YCbCr, Straight, Linear>;
pub type YCbCr16 = Pix<3, Ch16, YCbCr, Straight, Linear>;
pub type YCbCr32 = Pix<3, Ch32, YCbCr, Straight, Linear>;
pub type YCbCra8 = Pix<4, Ch8, YCbCr, Straight, Linear>;
pub type YCbCra16 = Pix<4, Ch16, YCbCr, Straight, Linear>;
pub type YCbCra32 = Pix<4, Ch32, YCbCr, Straight, Linear>;
pub type YCbCra8p = Pix<4, Ch8, YCbCr, Premultiplied, Linear>;
pub type YCbCra16p = Pix<4, Ch16, YCbCr, Premultiplied, Linear>;
pub type YCbCra32p = Pix<4, Ch32, YCbCr, Premultiplied, Linear>;