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
//! The sRGB standard.

use float::Float;

use rgb::{Primaries, RgbSpace, RgbStandard};
use luma::LumaStandard;
use encoding::TransferFn;
use white_point::{D65, WhitePoint};
use {cast, Component, Yxy};

///The sRGB color space.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct Srgb;

impl Primaries for Srgb {
    fn red<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T> {
        Yxy::with_wp(cast(0.6400), cast(0.3300), cast(0.212656))
    }
    fn green<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T> {
        Yxy::with_wp(cast(0.3000), cast(0.6000), cast(0.715158))
    }
    fn blue<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T> {
        Yxy::with_wp(cast(0.1500), cast(0.0600), cast(0.072186))
    }
}

impl RgbSpace for Srgb {
    type Primaries = Srgb;
    type WhitePoint = D65;
}

impl RgbStandard for Srgb {
    type Space = Srgb;
    type TransferFn = Srgb;
}

impl LumaStandard for Srgb {
    type WhitePoint = D65;
    type TransferFn = Srgb;
}

impl TransferFn for Srgb {
    fn into_linear<T: Float>(x: T) -> T {
        if x <= cast(0.04045) {
            x / cast(12.92)
        } else {
            ((x + cast(0.055)) / cast(1.055)).powf(cast(2.4))
        }
    }

    fn from_linear<T: Float>(x: T) -> T {
        if x <= cast(0.0031308) {
            x * cast(12.92)
        } else {
            x.powf(T::one() / cast(2.4)) * cast(1.055) - cast(0.055)
        }
    }
}