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