use crate::chan::{Alpha, Channel, Gamma, Linear, Premultiplied};
use crate::matte::Matte;
use crate::ops::Blend;
use crate::private::Sealed;
use crate::rgb::Rgb;
use crate::ColorModel;
use std::any::TypeId;
use std::fmt::Debug;
use std::marker::PhantomData;
pub trait Pixel: Clone + Copy + Debug + Default + PartialEq + Sealed {
type Chan: Channel;
type Model: ColorModel;
type Alpha: Alpha;
type Gamma: Gamma;
fn from_channels(ch: &[Self::Chan]) -> Self;
fn from_bit_depth<P>(p: P) -> Self
where
P: Pixel,
Self::Chan: From<P::Chan>;
fn channels(&self) -> &[Self::Chan];
fn channels_mut(&mut self) -> &mut [Self::Chan];
fn one(self) -> Self::Chan {
*self.channels().get(0).unwrap_or(&Self::Chan::MAX)
}
fn one_mut(&mut self) -> &mut Self::Chan {
&mut self.channels_mut()[0]
}
fn two(self) -> Self::Chan {
*self.channels().get(1).unwrap_or(&Self::Chan::MAX)
}
fn two_mut(&mut self) -> &mut Self::Chan {
&mut self.channels_mut()[1]
}
fn three(self) -> Self::Chan {
*self.channels().get(2).unwrap_or(&Self::Chan::MAX)
}
fn three_mut(&mut self) -> &mut Self::Chan {
&mut self.channels_mut()[2]
}
fn four(self) -> Self::Chan {
*self.channels().get(3).unwrap_or(&Self::Chan::MAX)
}
fn four_mut(&mut self) -> &mut Self::Chan {
&mut self.channels_mut()[3]
}
fn alpha(self) -> Self::Chan {
let chan = self.channels();
*chan.get(Self::Model::ALPHA).unwrap_or(&Self::Chan::MAX)
}
fn alpha_mut(&mut self) -> &mut Self::Chan {
let chan = self.channels_mut();
chan.get_mut(Self::Model::ALPHA).unwrap()
}
fn convert<D>(self) -> D
where
D: Pixel,
D::Chan: From<Self::Chan>,
{
if TypeId::of::<Self::Model>() == TypeId::of::<D::Model>() {
convert_same_model::<D, Self>(self)
} else {
convert_thru_rgba::<D, Self>(self)
}
}
fn copy_color(dst: &mut [Self], clr: &Self) {
for d in dst.iter_mut() {
*d = *clr;
}
}
fn copy_slice(dst: &mut [Self], src: &[Self]) {
for (d, s) in dst.iter_mut().zip(src) {
*d = *s;
}
}
fn composite_color<O>(dst: &mut [Self], clr: &Self, op: O)
where
Self: Pixel<Alpha = Premultiplied, Gamma = Linear>,
O: Blend,
{
for d in dst.iter_mut() {
d.composite_channels(clr, op);
}
}
fn composite_matte<M, O>(dst: &mut [Self], src: &[M], clr: &Self, op: O)
where
Self: Pixel<Alpha = Premultiplied, Gamma = Linear>,
M: Pixel<Chan = Self::Chan, Model = Matte, Gamma = Linear>,
O: Blend,
{
for (d, s) in dst.iter_mut().zip(src) {
d.composite_channels_matte(&s.alpha(), clr, op);
}
}
fn composite_slice<O>(dst: &mut [Self], src: &[Self], op: O)
where
Self: Pixel<Alpha = Premultiplied, Gamma = Linear>,
O: Blend,
{
for (d, s) in dst.iter_mut().zip(src) {
d.composite_channels(s, op);
}
}
fn composite_channels<O>(&mut self, src: &Self, op: O)
where
Self: Pixel<Alpha = Premultiplied, Gamma = Linear>,
O: Blend,
{
let da1 = Self::Chan::MAX - self.alpha();
let sa1 = Self::Chan::MAX - src.alpha();
let d_chan = &mut self.channels_mut()[Self::Model::CIRCULAR];
let s_chan = &src.channels()[Self::Model::CIRCULAR];
d_chan
.iter_mut()
.zip(s_chan)
.for_each(|(d, s)| circ_composite(d, da1, *s, sa1, op));
let d_chan = &mut self.channels_mut()[Self::Model::LINEAR];
let s_chan = &src.channels()[Self::Model::LINEAR];
d_chan
.iter_mut()
.zip(s_chan)
.for_each(|(d, s)| O::composite(d, da1, s, sa1));
O::composite(self.alpha_mut(), da1, &src.alpha(), sa1);
}
fn composite_channels_matte<O>(
&mut self,
alpha: &Self::Chan,
src: &Self,
op: O,
) where
Self: Pixel<Alpha = Premultiplied, Gamma = Linear>,
O: Blend,
{
let da1 = Self::Chan::MAX - self.alpha();
let sa1 = Self::Chan::MAX - *alpha;
let d_chan = &mut self.channels_mut()[Self::Model::CIRCULAR];
let s_chan = &src.channels()[Self::Model::CIRCULAR];
d_chan
.iter_mut()
.zip(s_chan)
.for_each(|(d, s)| circ_composite(d, da1, *s * *alpha, sa1, op));
let d_chan = &mut self.channels_mut()[Self::Model::LINEAR];
let s_chan = &src.channels()[Self::Model::LINEAR];
d_chan
.iter_mut()
.zip(s_chan)
.for_each(|(d, s)| O::composite(d, da1, &(*s * *alpha), sa1));
O::composite(self.alpha_mut(), da1, &(src.alpha() * *alpha), sa1);
}
}
#[inline]
fn circ_composite<C, O>(d: &mut C, da1: C, mut s: C, sa1: C, _op: O)
where
C: Channel,
O: Blend,
{
let mut t = C::MIN;
O::composite(&mut t, da1, &(C::MAX - sa1), sa1);
let rotate = s.max(*d) - s.min(*d) > C::MID;
if rotate {
if s > *d {
s = s - C::MID;
*d = *d + C::MID;
} else {
s = s + C::MID;
*d = *d - C::MID;
}
}
*d = d.lerp(s, t);
if rotate {
if *d < C::MID {
*d = *d + C::MID;
} else {
*d = *d - C::MID;
}
}
}
pub type PixRgba<P> =
Pix4<<P as Pixel>::Chan, Rgb, <P as Pixel>::Alpha, <P as Pixel>::Gamma>;
fn convert_same_model<D, S>(src: S) -> D
where
D: Pixel,
S: Pixel,
D::Chan: From<S::Chan>,
{
let mut dst = D::from_bit_depth(src);
if TypeId::of::<S::Alpha>() != TypeId::of::<D::Alpha>()
|| TypeId::of::<S::Gamma>() != TypeId::of::<D::Gamma>()
{
let alpha = dst.alpha();
let mut channels = dst.channels_mut();
convert_alpha_gamma::<D, S>(&mut channels, alpha);
}
dst
}
fn convert_alpha_gamma<D, S>(channels: &mut [D::Chan], alpha: D::Chan)
where
D: Pixel,
S: Pixel,
{
for c in channels[D::Model::LINEAR].iter_mut() {
*c = S::Gamma::to_linear(*c);
if TypeId::of::<S::Alpha>() != TypeId::of::<D::Alpha>() {
*c = S::Alpha::decode(*c, alpha);
*c = D::Alpha::encode(*c, alpha);
}
*c = D::Gamma::from_linear(*c);
}
}
fn convert_thru_rgba<D, S>(src: S) -> D
where
D: Pixel,
S: Pixel,
D::Chan: From<S::Chan>,
{
let rgba = S::Model::into_rgba::<S>(src);
let rgba = convert_same_model::<PixRgba<D>, PixRgba<S>>(rgba);
D::Model::from_rgba::<D>(rgba)
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[repr(C)]
pub struct Pix1<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
channels: [C; 1],
_model: PhantomData<M>,
_alpha: PhantomData<A>,
_gamma: PhantomData<G>,
}
impl<C, M, A, G> Pix1<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
pub fn new<H>(one: H) -> Self
where
C: From<H>,
{
let channels = [C::from(one); 1];
Pix1 {
channels,
_model: PhantomData,
_alpha: PhantomData,
_gamma: PhantomData,
}
}
}
impl<C, M, A, G> Pixel for Pix1<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
type Chan = C;
type Model = M;
type Alpha = A;
type Gamma = G;
fn from_channels(ch: &[C]) -> Self {
let one = ch[0];
Self::new::<C>(one)
}
fn from_bit_depth<P>(p: P) -> Self
where
P: Pixel,
Self::Chan: From<P::Chan>,
{
debug_assert_eq!(TypeId::of::<Self::Model>(), TypeId::of::<P::Model>());
let one = Self::Chan::from(p.one());
Self::new::<Self::Chan>(one)
}
fn channels(&self) -> &[Self::Chan] {
&self.channels
}
fn channels_mut(&mut self) -> &mut [Self::Chan] {
&mut self.channels
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[repr(C)]
pub struct Pix2<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
channels: [C; 2],
_model: PhantomData<M>,
_alpha: PhantomData<A>,
_gamma: PhantomData<G>,
}
impl<C, M, A, G> Pix2<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
pub fn new<H>(one: H, two: H) -> Self
where
C: From<H>,
{
let one = C::from(one);
let two = C::from(two);
let channels = [one, two];
Pix2 {
channels,
_model: PhantomData,
_alpha: PhantomData,
_gamma: PhantomData,
}
}
}
impl<C, M, A, G> Pixel for Pix2<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
type Chan = C;
type Model = M;
type Alpha = A;
type Gamma = G;
fn from_channels(ch: &[C]) -> Self {
let one = ch[0];
let two = ch[1];
Self::new::<C>(one, two)
}
fn from_bit_depth<P>(p: P) -> Self
where
P: Pixel,
Self::Chan: From<P::Chan>,
{
debug_assert_eq!(TypeId::of::<Self::Model>(), TypeId::of::<P::Model>());
let one = Self::Chan::from(p.one());
let two = Self::Chan::from(p.two());
Self::new::<Self::Chan>(one, two)
}
fn channels(&self) -> &[Self::Chan] {
&self.channels
}
fn channels_mut(&mut self) -> &mut [Self::Chan] {
&mut self.channels
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[repr(C)]
pub struct Pix3<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
channels: [C; 3],
_model: PhantomData<M>,
_alpha: PhantomData<A>,
_gamma: PhantomData<G>,
}
impl<C, M, A, G> Pix3<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
pub fn new<H>(one: H, two: H, three: H) -> Self
where
C: From<H>,
{
let one = C::from(one);
let two = C::from(two);
let three = C::from(three);
let channels = [one, two, three];
Pix3 {
channels,
_model: PhantomData,
_alpha: PhantomData,
_gamma: PhantomData,
}
}
}
impl<C, M, A, G> Pixel for Pix3<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
type Chan = C;
type Model = M;
type Alpha = A;
type Gamma = G;
fn from_channels(ch: &[C]) -> Self {
let one = ch[0];
let two = ch[1];
let three = ch[2];
Self::new::<C>(one, two, three)
}
fn from_bit_depth<P>(p: P) -> Self
where
P: Pixel,
Self::Chan: From<P::Chan>,
{
debug_assert_eq!(TypeId::of::<Self::Model>(), TypeId::of::<P::Model>());
let one = Self::Chan::from(p.one());
let two = Self::Chan::from(p.two());
let three = Self::Chan::from(p.three());
Self::new::<Self::Chan>(one, two, three)
}
fn channels(&self) -> &[Self::Chan] {
&self.channels
}
fn channels_mut(&mut self) -> &mut [Self::Chan] {
&mut self.channels
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[repr(C)]
pub struct Pix4<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
channels: [C; 4],
_model: PhantomData<M>,
_alpha: PhantomData<A>,
_gamma: PhantomData<G>,
}
impl<C, M, A, G> Pix4<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
pub fn new<H>(one: H, two: H, three: H, four: H) -> Self
where
C: From<H>,
{
let one = C::from(one);
let two = C::from(two);
let three = C::from(three);
let four = C::from(four);
let channels = [one, two, three, four];
Pix4 {
channels,
_model: PhantomData,
_alpha: PhantomData,
_gamma: PhantomData,
}
}
}
impl<C, M, A, G> Pixel for Pix4<C, M, A, G>
where
C: Channel,
M: ColorModel,
A: Alpha,
G: Gamma,
{
type Chan = C;
type Model = M;
type Alpha = A;
type Gamma = G;
fn from_channels(ch: &[C]) -> Self {
let one = ch[0];
let two = ch[1];
let three = ch[2];
let four = ch[3];
Self::new::<C>(one, two, three, four)
}
fn from_bit_depth<P>(p: P) -> Self
where
P: Pixel,
Self::Chan: From<P::Chan>,
{
debug_assert_eq!(TypeId::of::<Self::Model>(), TypeId::of::<P::Model>());
let one = Self::Chan::from(p.one());
let two = Self::Chan::from(p.two());
let three = Self::Chan::from(p.three());
let four = Self::Chan::from(p.four());
Self::new::<Self::Chan>(one, two, three, four)
}
fn channels(&self) -> &[Self::Chan] {
&self.channels
}
fn channels_mut(&mut self) -> &mut [Self::Chan] {
&mut self.channels
}
}
#[cfg(test)]
mod test {
use crate::el::*;
use crate::gray::*;
use crate::matte::*;
use crate::rgb::*;
#[test]
fn check_sizes() {
assert_eq!(std::mem::size_of::<Matte8>(), 1);
assert_eq!(std::mem::size_of::<Matte16>(), 2);
assert_eq!(std::mem::size_of::<Matte32>(), 4);
assert_eq!(std::mem::size_of::<SGray8>(), 1);
assert_eq!(std::mem::size_of::<SGray16>(), 2);
assert_eq!(std::mem::size_of::<SGray32>(), 4);
assert_eq!(std::mem::size_of::<SGraya8>(), 2);
assert_eq!(std::mem::size_of::<SGraya16>(), 4);
assert_eq!(std::mem::size_of::<SGraya32>(), 8);
assert_eq!(std::mem::size_of::<Rgb8>(), 3);
assert_eq!(std::mem::size_of::<Rgb16>(), 6);
assert_eq!(std::mem::size_of::<Rgb32>(), 12);
assert_eq!(std::mem::size_of::<Rgba8>(), 4);
assert_eq!(std::mem::size_of::<Rgba16>(), 8);
assert_eq!(std::mem::size_of::<Rgba32>(), 16);
}
#[test]
fn gray_to_rgb() {
assert_eq!(SRgb8::new(0xD9, 0xD9, 0xD9), SGray8::new(0xD9).convert(),);
assert_eq!(
SRgb8::new(0x33, 0x33, 0x33),
SGray16::new(0x337F).convert(),
);
assert_eq!(SRgb8::new(0x40, 0x40, 0x40), SGray32::new(0.25).convert(),);
assert_eq!(
SRgb16::new(0x2929, 0x2929, 0x2929),
SGray8::new(0x29).convert(),
);
assert_eq!(
SRgb16::new(0x5593, 0x5593, 0x5593),
SGray16::new(0x5593).convert(),
);
assert_eq!(
SRgb16::new(0xFFFF, 0xFFFF, 0xFFFF),
SGray32::new(1.0).convert(),
);
assert_eq!(
SRgb32::new(0.5019608, 0.5019608, 0.5019608),
SGray8::new(0x80).convert(),
);
assert_eq!(
SRgb32::new(0.75001144, 0.75001144, 0.75001144),
SGray16::new(0xC000).convert(),
);
assert_eq!(SRgb32::new(0.33, 0.33, 0.33), SGray32::new(0.33).convert(),);
}
#[test]
fn linear_to_srgb() {
assert_eq!(
SRgb8::new(0xEF, 0x8C, 0xC7),
Rgb8::new(0xDC, 0x43, 0x91).convert()
);
assert_eq!(
SRgb8::new(0x66, 0xF4, 0xB5),
Rgb16::new(0x2205, 0xE699, 0x7654).convert()
);
assert_eq!(
SRgb8::new(0xBC, 0x89, 0xE0),
Rgb32::new(0.5, 0.25, 0.75).convert()
);
}
#[test]
fn srgb_to_linear() {
assert_eq!(
Rgb8::new(0xDC, 0x43, 0x92),
SRgb8::new(0xEF, 0x8C, 0xC7).convert(),
);
assert_eq!(
Rgb8::new(0x22, 0xE7, 0x76),
SRgb16::new(0x6673, 0xF453, 0xB593).convert(),
);
assert_eq!(
Rgb8::new(0x37, 0x0D, 0x85),
SRgb32::new(0.5, 0.25, 0.75).convert(),
);
}
#[test]
fn straight_to_premultiplied() {
assert_eq!(
Rgba8p::new(0x10, 0x20, 0x40, 0x80),
Rgba8::new(0x20, 0x40, 0x80, 0x80).convert(),
);
assert_eq!(
Rgba8p::new(0x04, 0x10, 0x20, 0x40),
Rgba16::new(0x1000, 0x4000, 0x8000, 0x4000).convert(),
);
assert_eq!(
Rgba8p::new(0x60, 0xBF, 0x8F, 0xBF),
Rgba32::new(0.5, 1.0, 0.75, 0.75).convert(),
);
}
#[test]
fn premultiplied_to_straight() {
assert_eq!(
Rgba8::new(0x40, 0x80, 0xFF, 0x80),
Rgba8p::new(0x20, 0x40, 0x80, 0x80).convert(),
);
assert_eq!(
Rgba8::new(0x40, 0xFF, 0x80, 0x40),
Rgba16p::new(0x1000, 0x4000, 0x2000, 0x4000).convert(),
);
assert_eq!(
Rgba8::new(0xAB, 0x55, 0xFF, 0xBF),
Rgba32p::new(0.5, 0.25, 0.75, 0.75).convert(),
);
}
#[test]
fn straight_to_premultiplied_srgb() {
assert_eq!(
SRgba8p::new(0x16, 0x2A, 0x5C, 0x80),
SRgba8::new(0x20, 0x40, 0x80, 0x80).convert(),
);
assert_eq!(
SRgba8p::new(0x0D, 0x1C, 0x40, 0x40),
SRgba16::new(0x2000, 0x4000, 0x8000, 0x4000).convert(),
);
assert_eq!(
SRgba8p::new(0x70, 0xE0, 0xA7, 0xBF),
SRgba32::new(0.5, 1.0, 0.75, 0.75).convert(),
);
}
}