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