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
use clamp::clamp;
use super::{Rgba, ByteChannels};

/// A pixel that is one byte long and has just an intensity channel.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct Grayscale(pub u8);

unsafe impl ByteChannels for Grayscale {
    type Channels = [u8; 1];
    fn width() -> usize { 1 }
}

impl From<[u8; 1]> for Grayscale {
    fn from(c: [u8; 1]) -> Self {
        Grayscale(c[0])
    }
}

impl From<Grayscale> for [u8; 1] {
    fn from(p: Grayscale) -> Self {
        [p.0]
    }
}

impl From<Rgba> for Grayscale {
    fn from(Rgba(r, g, b, _): Rgba) -> Grayscale {
        const K_B: f32 = 0.0722;
        const K_R: f32 = 0.2126;
        const K_G: f32 = 1.0 - K_B - K_R;

        let (r, g, b) = (r as f32, g as f32, b as f32);

        Grayscale(clamp(K_R * r + K_G * g + K_B * b, 0.0, 255.0) as u8)
    }
}

impl From<Grayscale> for Rgba {
    fn from(Grayscale(l): Grayscale) -> Rgba {
        Rgba(l, l, l, 255)
    }
}