1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//! RGB types, spaces and standards.

use crate::encoding::{self, Gamma, Linear, TransferFn};
use crate::white_point::WhitePoint;
use crate::{Component, FloatComponent, FromComponent, Yxy};

pub use self::packed::{channels, Packed, RgbChannels};
pub use self::rgb::{FromHexError, Rgb, Rgba};

mod packed;
mod rgb;

/// Nonlinear sRGB.
pub type Srgb<T = f32> = Rgb<encoding::Srgb, T>;
/// Nonlinear sRGB with an alpha component.
pub type Srgba<T = f32> = Rgba<encoding::Srgb, T>;

/// Linear sRGB.
#[doc(alias = "linear")]
pub type LinSrgb<T = f32> = Rgb<Linear<encoding::Srgb>, T>;
/// Linear sRGB with an alpha component.
#[doc(alias = "linear")]
pub type LinSrgba<T = f32> = Rgba<Linear<encoding::Srgb>, T>;

/// Gamma 2.2 encoded sRGB.
pub type GammaSrgb<T = f32> = Rgb<Gamma<encoding::Srgb>, T>;
/// Gamma 2.2 encoded sRGB with an alpha component.
pub type GammaSrgba<T = f32> = Rgba<Gamma<encoding::Srgb>, T>;

/// An RGB space and a transfer function.
pub trait RgbStandard: 'static {
    /// The RGB color space.
    type Space: RgbSpace;

    /// The transfer function for the color components.
    type TransferFn: TransferFn;
}

impl<S: RgbSpace, T: TransferFn> RgbStandard for (S, T) {
    type Space = S;
    type TransferFn = T;
}

impl<P: Primaries, W: WhitePoint, T: TransferFn> RgbStandard for (P, W, T) {
    type Space = (P, W);
    type TransferFn = T;
}

/// A set of primaries and a white point.
pub trait RgbSpace: 'static {
    /// The primaries of the RGB color space.
    type Primaries: Primaries;

    /// The white point of the RGB color space.
    type WhitePoint: WhitePoint;
}

impl<P: Primaries, W: WhitePoint> RgbSpace for (P, W) {
    type Primaries = P;
    type WhitePoint = W;
}

/// Represents the red, green and blue primaries of an RGB space.
pub trait Primaries: 'static {
    /// Primary red.
    fn red<Wp: WhitePoint, T: FloatComponent>() -> Yxy<Wp, T>;
    /// Primary green.
    fn green<Wp: WhitePoint, T: FloatComponent>() -> Yxy<Wp, T>;
    /// Primary blue.
    fn blue<Wp: WhitePoint, T: FloatComponent>() -> Yxy<Wp, T>;
}

impl<T, U> From<LinSrgb<T>> for Srgb<U>
where
    T: FloatComponent,
    U: Component + FromComponent<T>,
{
    fn from(lin_srgb: LinSrgb<T>) -> Self {
        let non_lin = Srgb::<T>::from_linear(lin_srgb);
        non_lin.into_format()
    }
}

impl<T, U> From<Srgb<T>> for LinSrgb<U>
where
    T: FloatComponent,
    U: Component + FromComponent<T>,
{
    fn from(srgb: Srgb<T>) -> Self {
        srgb.into_linear().into_format()
    }
}

impl<T, U> From<LinSrgb<T>> for Srgba<U>
where
    T: FloatComponent,
    U: Component + FromComponent<T>,
{
    fn from(lin_srgb: LinSrgb<T>) -> Self {
        let non_lin = Srgb::<T>::from_linear(lin_srgb);
        let new_fmt = Srgb::<U>::from_format(non_lin);
        new_fmt.into()
    }
}

impl<T, U> From<LinSrgba<T>> for Srgba<U>
where
    T: FloatComponent,
    U: Component + FromComponent<T>,
{
    fn from(lin_srgba: LinSrgba<T>) -> Self {
        let non_lin = Srgba::<T>::from_linear(lin_srgba);
        non_lin.into_format()
    }
}

impl<T, U> From<Srgb<T>> for LinSrgba<U>
where
    T: FloatComponent,
    U: Component + FromComponent<T>,
{
    fn from(srgb: Srgb<T>) -> Self {
        srgb.into_linear().into_format().into()
    }
}

impl<T, U> From<Srgba<T>> for LinSrgba<U>
where
    T: FloatComponent,
    U: Component + FromComponent<T>,
{
    fn from(srgba: Srgba<T>) -> Self {
        srgba.into_linear().into_format()
    }
}