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