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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
use std::ops::{Add, AddAssign, Sub, Mul, MulAssign, Div};

/// A RGBA8 color used for both the input image data and the palette output.
#[derive(Copy,Clone,Eq,PartialEq,Hash)]
pub struct Color {
    pub r: u8,
    pub g: u8,
    pub b: u8,
    pub a: u8,
}

impl Color {
    /// Creates a new `Color` from the given channel components.
    pub fn new(r: u8, g: u8, b: u8, a: u8) -> Color {
        Color {
            r: r,
            g: g,
            b: b,
            a: a,
        }
    }
}

/// A color with floating point channel components.
///
/// Used for all internal processing.
///
/// It implements `Mul`, `Div`, `Add` and `Sub` operators that apply each operation component
/// wise to each channel in turn.
#[derive(Default, Copy, Clone, Debug)]
pub struct Colorf {
    pub r: f64,
    pub g: f64,
    pub b: f64,
    pub a: f64,
}

impl Colorf {
    /// Returns a `Colorf` with all channel components set to zero.
    pub fn zero() -> Colorf {
        Colorf {
            r: 0.,
            g: 0.,
            b: 0.,
            a: 0.,
        }
    }

    /// Returns the dot product of two `Colorf`s.
    pub fn dot(&self, rhs: &Colorf) -> f64 {
        self.r * rhs.r + self.g * rhs.g + self.b * rhs.b + self.a * rhs.a
    }

    /// Returns the magnitude (vector length) of a `Colorf`.
    pub fn abs(&self) -> f64 {
        self.dot(self).sqrt()
    }

    /// Returns a new `Colorf` with each color component raised to the given power.
    pub fn pow(&self, e: f64) -> Colorf {
        Colorf {
            r: self.r.max(0.0).powf(e),
            g: self.g.max(0.0).powf(e),
            b: self.b.max(0.0).powf(e),
            a: self.a.max(0.0).powf(e),
        }
    }
}

impl Add for Colorf {
    type Output = Colorf;
    fn add(self, rhs: Colorf) -> Colorf {
        Colorf {
            r: self.r + rhs.r,
            g: self.g + rhs.g,
            b: self.b + rhs.b,
            a: self.a + rhs.a,
        }
    }
}

impl Add<f64> for Colorf {
    type Output = Colorf;
    fn add(self, rhs: f64) -> Colorf {
        Colorf {
            r: self.r + rhs,
            g: self.g + rhs,
            b: self.b + rhs,
            a: self.a + rhs,
        }
    }
}

impl AddAssign for Colorf {
    fn add_assign(&mut self, rhs: Colorf) {
        self.r += rhs.r;
        self.g += rhs.g;
        self.b += rhs.b;
        self.a += rhs.a;
    }
}

impl Sub for Colorf {
    type Output = Colorf;
    fn sub(self, rhs: Colorf) -> Colorf {
        Colorf {
            r: self.r - rhs.r,
            g: self.g - rhs.g,
            b: self.b - rhs.b,
            a: self.a - rhs.a,
        }
    }
}

impl Mul<f64> for Colorf {
    type Output = Colorf;
    fn mul(self, rhs: f64) -> Colorf {
        Colorf {
            r: self.r * rhs,
            g: self.g * rhs,
            b: self.b * rhs,
            a: self.a * rhs,
        }
    }
}

impl MulAssign<f64> for Colorf {
    fn mul_assign(&mut self, rhs: f64) {
        self.r *= rhs;
        self.g *= rhs;
        self.b *= rhs;
        self.a *= rhs;
    }
}

impl Mul for Colorf {
    type Output = Colorf;
    fn mul(self, rhs: Colorf) -> Colorf {
        Colorf {
            r: self.r * rhs.r,
            g: self.g * rhs.g,
            b: self.b * rhs.b,
            a: self.a * rhs.a,
        }
    }
}

impl Div for Colorf {
    type Output = Colorf;
    fn div(self, rhs: Colorf) -> Colorf {
        Colorf {
            r: self.r / rhs.r,
            g: self.g / rhs.g,
            b: self.b / rhs.b,
            a: self.a / rhs.a,
        }
    }
}