color/
rgb.rs

1// Copyright 2013 The color-rs developers. For a full listing of the authors,
2// refer to the AUTHORS file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use num_traits::{self, Zero, Saturating, NumCast, Num, Float};
17use std::{borrow::{Borrow, BorrowMut}, ops::{Mul, Div, Add, Sub, Index, IndexMut}};
18use std::marker::PhantomData;
19use std::mem;
20use color_space::{TransferFunction, Srgb, LinearRgb, MatrixColorSpace, D65};
21use angle::*;
22
23use {Color, FloatColor};
24use {Channel, FloatChannel};
25use {Hsv, ToHsv};
26use {Luma, ToLuma};
27use xyz::{Xyz, ToXyz};
28use alpha::{ToRgba, Rgba};
29use std::fmt::{self, Debug};
30
31use crate::{oklab::{OkLab, ToOkLab}, ToHsl, Hsl};
32
33#[derive(Serialize, Deserialize)]
34pub struct Rgb<T = u8, S = Srgb> { pub r: T, pub g: T, pub b: T, standard: PhantomData<S> }
35
36impl<T: Clone,S> Clone for Rgb<T, S>{
37    fn clone(&self) -> Rgb<T, S>{
38        Rgb{ r: self.r.clone(), g: self.g.clone(), b: self.b.clone(), standard: PhantomData }
39    }
40}
41
42impl<T: Copy, S> Copy for Rgb<T, S>{}
43
44impl<N: Clone + PartialEq + Num + NumCast, S> PartialEq for Rgb<N, S>{
45	#[inline]
46	fn eq(&self, other: &Rgb<N, S>) -> bool{
47		self.r.eq(&other.r) && self.g.eq(&other.g) && self.b.eq(&other.b)
48	}
49}
50
51impl<N: Clone + PartialEq + Eq + Num + NumCast, S> Eq for Rgb<N, S>{}
52
53impl<T: Debug, S: Default + Debug> Debug for Rgb<T,S>{
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        f.debug_struct("Rgb")
56            .field("r", &self.r)
57            .field("g", &self.g)
58            .field("b", &self.b)
59            .field("standard", &S::default())
60            .finish()
61    }
62}
63
64#[derive(Serialize, Deserialize)]
65pub struct Rg<T = u8, S = Srgb> { pub r: T, pub g: T, pub standard: PhantomData<S> }
66
67impl<T, S> Rg<T, S>{
68    pub const fn new(r: T, g: T) -> Rg<T,S>{
69        Rg{r, g, standard: PhantomData}
70    }
71}
72
73impl<T: Clone,S> Clone for Rg<T, S>{
74    fn clone(&self) -> Rg<T, S>{
75        Rg{ r: self.r.clone(), g: self.g.clone(), standard: PhantomData }
76    }
77}
78
79impl<T: Copy, S> Copy for Rg<T, S>{}
80
81impl<N: Clone + PartialEq + Num + NumCast, S> PartialEq for Rg<N, S>{
82	#[inline]
83	fn eq(&self, other: &Rg<N, S>) -> bool{
84		self.r.eq(&other.r) && self.g.eq(&other.g)
85	}
86}
87
88impl<N: Clone + PartialEq + Eq + Num + NumCast, S> Eq for Rg<N, S>{}
89
90impl<T: Debug, S: Default + Debug> Debug for Rg<T,S>{
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92        f.debug_struct("Rg")
93            .field("r", &self.r)
94            .field("g", &self.g)
95            .field("standard", &S::default())
96            .finish()
97    }
98}
99
100fn cast<T: num_traits::NumCast, U: num_traits::NumCast>(n: T) -> U {
101    num_traits::cast(n).unwrap()
102}
103
104impl<T, S> Rgb<T, S> {
105    #[inline]
106    pub const fn new(r: T, g: T, b: T) -> Rgb<T, S> {
107        Rgb { r: r, g: g, b: b, standard: PhantomData }
108    }
109}
110
111impl<T: Channel, S: TransferFunction> Rgb<T, S> {
112    pub fn from_hex(hex: u32) -> Rgb<T, S> {
113        let r = hex >> 16 & 0xFF;
114        let g = hex >> 8 & 0xFF;
115        let b = hex & 0xFF;
116        Rgb::<u8, S>::new(r as u8, g as u8, b as u8).to_rgb()
117    }
118
119    #[inline]
120    pub fn rg(&self) -> Rg<T, S> {
121        Rg{r: self.r, g: self.g, standard: PhantomData}
122    }
123
124    #[inline]
125    pub fn rb(&self) -> Rg<T, S> {
126        Rg{r: self.r, g: self.b, standard: PhantomData}
127    }
128
129    #[inline]
130    pub fn gr(&self) -> Rg<T, S> {
131        Rg{r: self.g, g: self.r, standard: PhantomData}
132    }
133
134    #[inline]
135    pub fn gb(&self) -> Rg<T, S> {
136        Rg{r: self.g, g: self.b, standard: PhantomData}
137    }
138
139    #[inline]
140    pub fn br(&self) -> Rg<T, S> {
141        Rg{r: self.b, g: self.r, standard: PhantomData}
142    }
143
144    #[inline]
145    pub fn bg(&self) -> Rg<T, S> {
146        Rg{r: self.b, g: self.g, standard: PhantomData}
147    }
148
149    #[inline]
150    pub fn rgb(&self) -> Rgb<T, S> {
151        Rgb{r: self.r, g: self.g, b: self.b, standard: PhantomData}
152    }
153
154    #[inline]
155    pub fn rbg(&self) -> Rgb<T, S> {
156        Rgb{r: self.r, g: self.b, b: self.g, standard: PhantomData}
157    }
158
159    #[inline]
160    pub fn bgr(&self) -> Rgb<T, S> {
161        Rgb{r: self.b, g: self.g, b: self.r, standard: PhantomData}
162    }
163
164    #[inline]
165    pub fn brg(&self) -> Rgb<T, S> {
166        Rgb{r: self.b, g: self.r, b: self.g, standard: PhantomData}
167    }
168
169    #[inline]
170    pub fn grb(&self) -> Rgb<T, S> {
171        Rgb{r: self.g, g: self.r, b: self.b, standard: PhantomData}
172    }
173
174    #[inline]
175    pub fn gbr(&self) -> Rgb<T, S> {
176        Rgb{r: self.g, g: self.b, b: self.r, standard: PhantomData}
177    }
178}
179
180impl<T: Channel, S: TransferFunction> Rgb<T, S> {
181    pub fn to_standard<S2: TransferFunction>(&self) -> Rgb<T, S2>{
182        if std::any::TypeId::of::<S>() != std::any::TypeId::of::<S2>(){
183            let r = S2::from_linear(S::to_linear(self.r.to_nearest_precision_float()));
184            let g = S2::from_linear(S::to_linear(self.g.to_nearest_precision_float()));
185            let b = S2::from_linear(S::to_linear(self.b.to_nearest_precision_float()));
186            Rgb::new(r.to_channel(), g.to_channel(), b.to_channel())
187        }else{
188            Rgb::new(self.r, self.g, self.b)
189        }
190    }
191
192    pub fn to_linear(&self) -> Rgb<T, LinearRgb>{
193        let r = S::to_linear(self.r.to_nearest_precision_float());
194        let g = S::to_linear(self.g.to_nearest_precision_float());
195        let b = S::to_linear(self.b.to_nearest_precision_float());
196        Rgb::new(r.to_channel(), g.to_channel(), b.to_channel())
197    }
198}
199
200#[macro_export]
201macro_rules! rgb{
202    ( $r: expr, $g: expr, $b: expr ) => {
203        $crate::Rgb::<_, $crate::color_space::Srgb>::new( $r, $g, $b )
204    };
205    ( $rg: expr, $b: expr ) => {
206        $crate::Rgb::<_, $crate::color_space::Srgb>::new( $rg.r, $rg.g, $b )
207    };
208    ( $r: expr, $gb: expr ) => {
209        $crate::Rgb::<_, $crate::color_space::Srgb>::new( $r, $gb.r, $gb.g )
210    };
211    ( $num: expr ) => {
212        $crate::Rgb::<_, $crate::color_space::Srgb>::new( $num, $num, $num )
213    };
214}
215
216#[macro_export]
217macro_rules! rgb_linear{
218    ( $r: expr, $g: expr, $b: expr ) => {
219        $crate::Rgb::<_, $crate::color_space::LinearRgb>::new( $r, $g, $b )
220    };
221    ( $rg: expr, $b: expr ) => {
222        $crate::Rgb::<_, $crate::color_space::LinearRgb>::new( $rg.r, $rg.g, $b )
223    };
224    ( $r: expr, $gb: expr ) => {
225        $crate::Rgb::<_, $crate::color_space::LinearRgb>::new( $r, $gb.r, $gb.g )
226    };
227    ( $num: expr ) => {
228        $crate::Rgb::<_, $crate::color_space::LinearRgb>::new( $num, $num, $num )
229    };
230}
231
232impl<T: Channel, S> Color<T> for Rgb<T, S> {
233    /// Clamps the components of the color to the range `(lo,hi)`.
234    #[inline]
235    fn clamp_s(self, lo: T, hi: T) -> Rgb<T, S> {
236        Rgb::new(self.r.clamp(lo, hi),
237                 self.g.clamp(lo, hi),
238                 self.b.clamp(lo, hi))
239    }
240
241    /// Clamps the components of the color component-wise between `lo` and `hi`.
242    #[inline]
243    fn clamp_c(self, lo: Rgb<T, S>, hi: Rgb<T, S>) -> Rgb<T, S> {
244        Rgb::new(self.r.clamp(lo.r, hi.r),
245                 self.g.clamp(lo.g, hi.g),
246                 self.b.clamp(lo.b, hi.b))
247    }
248
249    /// Inverts the color.
250    #[inline]
251    fn inverse(self) -> Rgb<T, S> {
252        Rgb::new(self.r.invert_channel(),
253                 self.g.invert_channel(),
254                 self.b.invert_channel())
255    }
256
257    #[inline]
258    fn mix(self, other: Self, value: T) -> Self {
259        Rgb::new(self.r.mix(other.r, value),
260             self.g.mix(other.g, value),
261             self.b.mix(other.b, value))
262    }
263}
264
265impl<T: FloatChannel, S> FloatColor<T> for Rgb<T, S> {
266    /// Clamps the components of the color to the range `(0,1)`.
267    #[inline]
268    fn saturate(self) -> Rgb<T, S> {
269        Rgb::new(self.r.saturate(),
270                 self.g.saturate(),
271                 self.b.saturate())
272    }
273}
274
275pub trait ToRgb {
276    type Standard: TransferFunction;
277    fn to_rgb<U:Channel>(&self) -> Rgb<U, Self::Standard>;
278}
279
280impl ToRgb for u32 {
281    type Standard = Srgb;
282    #[inline]
283    fn to_rgb<U:Channel>(&self) -> Rgb<U, Srgb> {
284        let r: u8 = cast((*self >> 16) & 0xff);
285        let g: u8 = cast((*self >> 8) & 0xff);
286        let b: u8 = cast((*self >> 0) & 0xff);
287        let r: U = Channel::from(r);
288        let g: U = Channel::from(g);
289        let b: U = Channel::from(b);
290        rgb!(r, g, b)
291    }
292}
293
294impl<T: Channel, S: TransferFunction> ToRgb for Rgb<T,S> {
295    type Standard = S;
296    #[inline]
297    fn to_rgb<U:Channel>(&self) -> Rgb<U,S> {
298        Rgb::new(self.r.to_channel(),
299                 self.g.to_channel(),
300                 self.b.to_channel())
301    }
302}
303
304impl<T: Channel, S: TransferFunction> ToLuma for Rgb<T, S> {
305    type Standard = S;
306    fn to_luma<U: Channel>(&self) -> Luma<U, S> {
307        Luma::new(Channel::from(
308            self.r.to_nearest_precision_float() * cast::<f32, <T as Channel>::NearestFloat>(0.2126)
309                + self.g.to_nearest_precision_float() * cast::<f32, <T as Channel>::NearestFloat>(0.7152)
310                + self.b.to_nearest_precision_float() * cast::<f32, <T as Channel>::NearestFloat>(0.0722)
311        ))
312    }
313}
314
315impl<T: Channel, S: TransferFunction> ToRgba for Rgb<T, S> {
316    type Standard = S;
317
318    #[inline]
319    fn to_rgba<U: Channel>(&self) -> Rgba<U, S>{
320        Rgba{c: self.to_rgb(), a: 1.0f32.to_channel()}
321    }
322}
323
324impl<T:Channel, S: TransferFunction> ToHsv for Rgb<T, S> {
325    type Standard = S;
326    #[inline]
327    fn to_hsv<U:Channel + NumCast + Num>(&self) -> Hsv<U, S> {
328        // Algorithm taken from the Wikipedia article on HSL and Hsv:
329        // http://en.wikipedia.org/wiki/HSL_and_Hsv#From_Hsv
330
331        let rgb_u = self.to_rgb::<U>();
332
333        let mx = cast(cast::<U,f64>(rgb_u.r).max(cast(rgb_u.g)).max(cast(rgb_u.b)));
334        let mn = cast(cast::<U,f64>(rgb_u.r).min(cast(rgb_u.g)).min(cast(rgb_u.b)));
335        let chr = mx - mn;
336
337        if chr != Zero::zero() {
338            let h =
339                if      rgb_u.r == mx       { ((rgb_u.g - rgb_u.b) / chr) % cast(6u8) }
340                else if rgb_u.g == mx       { ((rgb_u.b - rgb_u.r) / chr) + cast(2u8) }
341                else    /* rgb_u.b == mx */ { ((rgb_u.r - rgb_u.g) / chr) + cast(4u8) }
342            * cast(60u8);
343
344            let s = chr / mx;
345
346            Hsv::new(Deg(h), s, mx)
347
348        } else {
349            Hsv::new(Zero::zero(), Zero::zero(),mx)
350        }
351    }
352}
353
354impl<T:Channel, S: TransferFunction> ToHsl for Rgb<T, S> {
355    type Standard = S;
356    #[inline]
357    fn to_hsl<U:Channel + NumCast + Num>(&self) -> Hsl<U, S> {
358        let rgb_f64 = self.to_rgb::<f64>();
359
360        let mx = rgb_f64.r.channel_max(rgb_f64.g).channel_max(rgb_f64.b);
361        let mn = rgb_f64.r.channel_min(rgb_f64.g).channel_min(rgb_f64.b);
362        let d = mx - mn;
363        let l = (mx + mn) * 0.5;
364        if d != Zero::zero() {
365            let s = if l < 0.5 { d / (mx + mn) } else { d / (2. - mx - mn ) } ;
366            let h =
367                if      rgb_f64.r == mx       { (rgb_f64.g - rgb_f64.b) / d }
368                else if rgb_f64.g == mx       { ((rgb_f64.b - rgb_f64.r) / d) + 2. }
369                else    /* rgb_u.b == mx */ { ((rgb_f64.r - rgb_f64.g) / d) + 4. }
370            * 60.;
371
372            Hsl::new(angle::cast(Deg(h)).unwrap(), Channel::from(s), Channel::from(l))
373        } else {
374            Hsl::new(Zero::zero(), Zero::zero(), Channel::from(l))
375        }
376    }
377}
378
379impl<T: Channel, S: MatrixColorSpace + TransferFunction> ToXyz for Rgb<T, S> {
380    type WhitePoint = D65;
381    fn to_xyz<U: Channel + Float>(&self) -> Xyz<U, D65> {
382        let rgb = self.to_rgb().to_linear();
383        let xyz = S::to_xyz_matrix() * rgb.into();
384        Xyz::new(xyz[0], xyz[1], xyz[2])
385    }
386}
387
388impl <T: Channel + Float + NumCast, S: MatrixColorSpace + TransferFunction> ToOkLab for Rgb<T, S> {
389    fn to_oklab<U: Channel>(&self) -> OkLab<U> {
390        let c: Rgb<T,_> = self.to_rgb().to_linear();
391        let l = cast::<f64, T>(0.4122214708) * c.r + cast::<f64, T>(0.5363325363) * c.g + cast::<f64, T>(0.0514459929) * c.b;
392        let m = cast::<f64, T>(0.2119034982) * c.r + cast::<f64, T>(0.6806995451) * c.g + cast::<f64, T>(0.1073969566) * c.b;
393        let s = cast::<f64, T>(0.0883024619) * c.r + cast::<f64, T>(0.2817188376) * c.g + cast::<f64, T>(0.6299787005) * c.b;
394
395        let l_ = l.cbrt();
396        let m_ = m.cbrt();
397        let s_ = s.cbrt();
398
399        OkLab {
400            l: (cast::<f64, T>(0.2104542553)*l_ + cast::<f64, T>(0.7936177850)*m_ - cast::<f64, T>(0.0040720468)*s_).to_channel(),
401            a: (cast::<f64, T>(1.9779984951)*l_ - cast::<f64, T>(2.4285922050)*m_ + cast::<f64, T>(0.4505937099)*s_).to_channel(),
402            b: (cast::<f64, T>(0.0259040371)*l_ + cast::<f64, T>(0.7827717662)*m_ - cast::<f64, T>(0.8086757660)*s_).to_channel(),
403        }
404    }
405}
406
407impl<T: Channel, S> Mul for Rgb<T, S> {
408    type Output = Rgb<T, S>;
409
410    #[inline]
411    fn mul(self, rhs: Rgb<T, S>) -> Rgb<T, S> {
412        Rgb::new(self.r.normalized_mul(rhs.r),
413                 self.g.normalized_mul(rhs.g),
414                 self.b.normalized_mul(rhs.b))
415    }
416}
417
418impl<T: Channel + Mul<T,Output=T>, S> Mul<T> for Rgb<T, S> {
419    type Output = Rgb<T, S>;
420
421    #[inline]
422    fn mul(self, rhs: T) -> Rgb<T, S> {
423        Rgb::new(self.r * rhs,
424                 self.g * rhs,
425                 self.b * rhs)
426    }
427}
428
429
430impl<T: Channel, S> Div for Rgb<T, S> {
431    type Output = Rgb<T, S>;
432
433    #[inline]
434    fn div(self, rhs: Rgb<T, S>) -> Rgb<T, S> {
435        Rgb::new(self.r.normalized_div(rhs.r),
436                 self.g.normalized_div(rhs.g),
437                 self.b.normalized_div(rhs.b))
438    }
439}
440
441impl<T: Channel + Div<T,Output=T>, S> Div<T> for Rgb<T, S> {
442    type Output = Rgb<T, S>;
443
444    #[inline]
445    fn div(self, rhs: T) -> Rgb<T, S> {
446        Rgb::new(self.r / rhs,
447                 self.g / rhs,
448                 self.b / rhs)
449    }
450}
451
452impl<T: Channel + Add<T,Output=T>, S> Add for Rgb<T, S> {
453    type Output = Rgb<T, S>;
454
455    #[inline]
456    fn add(self, rhs: Rgb<T, S>) -> Rgb<T, S> {
457        Rgb::new(self.r + rhs.r,
458                 self.g + rhs.g,
459                 self.b + rhs.b)
460    }
461}
462
463impl<T: Channel + Sub<T,Output=T>, S> Sub for Rgb<T, S> {
464    type Output = Rgb<T, S>;
465
466    #[inline]
467    fn sub(self, rhs: Rgb<T, S>) -> Rgb<T, S> {
468        Rgb::new(self.r - rhs.r,
469                 self.g - rhs.g,
470                 self.b - rhs.b)
471    }
472}
473
474impl<T: Channel + Saturating, S> Saturating for Rgb<T, S> {
475    fn saturating_add(self, v: Rgb<T, S>) -> Rgb<T, S> {
476        Rgb::new(self.r.saturating_add(v.r),
477            self.g.saturating_add(v.g),
478            self.b.saturating_add(v.b))
479    }
480
481    fn saturating_sub(self, v: Rgb<T, S>) -> Rgb<T, S> {
482        Rgb::new(self.r.saturating_sub(v.r),
483            self.g.saturating_sub(v.g),
484            self.b.saturating_sub(v.b))
485    }
486}
487
488impl<T, S> Index<usize> for Rgb<T, S> {
489    type Output = T;
490    fn index<'a>(&'a self, index: usize) -> &'a T {
491        self.as_ref().index(index)
492    }
493}
494
495impl<T, S> IndexMut<usize> for Rgb<T, S> {
496    fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut T {
497        self.as_mut().index_mut(index)
498    }
499}
500
501impl<T, S> AsRef<[T;3]> for Rgb<T, S> {
502    fn as_ref(&self) -> &[T;3] {
503        unsafe{ mem::transmute(self) }
504    }
505}
506
507impl<T, S> AsMut<[T;3]> for Rgb<T, S> {
508    fn as_mut(&mut self) -> &mut [T;3] {
509        unsafe{ mem::transmute(self) }
510    }
511}
512
513impl<T, S> Borrow<[T;3]> for Rgb<T, S> {
514    fn borrow(&self) -> &[T;3] {
515        unsafe{ mem::transmute(self)}
516    }
517}
518
519impl<T, S> BorrowMut<[T;3]> for Rgb<T, S> {
520    fn borrow_mut(&mut self) -> &mut [T;3] {
521        unsafe{ mem::transmute(self)}
522    }
523}
524
525/// SVG 1.0 color constants: http://www.w3.org/TR/SVG/types.html#ColorKeywords
526pub mod consts {
527    use Rgb;
528    use color_space::Srgb;
529
530    pub static ALICEBLUE:               Rgb<u8, Srgb> = Rgb::new(0xF0, 0xF8, 0xFF);
531    pub static ANTIQUEWHITE:            Rgb<u8, Srgb> = Rgb::new(0xFA, 0xEB, 0xD7);
532    pub static AQUA:                    Rgb<u8, Srgb> = Rgb::new(0x00, 0xFF, 0xFF);
533    pub static AQUAMARINE:              Rgb<u8, Srgb> = Rgb::new(0x7F, 0xFF, 0xD4);
534    pub static AZURE:                   Rgb<u8, Srgb> = Rgb::new(0xF0, 0xFF, 0xFF);
535    pub static BEIGE:                   Rgb<u8, Srgb> = Rgb::new(0xF5, 0xF5, 0xDC);
536    pub static BISQUE:                  Rgb<u8, Srgb> = Rgb::new(0xFF, 0xE4, 0xC4);
537    pub static BLACK:                   Rgb<u8, Srgb> = Rgb::new(0x00, 0x00, 0x00);
538    pub static BLANCHEDALMOND:          Rgb<u8, Srgb> = Rgb::new(0xFF, 0xEB, 0xCD);
539    pub static BLUE:                    Rgb<u8, Srgb> = Rgb::new(0x00, 0x00, 0xFF);
540    pub static BLUEVIOLET:              Rgb<u8, Srgb> = Rgb::new(0x8A, 0x2B, 0xE2);
541    pub static BROWN:                   Rgb<u8, Srgb> = Rgb::new(0xA5, 0x2A, 0x2A);
542    pub static BURLYWOOD:               Rgb<u8, Srgb> = Rgb::new(0xDE, 0xB8, 0x87);
543    pub static CADETBLUE:               Rgb<u8, Srgb> = Rgb::new(0x5F, 0x9E, 0xA0);
544    pub static CHARTREUSE:              Rgb<u8, Srgb> = Rgb::new(0x7F, 0xFF, 0x00);
545    pub static CHOCOLATE:               Rgb<u8, Srgb> = Rgb::new(0xD2, 0x69, 0x1E);
546    pub static CORAL:                   Rgb<u8, Srgb> = Rgb::new(0xFF, 0x7F, 0x50);
547    pub static CORNFLOWERBLUE:          Rgb<u8, Srgb> = Rgb::new(0x64, 0x95, 0xED);
548    pub static CORNSILK:                Rgb<u8, Srgb> = Rgb::new(0xFF, 0xF8, 0xDC);
549    pub static CRIMSON:                 Rgb<u8, Srgb> = Rgb::new(0xDC, 0x14, 0x3C);
550    pub static CYAN:                    Rgb<u8, Srgb> = Rgb::new(0x00, 0xFF, 0xFF);
551    pub static DARKBLUE:                Rgb<u8, Srgb> = Rgb::new(0x00, 0x00, 0x8B);
552    pub static DARKCYAN:                Rgb<u8, Srgb> = Rgb::new(0x00, 0x8B, 0x8B);
553    pub static DARKGOLDENROD:           Rgb<u8, Srgb> = Rgb::new(0xB8, 0x86, 0x0B);
554    pub static DARKGRAY:                Rgb<u8, Srgb> = Rgb::new(0xA9, 0xA9, 0xA9);
555    pub static DARKGREEN:               Rgb<u8, Srgb> = Rgb::new(0x00, 0x64, 0x00);
556    pub static DARKKHAKI:               Rgb<u8, Srgb> = Rgb::new(0xBD, 0xB7, 0x6B);
557    pub static DARKMAGENTA:             Rgb<u8, Srgb> = Rgb::new(0x8B, 0x00, 0x8B);
558    pub static DARKOLIVEGREEN:          Rgb<u8, Srgb> = Rgb::new(0x55, 0x6B, 0x2F);
559    pub static DARKORANGE:              Rgb<u8, Srgb> = Rgb::new(0xFF, 0x8C, 0x00);
560    pub static DARKORCHID:              Rgb<u8, Srgb> = Rgb::new(0x99, 0x32, 0xCC);
561    pub static DARKRED:                 Rgb<u8, Srgb> = Rgb::new(0x8B, 0x00, 0x00);
562    pub static DARKSALMON:              Rgb<u8, Srgb> = Rgb::new(0xE9, 0x96, 0x7A);
563    pub static DARKSEAGREEN:            Rgb<u8, Srgb> = Rgb::new(0x8F, 0xBC, 0x8F);
564    pub static DARKSLATEBLUE:           Rgb<u8, Srgb> = Rgb::new(0x48, 0x3D, 0x8B);
565    pub static DARKSLATEGRAY:           Rgb<u8, Srgb> = Rgb::new(0x2F, 0x4F, 0x4F);
566    pub static DARKTURQUOISE:           Rgb<u8, Srgb> = Rgb::new(0x00, 0xCE, 0xD1);
567    pub static DARKVIOLET:              Rgb<u8, Srgb> = Rgb::new(0x94, 0x00, 0xD3);
568    pub static DEEPPINK:                Rgb<u8, Srgb> = Rgb::new(0xFF, 0x14, 0x93);
569    pub static DEEPSKYBLUE:             Rgb<u8, Srgb> = Rgb::new(0x00, 0xBF, 0xFF);
570    pub static DIMGRAY:                 Rgb<u8, Srgb> = Rgb::new(0x69, 0x69, 0x69);
571    pub static DODGERBLUE:              Rgb<u8, Srgb> = Rgb::new(0x1E, 0x90, 0xFF);
572    pub static FIREBRICK:               Rgb<u8, Srgb> = Rgb::new(0xB2, 0x22, 0x22);
573    pub static FLORALWHITE:             Rgb<u8, Srgb> = Rgb::new(0xFF, 0xFA, 0xF0);
574    pub static FORESTGREEN:             Rgb<u8, Srgb> = Rgb::new(0x22, 0x8B, 0x22);
575    pub static FUCHSIA:                 Rgb<u8, Srgb> = Rgb::new(0xFF, 0x00, 0xFF);
576    pub static GAINSBORO:               Rgb<u8, Srgb> = Rgb::new(0xDC, 0xDC, 0xDC);
577    pub static GHOSTWHITE:              Rgb<u8, Srgb> = Rgb::new(0xF8, 0xF8, 0xFF);
578    pub static GOLD:                    Rgb<u8, Srgb> = Rgb::new(0xFF, 0xD7, 0x00);
579    pub static GOLDENROD:               Rgb<u8, Srgb> = Rgb::new(0xDA, 0xA5, 0x20);
580    pub static GRAY:                    Rgb<u8, Srgb> = Rgb::new(0x80, 0x80, 0x80);
581    pub static GREEN:                   Rgb<u8, Srgb> = Rgb::new(0x00, 0x80, 0x00);
582    pub static GREENYELLOW:             Rgb<u8, Srgb> = Rgb::new(0xAD, 0xFF, 0x2F);
583    pub static HONEYDEW:                Rgb<u8, Srgb> = Rgb::new(0xF0, 0xFF, 0xF0);
584    pub static HOTPINK:                 Rgb<u8, Srgb> = Rgb::new(0xFF, 0x69, 0xB4);
585    pub static INDIANRED:               Rgb<u8, Srgb> = Rgb::new(0xCD, 0x5C, 0x5C);
586    pub static INDIGO:                  Rgb<u8, Srgb> = Rgb::new(0x4B, 0x00, 0x82);
587    pub static IVORY:                   Rgb<u8, Srgb> = Rgb::new(0xFF, 0xFF, 0xF0);
588    pub static KHAKI:                   Rgb<u8, Srgb> = Rgb::new(0xF0, 0xE6, 0x8C);
589    pub static LAVENDER:                Rgb<u8, Srgb> = Rgb::new(0xE6, 0xE6, 0xFA);
590    pub static LAVENDERBLUSH:           Rgb<u8, Srgb> = Rgb::new(0xFF, 0xF0, 0xF5);
591    pub static LAWNGREEN:               Rgb<u8, Srgb> = Rgb::new(0x7C, 0xFC, 0x00);
592    pub static LEMONCHIFFON:            Rgb<u8, Srgb> = Rgb::new(0xFF, 0xFA, 0xCD);
593    pub static LIGHTBLUE:               Rgb<u8, Srgb> = Rgb::new(0xAD, 0xD8, 0xE6);
594    pub static LIGHTCORAL:              Rgb<u8, Srgb> = Rgb::new(0xF0, 0x80, 0x80);
595    pub static LIGHTCYAN:               Rgb<u8, Srgb> = Rgb::new(0xE0, 0xFF, 0xFF);
596    pub static LIGHTGOLDENRODYELLOW:    Rgb<u8, Srgb> = Rgb::new(0xFA, 0xFA, 0xD2);
597    pub static LIGHTGREEN:              Rgb<u8, Srgb> = Rgb::new(0x90, 0xEE, 0x90);
598    pub static LIGHTGREY:               Rgb<u8, Srgb> = Rgb::new(0xD3, 0xD3, 0xD3);
599    pub static LIGHTPINK:               Rgb<u8, Srgb> = Rgb::new(0xFF, 0xB6, 0xC1);
600    pub static LIGHTSALMON:             Rgb<u8, Srgb> = Rgb::new(0xFF, 0xA0, 0x7A);
601    pub static LIGHTSEAGREEN:           Rgb<u8, Srgb> = Rgb::new(0x20, 0xB2, 0xAA);
602    pub static LIGHTSKYBLUE:            Rgb<u8, Srgb> = Rgb::new(0x87, 0xCE, 0xFA);
603    pub static LIGHTSLATEGRAY:          Rgb<u8, Srgb> = Rgb::new(0x77, 0x88, 0x99);
604    pub static LIGHTSTEELBLUE:          Rgb<u8, Srgb> = Rgb::new(0xB0, 0xC4, 0xDE);
605    pub static LIGHTYELLOW:             Rgb<u8, Srgb> = Rgb::new(0xFF, 0xFF, 0xE0);
606    pub static LIME:                    Rgb<u8, Srgb> = Rgb::new(0x00, 0xFF, 0x00);
607    pub static LIMEGREEN:               Rgb<u8, Srgb> = Rgb::new(0x32, 0xCD, 0x32);
608    pub static LINEN:                   Rgb<u8, Srgb> = Rgb::new(0xFA, 0xF0, 0xE6);
609    pub static MAGENTA:                 Rgb<u8, Srgb> = Rgb::new(0xFF, 0x00, 0xFF);
610    pub static MAROON:                  Rgb<u8, Srgb> = Rgb::new(0x80, 0x00, 0x00);
611    pub static MEDIUMAQUAMARINE:        Rgb<u8, Srgb> = Rgb::new(0x66, 0xCD, 0xAA);
612    pub static MEDIUMBLUE:              Rgb<u8, Srgb> = Rgb::new(0x00, 0x00, 0xCD);
613    pub static MEDIUMORCHID:            Rgb<u8, Srgb> = Rgb::new(0xBA, 0x55, 0xD3);
614    pub static MEDIUMPURPLE:            Rgb<u8, Srgb> = Rgb::new(0x93, 0x70, 0xDB);
615    pub static MEDIUMSEAGREEN:          Rgb<u8, Srgb> = Rgb::new(0x3C, 0xB3, 0x71);
616    pub static MEDIUMSLATEBLUE:         Rgb<u8, Srgb> = Rgb::new(0x7B, 0x68, 0xEE);
617    pub static MEDIUMSPRINGGREEN:       Rgb<u8, Srgb> = Rgb::new(0x00, 0xFA, 0x9A);
618    pub static MEDIUMTURQUOISE:         Rgb<u8, Srgb> = Rgb::new(0x48, 0xD1, 0xCC);
619    pub static MEDIUMVIOLETRED:         Rgb<u8, Srgb> = Rgb::new(0xC7, 0x15, 0x85);
620    pub static MIDNIGHTBLUE:            Rgb<u8, Srgb> = Rgb::new(0x19, 0x19, 0x70);
621    pub static MINTCREAM:               Rgb<u8, Srgb> = Rgb::new(0xF5, 0xFF, 0xFA);
622    pub static MISTYROSE:               Rgb<u8, Srgb> = Rgb::new(0xFF, 0xE4, 0xE1);
623    pub static MOCCASIN:                Rgb<u8, Srgb> = Rgb::new(0xFF, 0xE4, 0xB5);
624    pub static NAVAJOWHITE:             Rgb<u8, Srgb> = Rgb::new(0xFF, 0xDE, 0xAD);
625    pub static NAVY:                    Rgb<u8, Srgb> = Rgb::new(0x00, 0x00, 0x80);
626    pub static OLDLACE:                 Rgb<u8, Srgb> = Rgb::new(0xFD, 0xF5, 0xE6);
627    pub static OLIVE:                   Rgb<u8, Srgb> = Rgb::new(0x80, 0x80, 0x00);
628    pub static OLIVEDRAB:               Rgb<u8, Srgb> = Rgb::new(0x6B, 0x8E, 0x23);
629    pub static ORANGE:                  Rgb<u8, Srgb> = Rgb::new(0xFF, 0xA5, 0x00);
630    pub static ORANGERED:               Rgb<u8, Srgb> = Rgb::new(0xFF, 0x45, 0x00);
631    pub static ORCHID:                  Rgb<u8, Srgb> = Rgb::new(0xDA, 0x70, 0xD6);
632    pub static PALEGOLDENROD:           Rgb<u8, Srgb> = Rgb::new(0xEE, 0xE8, 0xAA);
633    pub static PALEGREEN:               Rgb<u8, Srgb> = Rgb::new(0x98, 0xFB, 0x98);
634    pub static PALEVIOLETRED:           Rgb<u8, Srgb> = Rgb::new(0xDB, 0x70, 0x93);
635    pub static PAPAYAWHIP:              Rgb<u8, Srgb> = Rgb::new(0xFF, 0xEF, 0xD5);
636    pub static PEACHPUFF:               Rgb<u8, Srgb> = Rgb::new(0xFF, 0xDA, 0xB9);
637    pub static PERU:                    Rgb<u8, Srgb> = Rgb::new(0xCD, 0x85, 0x3F);
638    pub static PINK:                    Rgb<u8, Srgb> = Rgb::new(0xFF, 0xC0, 0xCB);
639    pub static PLUM:                    Rgb<u8, Srgb> = Rgb::new(0xDD, 0xA0, 0xDD);
640    pub static POWDERBLUE:              Rgb<u8, Srgb> = Rgb::new(0xB0, 0xE0, 0xE6);
641    pub static PURPLE:                  Rgb<u8, Srgb> = Rgb::new(0x80, 0x00, 0x80);
642    pub static RED:                     Rgb<u8, Srgb> = Rgb::new(0xFF, 0x00, 0x00);
643    pub static ROSYBROWN:               Rgb<u8, Srgb> = Rgb::new(0xBC, 0x8F, 0x8F);
644    pub static ROYALBLUE:               Rgb<u8, Srgb> = Rgb::new(0x41, 0x69, 0xE1);
645    pub static SADDLEBROWN:             Rgb<u8, Srgb> = Rgb::new(0x8B, 0x45, 0x13);
646    pub static SALMON:                  Rgb<u8, Srgb> = Rgb::new(0xFA, 0x80, 0x72);
647    pub static SANDYBROWN:              Rgb<u8, Srgb> = Rgb::new(0xFA, 0xA4, 0x60);
648    pub static SEAGREEN:                Rgb<u8, Srgb> = Rgb::new(0x2E, 0x8B, 0x57);
649    pub static SEASHELL:                Rgb<u8, Srgb> = Rgb::new(0xFF, 0xF5, 0xEE);
650    pub static SIENNA:                  Rgb<u8, Srgb> = Rgb::new(0xA0, 0x52, 0x2D);
651    pub static SILVER:                  Rgb<u8, Srgb> = Rgb::new(0xC0, 0xC0, 0xC0);
652    pub static SKYBLUE:                 Rgb<u8, Srgb> = Rgb::new(0x87, 0xCE, 0xEB);
653    pub static SLATEBLUE:               Rgb<u8, Srgb> = Rgb::new(0x6A, 0x5A, 0xCD);
654    pub static SLATEGRAY:               Rgb<u8, Srgb> = Rgb::new(0x70, 0x80, 0x90);
655    pub static SNOW:                    Rgb<u8, Srgb> = Rgb::new(0xFF, 0xFA, 0xFA);
656    pub static SPRINGGREEN:             Rgb<u8, Srgb> = Rgb::new(0x00, 0xFF, 0x7F);
657    pub static STEELBLUE:               Rgb<u8, Srgb> = Rgb::new(0x46, 0x82, 0xB4);
658    pub static TAN:                     Rgb<u8, Srgb> = Rgb::new(0xD2, 0xB4, 0x8C);
659    pub static TEAL:                    Rgb<u8, Srgb> = Rgb::new(0x00, 0x80, 0x80);
660    pub static THISTLE:                 Rgb<u8, Srgb> = Rgb::new(0xD8, 0xBF, 0xD8);
661    pub static TOMATO:                  Rgb<u8, Srgb> = Rgb::new(0xFF, 0x63, 0x47);
662    pub static TURQUOISE:               Rgb<u8, Srgb> = Rgb::new(0x40, 0xE0, 0xD0);
663    pub static VIOLET:                  Rgb<u8, Srgb> = Rgb::new(0xEE, 0x82, 0xEE);
664    pub static WHEAT:                   Rgb<u8, Srgb> = Rgb::new(0xF5, 0xDE, 0xB3);
665    pub static WHITE:                   Rgb<u8, Srgb> = Rgb::new(0xFF, 0xFF, 0xFF);
666    pub static WHITESMOKE:              Rgb<u8, Srgb> = Rgb::new(0xF5, 0xF5, 0xF5);
667    pub static YELLOW:                  Rgb<u8, Srgb> = Rgb::new(0xFF, 0xFF, 0x00);
668    pub static YELLOWGREEN:             Rgb<u8, Srgb> = Rgb::new(0x9A, 0xCD, 0x32);
669}
670
671#[cfg(test)]
672mod tests {
673    use {Hsv, ToHsv};
674    use {Rgb, ToRgb};
675    use FloatColor;
676    use angle::*;
677    use num_traits::Saturating;
678
679    #[test]
680    fn test_rgb_to_rgb() {
681        assert_eq!(Rgb::<u8>::new(0xA0, 0xA0, 0xA0).to_rgb::<u8>(), Rgb::<u8>::new(0xA0, 0xA0, 0xA0));
682        assert_eq!(Rgb::<u8>::new(0xA0, 0xA0, 0xA0).to_rgb::<u16>(), Rgb::<u16>::new(0xA0A0, 0xA0A0, 0xA0A0));
683    }
684
685    #[test]
686    fn test_rgb_to_hsv() {
687        assert_eq!(Rgb::<u8>::new(0xFF, 0xFF, 0xFF).to_hsv::<f32>(), Hsv::<f32>::new(Deg(0.0), 0.0, 1.0));
688        assert_eq!(Rgb::<u8>::new(0x99, 0x00, 0x00).to_hsv::<f32>(), Hsv::<f32>::new(Deg(0.0), 1.0, 0.6));
689        assert_eq!(Rgb::<u8>::new(0x00, 0x99, 0x00).to_hsv::<f32>(), Hsv::<f32>::new(Deg(120.0), 1.0, 0.6));
690        assert_eq!(Rgb::<u8>::new(0x00, 0x00, 0x99).to_hsv::<f32>(), Hsv::<f32>::new(Deg(240.0), 1.0, 0.6));
691    }
692
693    #[test]
694    fn test_rgb_ops(){
695        assert_eq!( rgb!(20u8, 20, 20) + rgb!(20, 20, 20), rgb!(40, 40, 40) );
696        assert_eq!( rgb!(254u8, 254, 254).saturating_add( rgb!(20, 20, 20) ), rgb!(255, 255, 255) );
697        assert_eq!( rgb!(20u8, 20, 20).saturating_sub( rgb!(50, 50, 50) ), rgb!(0, 0, 0) );
698        assert_eq!( rgb!(127u8, 127, 127) * rgb!(255, 255, 255), rgb!(127, 127, 127) );
699        assert_eq!( rgb!(127u8, 127, 127) / rgb!(255, 255, 255), rgb!(127, 127, 127) );
700        assert_eq!( rgb!(1.0f32, 1.0, 1.0) * 2.0, rgb!(2.0, 2.0, 2.0));
701        assert_eq!( (rgb!(1.0f32, 1.0, 1.0) * 2.0).saturate(), rgb!(1.0, 1.0, 1.0));
702    }
703}