1 use super::pixel::*;
2 use crate::alt::BGR;
3 use crate::alt::BGRA;
4 use crate::RGB;
5 use crate::RGBA;
6 use core::fmt;
7 
8 impl<T> RGB<T> {
9     /// Convenience function for creating a new pixel
10     /// The order of arguments is R,G,B
11     #[inline(always)]
new(r: T, g: T, b: T) -> Self12     pub const fn new(r: T, g: T, b: T) -> Self {
13         Self { r, g, b }
14     }
15 }
16 
17 impl<T> BGR<T> {
18     /// Convenience function for creating a new pixel
19     /// Wargning: The order of arguments is R,G,B
20     #[deprecated(note="This function has a misleading order of arguments. Use BGR{} literal instead")]
21     #[inline(always)]
new(r: T, g: T, b: T) -> Self22     pub const fn new(r: T, g: T, b: T) -> Self {
23         Self { b, g, r }
24     }
25 }
26 
27 #[cfg(feature = "as-bytes")]
28 unsafe impl<T> crate::Pod for RGB<T> where T: crate::Pod {}
29 #[cfg(feature = "as-bytes")]
30 unsafe impl<T> crate::Pod for BGR<T> where T: crate::Pod {}
31 #[cfg(feature = "as-bytes")]
32 unsafe impl<T> crate::Zeroable for RGB<T> where T: crate::Zeroable {}
33 #[cfg(feature = "as-bytes")]
34 unsafe impl<T> crate::Zeroable for BGR<T> where T: crate::Zeroable {}
35 
36 macro_rules! impl_rgb {
37     ($RGB:ident, $RGBA:ident) => {
38         impl<T: Clone> $RGB<T> {
39             /// Iterate over color components (R, G, and B)
40             #[inline(always)]
41             pub fn iter(&self) -> core::iter::Cloned<core::slice::Iter<'_, T>> {
42                 self.as_slice().iter().cloned()
43             }
44 
45             /// Convenience function for converting to RGBA
46             #[inline(always)]
47             pub fn alpha(&self, a: T) -> $RGBA<T> {
48                 $RGBA {
49                     r: self.r.clone(),
50                     g: self.g.clone(),
51                     b: self.b.clone(),
52                     a,
53                 }
54             }
55 
56             /// Convenience function for converting to RGBA with alpha channel of a different type than type of the pixels
57             #[inline(always)]
58             pub fn new_alpha<A>(&self, a: A) -> $RGBA<T, A> {
59                 $RGBA {
60                     r: self.r.clone(),
61                     g: self.g.clone(),
62                     b: self.b.clone(),
63                     a,
64                 }
65             }
66         }
67 
68         impl<T: Copy, B> ComponentMap<$RGB<B>, T, B> for $RGB<T> {
69             #[inline(always)]
70             fn map<F>(&self, mut f: F) -> $RGB<B>
71                 where F: FnMut(T) -> B {
72                 $RGB {
73                     r:f(self.r),
74                     g:f(self.g),
75                     b:f(self.b),
76                 }
77             }
78         }
79 
80         impl<T: Copy, B> ColorComponentMap<$RGB<B>, T, B> for $RGB<T> {
81             #[inline(always)]
82             fn map_c<F>(&self, mut f: F) -> $RGB<B>
83                 where F: FnMut(T) -> B {
84                 $RGB {
85                     r:f(self.r),
86                     g:f(self.g),
87                     b:f(self.b),
88                 }
89             }
90         }
91 
92         impl<T> ComponentSlice<T> for $RGB<T> {
93             #[inline(always)]
94             fn as_slice(&self) -> &[T] {
95                 unsafe {
96                     core::slice::from_raw_parts(self as *const Self as *const T, 3)
97                 }
98             }
99 
100             #[inline(always)]
101             fn as_mut_slice(&mut self) -> &mut [T] {
102                 unsafe {
103                     core::slice::from_raw_parts_mut(self as *mut Self as *mut T, 3)
104                 }
105             }
106         }
107 
108         impl<T> ComponentSlice<T> for [$RGB<T>] {
109             #[inline]
110             fn as_slice(&self) -> &[T] {
111                 unsafe {
112                     core::slice::from_raw_parts(self.as_ptr() as *const _, self.len() * 3)
113                 }
114             }
115 
116             #[inline]
117             fn as_mut_slice(&mut self) -> &mut [T] {
118                 unsafe {
119                     core::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut _, self.len() * 3)
120                 }
121             }
122         }
123 
124         #[cfg(feature = "as-bytes")]
125         impl<T: crate::Pod> ComponentBytes<T> for [$RGB<T>] {}
126     }
127 }
128 
129 impl<T> core::iter::FromIterator<T> for RGB<T> {
130     /// Takes exactly 3 elements from the iterator and creates a new instance.
131     /// Panics if there are fewer elements in the iterator.
132     #[inline(always)]
from_iter<I: IntoIterator<Item = T>>(into_iter: I) -> Self133     fn from_iter<I: IntoIterator<Item = T>>(into_iter: I) -> Self {
134         let mut iter = into_iter.into_iter();
135         Self {
136             r: iter.next().unwrap(),
137             g: iter.next().unwrap(),
138             b: iter.next().unwrap(),
139         }
140     }
141 }
142 
143 impl_rgb!{RGB, RGBA}
144 impl_rgb!{BGR, BGRA}
145 
146 impl<T: fmt::Display> fmt::Display for RGB<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result147     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148         write!(f,"rgb({},{},{})", self.r,self.g,self.b)
149     }
150 }
151 
152 impl<T: fmt::UpperHex> fmt::UpperHex for RGB<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result153     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154         write!(f,"RGB {{ #{:02X}{:02X}{:02X} }}", self.r, self.g, self.b)
155     }
156 }
157 
158 impl<T: fmt::LowerHex> fmt::LowerHex for RGB<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result159     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160         write!(f,"RGB {{ #{:02x}{:02x}{:02x} }}", self.r, self.g, self.b)
161     }
162 }
163 
164 impl<T: fmt::Display> fmt::Display for BGR<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result165     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166         write!(f,"bgr({},{},{})", self.b, self.g, self.r)
167     }
168 }
169 
170 impl<T: fmt::UpperHex> fmt::UpperHex for BGR<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result171     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172         write!(f,"BGR {{ #{:02X}{:02X}{:02X} }}", self.b, self.g, self.r)
173     }
174 }
175 
176 impl<T: fmt::LowerHex> fmt::LowerHex for BGR<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result177     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178         write!(f,"BGR {{ #{:02x}{:02x}{:02x} }}", self.b, self.g, self.r)
179     }
180 }
181 
182 #[cfg(test)]
183 mod rgb_test {
184     use super::*;
185     use std;
186     #[test]
sanity_check()187     fn sanity_check() {
188         let neg = RGB::new(1,2,3i32).map(|x| -x);
189         assert_eq!(neg.r, -1);
190         assert_eq!(neg.g, -2);
191         assert_eq!(neg.b, -3);
192 
193         let mut px = RGB::new(3,4,5);
194         px.as_mut_slice()[1] = 111;
195         assert_eq!(111, px.g);
196 
197         assert_eq!(RGBA::new(250,251,252,253), RGB::new(250,251,252).alpha(253));
198 
199         assert_eq!(RGB{r:1u8,g:2,b:3}, RGB::new(1u8,2,3));
200         assert!(RGB{r:1u8,g:1,b:2} < RGB::new(2,1,1));
201 
202         let mut h = std::collections::HashSet::new();
203         h.insert(px);
204         assert!(h.contains(&RGB::new(3,111,5)));
205         assert!(!h.contains(&RGB::new(111,5,3)));
206 
207 
208         #[cfg(feature = "as-bytes")]
209         {
210             let v = vec![RGB::new(1u8,2,3), RGB::new(4,5,6)];
211             assert_eq!(&[1,2,3,4,5,6], v.as_bytes());
212         }
213 
214         assert_eq!(RGB::new(0u8,0,0), Default::default());
215     }
216 
217     #[test]
218     #[allow(deprecated)]
test_fmt()219     fn test_fmt() {
220         let red_rgb = RGB::new(255, 0, 0);
221         let red_bgr = BGR::new(255, 0, 0);
222         assert_eq!("RGB { #FF0000 }", &format!("{:X}", red_rgb));
223         assert_eq!("BGR { #0000FF }", &format!("{:X}", red_bgr));
224 
225         assert_eq!("RGB { #ff0000 }", &format!("{:x}", red_rgb));
226         assert_eq!("BGR { #0000ff }", &format!("{:x}", red_bgr));
227 
228         assert_eq!("rgb(255,0,0)", &format!("{}", red_rgb));
229         assert_eq!("bgr(0,0,255)", &format!("{}", red_bgr));
230     }
231 }
232