#[derive(Clone, Copy, Debug, Default)]
pub struct Unorm;
#[derive(Clone, Copy, Debug, Default)]
pub struct Inorm;
#[derive(Clone, Copy, Debug, Default)]
pub struct Uint;
#[derive(Clone, Copy, Debug, Default)]
pub struct Int;
#[derive(Clone, Copy, Debug, Default)]
pub struct Uscaled;
#[derive(Clone, Copy, Debug, Default)]
pub struct Iscaled;
#[derive(Clone, Copy, Debug, Default)]
pub struct Srgb;
#[derive(Clone, Copy, Debug, Default)]
pub struct Float;
#[derive(Clone, Copy, Debug, Default)]
pub struct _8;
#[derive(Clone, Copy, Debug, Default)]
pub struct _16;
#[derive(Clone, Copy, Debug, Default)]
pub struct _32;
#[derive(Clone, Copy, Debug, Default)]
pub struct _64;
pub trait ChannelSize {
const SIZE: u32;
}
impl ChannelSize for _8 {
const SIZE: u32 = 1;
}
impl ChannelSize for _16 {
const SIZE: u32 = 2;
}
impl ChannelSize for _32 {
const SIZE: u32 = 4;
}
impl ChannelSize for _64 {
const SIZE: u32 = 8;
}
pub trait ChannelRepr<S> {
type Repr: Sized + std::fmt::Debug + Default + Copy + Send + Sync + 'static;
}
macro_rules! impl_channel_repr {
($($type:ident * $size:ident = $repr:ident;)*) => {
$(
impl ChannelRepr<$size> for $type { type Repr = $repr; }
)*
};
}
impl_channel_repr! {
Unorm * _8 = u8;
Inorm * _8 = u8;
Uint * _8 = u8;
Int * _8 = u8;
Uscaled * _8 = u8;
Iscaled * _8 = u8;
Srgb * _8 = u8;
Unorm * _16 = u16;
Inorm * _16 = u16;
Uint * _16 = u16;
Int * _16 = u16;
Uscaled * _16 = u16;
Iscaled * _16 = u16;
Srgb * _16 = u16;
Unorm * _32 = u32;
Inorm * _32 = u32;
Uint * _32 = u32;
Int * _32 = u32;
Uscaled * _32 = u32;
Iscaled * _32 = u32;
Srgb * _32 = u32;
Float * _32 = f32;
Unorm * _64 = u64;
Inorm * _64 = u64;
Uint * _64 = u64;
Int * _64 = u64;
Uscaled * _64 = u64;
Iscaled * _64 = u64;
Srgb * _64 = u64;
Float * _64 = f64;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct R;
#[derive(Clone, Copy, Debug, Default)]
pub struct Rg;
#[derive(Clone, Copy, Debug, Default)]
pub struct Rgb;
#[derive(Clone, Copy, Debug, Default)]
pub struct Rgba;
#[derive(Clone, Copy, Debug, Default)]
pub struct Bgr;
#[derive(Clone, Copy, Debug, Default)]
pub struct Bgra;
#[derive(Clone, Copy, Debug, Default)]
pub struct Abgr;
pub trait PixelRepr<S, T> {
type Repr: Sized + std::fmt::Debug + Default + Copy + Send + Sync + 'static;
}
macro_rules! num_channels {
(R) => {
1
};
(Rg) => {
2
};
(Rgb) => {
3
};
(Rgba) => {
4
};
(Bgr) => {
3
};
(Bgra) => {
4
};
(Abgr) => {
4
};
}
macro_rules! impl_pixel_repr {
($($channels:ident;)*) => {
$(
impl<S, T> PixelRepr<S, T> for $channels
where
S: ChannelSize,
T: ChannelRepr<S>,
{
type Repr = [<T as ChannelRepr<S>>::Repr; num_channels!($channels)];
}
)*
};
}
impl_pixel_repr! {
R;
Rg;
Rgb;
Rgba;
Bgr;
Bgra;
Abgr;
}
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = ""),
Copy(bound = ""),
Debug(bound = ""),
Default(bound = "")
)]
#[repr(transparent)]
pub struct Pixel<C, S, T>
where
C: PixelRepr<S, T>,
{
pub repr: <C as PixelRepr<S, T>>::Repr,
}
pub trait AsPixel: Copy + std::fmt::Debug + Default + Send + Sync + 'static {
const NAME: &'static str;
const SIZE: u32;
const FORMAT: gfx_hal::format::Format;
}
macro_rules! impl_pixel {
($($alias:ident = $channels:ident $size:ident $type:ident;)*) => {
$(
pub type $alias = Pixel<$channels, $size, $type>;
impl AsPixel for $alias {
const NAME: &'static str = stringify!($alias);
const SIZE: u32 = num_channels!($channels) * <$size as ChannelSize>::SIZE;
const FORMAT: gfx_hal::format::Format = gfx_hal::format::Format::$alias;
}
)*
};
}
impl_pixel! {
R8Unorm = R _8 Unorm;
R8Snorm = R _8 Inorm;
R8Uscaled = R _8 Uscaled;
R8Sscaled = R _8 Iscaled;
R8Uint = R _8 Uint;
R8Sint = R _8 Int;
R8Srgb = R _8 Srgb;
Rg8Unorm = Rg _8 Unorm;
Rg8Snorm = Rg _8 Inorm;
Rg8Uscaled = Rg _8 Uscaled;
Rg8Sscaled = Rg _8 Iscaled;
Rg8Uint = Rg _8 Uint;
Rg8Sint = Rg _8 Int;
Rg8Srgb = Rg _8 Srgb;
Rgb8Unorm = Rgb _8 Unorm;
Rgb8Snorm = Rgb _8 Inorm;
Rgb8Uscaled = Rgb _8 Uscaled;
Rgb8Sscaled = Rgb _8 Iscaled;
Rgb8Uint = Rgb _8 Uint;
Rgb8Sint = Rgb _8 Int;
Rgb8Srgb = Rgb _8 Srgb;
Bgr8Unorm = Bgr _8 Unorm;
Bgr8Snorm = Bgr _8 Inorm;
Bgr8Uscaled = Bgr _8 Uscaled;
Bgr8Sscaled = Bgr _8 Iscaled;
Bgr8Uint = Bgr _8 Uint;
Bgr8Sint = Bgr _8 Int;
Bgr8Srgb = Bgr _8 Srgb;
Rgba8Unorm = Rgba _8 Unorm;
Rgba8Snorm = Rgba _8 Inorm;
Rgba8Uscaled = Rgba _8 Uscaled;
Rgba8Sscaled = Rgba _8 Iscaled;
Rgba8Uint = Rgba _8 Uint;
Rgba8Sint = Rgba _8 Int;
Rgba8Srgb = Rgba _8 Srgb;
Bgra8Unorm = Bgra _8 Unorm;
Bgra8Snorm = Bgra _8 Inorm;
Bgra8Uscaled = Bgra _8 Uscaled;
Bgra8Sscaled = Bgra _8 Iscaled;
Bgra8Uint = Bgra _8 Uint;
Bgra8Sint = Bgra _8 Int;
Bgra8Srgb = Bgra _8 Srgb;
Abgr8Unorm = Abgr _8 Unorm;
Abgr8Snorm = Abgr _8 Inorm;
Abgr8Uscaled = Abgr _8 Uscaled;
Abgr8Sscaled = Abgr _8 Iscaled;
Abgr8Uint = Abgr _8 Uint;
Abgr8Sint = Abgr _8 Int;
Abgr8Srgb = Abgr _8 Srgb;
R16Unorm = R _16 Unorm;
R16Snorm = R _16 Inorm;
R16Uscaled = R _16 Uscaled;
R16Sscaled = R _16 Iscaled;
R16Uint = R _16 Uint;
R16Sint = R _16 Int;
Rg16Unorm = Rg _16 Unorm;
Rg16Snorm = Rg _16 Inorm;
Rg16Uscaled = Rg _16 Uscaled;
Rg16Sscaled = Rg _16 Iscaled;
Rg16Uint = Rg _16 Uint;
Rg16Sint = Rg _16 Int;
Rgb16Unorm = Rgb _16 Unorm;
Rgb16Snorm = Rgb _16 Inorm;
Rgb16Uscaled = Rgb _16 Uscaled;
Rgb16Sscaled = Rgb _16 Iscaled;
Rgb16Uint = Rgb _16 Uint;
Rgb16Sint = Rgb _16 Int;
Rgba16Unorm = Rgba _16 Unorm;
Rgba16Snorm = Rgba _16 Inorm;
Rgba16Uscaled = Rgba _16 Uscaled;
Rgba16Sscaled = Rgba _16 Iscaled;
Rgba16Uint = Rgba _16 Uint;
Rgba16Sint = Rgba _16 Int;
R32Uint = R _32 Uint;
R32Sint = R _32 Int;
R32Sfloat = R _32 Float;
Rg32Uint = Rg _32 Uint;
Rg32Sint = Rg _32 Int;
Rg32Sfloat = Rg _32 Float;
Rgb32Uint = Rgb _32 Uint;
Rgb32Sint = Rgb _32 Int;
Rgb32Sfloat = Rgb _32 Float;
Rgba32Uint = Rgba _32 Uint;
Rgba32Sint = Rgba _32 Int;
Rgba32Sfloat = Rgba _32 Float;
R64Uint = R _64 Uint;
R64Sint = R _64 Int;
R64Sfloat = R _64 Float;
Rg64Uint = Rg _64 Uint;
Rg64Sint = Rg _64 Int;
Rg64Sfloat = Rg _64 Float;
Rgb64Uint = Rgb _64 Uint;
Rgb64Sint = Rgb _64 Int;
Rgb64Sfloat = Rgb _64 Float;
Rgba64Uint = Rgba _64 Uint;
Rgba64Sint = Rgba _64 Int;
Rgba64Sfloat = Rgba _64 Float;
}
#[cfg(feature = "palette")]
mod palette_pixel {
use palette::{
encoding,
luma::{Luma, LumaStandard, Lumaa},
rgb::{Rgb, RgbStandard, Rgba},
white_point::D65,
Component,
};
macro_rules! impl_from_palette {
(# $color:ident R as $encoding:path) => {
{
let f = $color.into_format();
let _: (f32,) = f.into_components();
let (r,) = f.into_encoding::<$encoding>().into_format().into_components();
Self { repr: [r] }
}
};
(# $color:ident Rg as $encoding:path) => {
{
let f = $color.into_format();
let _: (f32,f32) = f.into_components();
let (r,g) = f.into_encoding::<$encoding>().into_format().into_components();
Self { repr: [r,g] }
}
};
(# $color:ident Rgb as $encoding:path) => {
{
let f = $color.into_format();
let _: (f32,f32,f32) = f.into_components();
let (r,g,b) = f.into_encoding::<$encoding>().into_format().into_components();
Self { repr: [r,g,b] }
}
};
(# $color:ident Rgba as $encoding:path) => {
{
let f = $color.into_format();
let _: (f32,f32,f32,f32) = f.into_components();
let (r,g,b,a) = f.into_encoding::<$encoding>().into_format().into_components();
Self { repr: [r,g,b,a] }
}
};
($($container:path as $encoding:path : $standard:path => $channels:ident $($repr:ident)|+),* $(,)*) => {$($(
impl<S, T, B> From<$container> for super::Pixel<super::$channels, B, super::$repr>
where
S: $standard,
T: Component,
B: super::ChannelSize,
super::$repr: super::ChannelRepr<B>,
<super::$repr as super::ChannelRepr<B>>::Repr: Component,
{
fn from(color: $container) -> Self {
impl_from_palette!(# color $channels as $encoding)
}
}
)+)*};
}
impl_from_palette! {
Rgb<S, T> as encoding::Srgb: RgbStandard<Space = encoding::Srgb> => Rgb Srgb,
Rgba<S, T> as encoding::Srgb: RgbStandard<Space = encoding::Srgb> => Rgba Srgb,
Luma<S, T> as encoding::Srgb: LumaStandard<WhitePoint = D65> => R Srgb,
Lumaa<S, T> as encoding::Srgb: LumaStandard<WhitePoint = D65> => Rg Srgb,
Rgb<S, T> as encoding::Linear<encoding::Srgb>: RgbStandard<Space = encoding::Srgb> => Rgb Unorm | Float,
Rgba<S, T> as encoding::Linear<encoding::Srgb>: RgbStandard<Space = encoding::Srgb> => Rgba Unorm | Float,
Luma<S, T> as encoding::Linear<D65>: LumaStandard<WhitePoint = D65> => R Unorm | Float,
Lumaa<S, T> as encoding::Linear<D65>: LumaStandard<WhitePoint = D65> => Rg Unorm | Float,
}
}