rgb/legacy/internal/
rgba.rs

1use super::pixel::{ComponentSlice, ComponentMap, ColorComponentMap};
2#[cfg(feature = "as-bytes")]
3use super::pixel::{ComponentBytes};
4use crate::alt::{BGRA, ARGB, ABGR, BGR};
5use crate::{RGB, RGBA};
6use core::fmt;
7
8impl<T, A> RGBA<T, A> {
9    #[inline(always)]
10    /// Convenience function for creating a new pixel
11    /// The order of arguments is R,G,B,A
12    pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self {
13        Self { r, g, b, a }
14    }
15}
16
17impl<T> BGRA<T> {
18    #[inline(always)]
19    /// Convenience function for creating a new pixel
20    /// Warning: The order of arguments is R,G,B,A
21    #[deprecated(note = "This function has a misleading order of arguments. Use BGRA{} literal instead")]
22    pub const fn new(r: T, g: T, b: T, a: T) -> Self {
23        Self { b, g, r, a }
24    }
25}
26
27/// ```rust,compile_fail
28/// let r = rgb::BGRA::<u8,u16>::zeroed();
29/// ```
30impl<T, A> BGRA<T, A> {
31    #[inline(always)]
32    /// Convenience function for creating a new pixel
33    /// Warning: The order of arguments is R,G,B,A
34    #[deprecated(note = "This function has a misleading order of arguments. Use BGRA{} literal instead")]
35    pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self {
36        Self { b, g, r, a }
37    }
38}
39
40impl<T> ARGB<T> {
41    #[inline(always)]
42    /// Convenience function for creating a new pixel
43    /// The order of arguments is R,G,B,A
44    #[deprecated(note = "This function has a misleading order of arguments. Use ARGB{} literal instead")]
45    pub const fn new(r: T, g: T, b: T, a: T) -> Self {
46        Self { a, r, g, b }
47    }
48}
49
50impl<T, A> ARGB<T, A> {
51    #[inline(always)]
52    /// Convenience function for creating a new pixel
53    /// The order of arguments is R,G,B,A
54    #[deprecated(note = "This function has a misleading order of arguments. Use ARGB{} literal instead")]
55    pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self {
56        Self { a, r, g, b }
57    }
58}
59
60impl<T> ABGR<T> {
61    #[inline(always)]
62    /// Convenience function for creating a new pixel
63    /// The order of arguments is R,G,B,A
64    #[deprecated(note = "This function has a misleading order of arguments. Use ABGR{} literal instead")]
65    pub const fn new(r: T, g: T, b: T, a: T) -> Self {
66        Self { a, b, g, r }
67    }
68}
69
70impl<T, A> ABGR<T, A> {
71    #[inline(always)]
72    /// Convenience function for creating a new pixel
73    /// The order of arguments is R,G,B,A
74    #[deprecated(note = "This function has a misleading order of arguments. Use ABGR{} literal instead")]
75    pub const fn new_alpha(r: T, g: T, b: T, a: A) -> Self {
76        Self { a, b, g, r }
77    }
78}
79
80macro_rules! impl_rgba {
81    ($RGBA:ident) => {
82        impl<T: Clone> $RGBA<T> {
83            /// Iterate over all components (length=4)
84            #[inline(always)]
85            pub fn iter(&self) -> core::iter::Cloned<core::slice::Iter<'_, T>> {
86                self.as_slice().iter().cloned()
87            }
88        }
89
90        impl<T: Clone, A> $RGBA<T, A> {
91            /// Copy RGB components out of the RGBA struct
92            ///
93            /// Note: you can use `.into()` to convert between other types
94            #[inline(always)]
95            pub fn bgr(&self) -> BGR<T> {
96                BGR {
97                    r: self.r.clone(),
98                    g: self.g.clone(),
99                    b: self.b.clone(),
100                }
101            }
102        }
103
104        impl<T: Copy, A: Clone> $RGBA<T, A> {
105            /// Create new RGBA with the same alpha value, but different RGB values
106            #[deprecated(note = "Renamed to map_colors()")]
107            pub fn map_rgb<F, U, B>(&self, mut f: F) -> $RGBA<U, B>
108                where F: FnMut(T) -> U, U: Clone, B: From<A> + Clone
109            {
110                $RGBA {
111                    r: f(self.r),
112                    g: f(self.g),
113                    b: f(self.b),
114                    a: self.a.clone().into(),
115                }
116            }
117
118            #[doc(hidden)]
119            #[deprecated(note = "use .with_alpha(a) instead")]
120            /// Create a new RGBA with the new alpha value, but same RGB values
121            pub fn alpha(&self, a: A) -> Self {
122                self.with_alpha(a)
123            }
124
125            #[inline(always)]
126            /// Create a new RGBA with the new alpha value, but same RGB values
127            pub fn with_alpha(&self, a: A) -> Self {
128                Self { r: self.r, g: self.g, b: self.b, a }
129            }
130
131            /// Create a new RGBA with a new alpha value created by the callback.
132            /// Allows changing of the type used for the alpha channel.
133            #[inline]
134            pub fn map_alpha<F, B>(&self, f: F) -> $RGBA<T, B>
135                where F: FnOnce(A) -> B {
136                $RGBA {
137                    r: self.r,
138                    g: self.g,
139                    b: self.b,
140                    a: f(self.a.clone()),
141                }
142            }
143        }
144
145        impl<T: Copy, B> ComponentMap<$RGBA<B>, T, B> for $RGBA<T> {
146            #[inline(always)]
147            fn map<F>(&self, mut f: F) -> $RGBA<B>
148            where F: FnMut(T) -> B {
149                $RGBA {
150                    r: f(self.r),
151                    g: f(self.g),
152                    b: f(self.b),
153                    a: f(self.a),
154                }
155            }
156        }
157
158        impl<T: Copy, A: Copy, B> ColorComponentMap<$RGBA<B, A>, T, B> for $RGBA<T, A> {
159            #[inline(always)]
160            fn map_colors<F>(&self, mut f: F) -> $RGBA<B, A>
161            where F: FnMut(T) -> B {
162                $RGBA {
163                    r: f(self.r),
164                    g: f(self.g),
165                    b: f(self.b),
166                    a: self.a,
167                }
168            }
169        }
170
171        impl<T> ComponentSlice<T> for $RGBA<T> {
172            #[inline(always)]
173            fn as_slice(&self) -> &[T] {
174                unsafe {
175                    core::slice::from_raw_parts(self as *const Self as *const T, 4)
176                }
177            }
178
179            #[inline(always)]
180            fn as_mut_slice(&mut self) -> &mut [T] {
181                unsafe {
182                    core::slice::from_raw_parts_mut(self as *mut Self as *mut T, 4)
183                }
184            }
185        }
186
187        impl<T> ComponentSlice<T> for [$RGBA<T>] {
188            #[inline]
189            fn as_slice(&self) -> &[T] {
190                unsafe {
191                    core::slice::from_raw_parts(self.as_ptr() as *const _, self.len() * 4)
192                }
193            }
194
195            #[inline]
196            fn as_mut_slice(&mut self) -> &mut [T] {
197                unsafe {
198                    core::slice::from_raw_parts_mut(self.as_mut_ptr() as *mut _, self.len() * 4)
199                }
200            }
201        }
202
203        #[cfg(feature = "as-bytes")]
204        impl<T: crate::Pod> ComponentBytes<T> for [$RGBA<T>] {}
205    };
206}
207
208macro_rules! impl_alpha_conv {
209    ($RGB:ident, $RGBA:ident) => {
210        /// Assumes 255 is opaque
211        impl<T: Copy> From<$RGB<T>> for $RGBA<T, u8> {
212            #[inline(always)]
213            fn from(other: $RGB<T>) -> Self {
214                Self {
215                    r: other.r,
216                    g: other.g,
217                    b: other.b,
218                    a: 0xFF,
219                }
220            }
221        }
222
223        /// Assumes 65535 is opaque
224        impl<T: Copy> From<$RGB<T>> for $RGBA<T, u16> {
225            #[inline(always)]
226            fn from(other: $RGB<T>) -> Self {
227                Self {
228                    r: other.r,
229                    g: other.g,
230                    b: other.b,
231                    a: 0xFFFF,
232                }
233            }
234        }
235    };
236}
237
238impl<T, A> RGBA<T, A> {
239    /// Provide a mutable view of only RGB components (leaving out alpha).
240    /// Useful to change color without changing opacity.
241    #[inline(always)]
242    pub fn rgb_mut(&mut self) -> &mut RGB<T> {
243        unsafe { &mut *(self as *mut Self).cast::<RGB<T>>() }
244    }
245}
246
247impl<T, A> BGRA<T, A> {
248    /// Provide a mutable view of only RGB components (leaving out alpha).
249    /// Useful to change color without changing opacity.
250    #[deprecated(note = "This function will change. Use bgr_mut()")]
251    pub fn rgb_mut(&mut self) -> &mut BGR<T> {
252        unsafe { &mut *(self as *mut Self).cast::<BGR<T>>() }
253    }
254
255    /// Provide a mutable view of only RGB components (leaving out alpha).
256    /// Useful to change color without changing opacity.
257    #[inline(always)]
258    pub fn bgr_mut(&mut self) -> &mut BGR<T> {
259        unsafe { &mut *(self as *mut Self).cast::<BGR<T>>() }
260    }
261}
262
263impl<T> core::iter::FromIterator<T> for RGBA<T> {
264    #[inline(always)]
265    /// Takes exactly 4 elements from the iterator and creates a new instance.
266    /// Panics if there are fewer elements in the iterator.
267    fn from_iter<I: IntoIterator<Item = T>>(into_iter: I) -> Self {
268        let mut iter = into_iter.into_iter();
269        Self {
270            r: iter.next().unwrap(),
271            g: iter.next().unwrap(),
272            b: iter.next().unwrap(),
273            a: iter.next().unwrap(),
274        }
275    }
276}
277
278impl<T: Clone, A> RGBA<T, A> {
279    /// Copy RGB components out of the RGBA struct
280    ///
281    /// Note: you can use `.into()` to convert between other types
282    #[inline(always)]
283    pub fn rgb(&self) -> RGB<T> {
284        RGB {
285            r: self.r.clone(),
286            g: self.g.clone(),
287            b: self.b.clone(),
288        }
289    }
290}
291
292impl<T: Clone, A> ARGB<T, A> {
293    /// Copy RGB components out of the ARGB struct
294    ///
295    /// Note: you can use `.into()` to convert between other types
296    #[inline(always)]
297    pub fn rgb(&self) -> RGB<T> {
298        RGB {
299            r: self.r.clone(),
300            g: self.g.clone(),
301            b: self.b.clone(),
302        }
303    }
304}
305
306impl<T: Clone, A> BGRA<T, A> {
307    /// Copy RGB components out of the RGBA struct
308    ///
309    /// Note: you can use `.into()` to convert between other types
310    #[deprecated(note = "This function will change. Use bgr()")]
311    pub fn rgb(&self) -> BGR<T> {
312        BGR {
313            r: self.r.clone(),
314            g: self.g.clone(),
315            b: self.b.clone(),
316        }
317    }
318}
319
320impl_rgba! {RGBA}
321impl_rgba! {BGRA}
322impl_rgba! {ARGB}
323impl_rgba! {ABGR}
324
325impl_alpha_conv! {BGR, BGRA}
326impl_alpha_conv! {RGB, BGRA}
327impl_alpha_conv! {BGR, RGBA}
328impl_alpha_conv! {RGB, RGBA}
329impl_alpha_conv! {BGR, ABGR}
330impl_alpha_conv! {RGB, ABGR}
331impl_alpha_conv! {BGR, ARGB}
332impl_alpha_conv! {RGB, ARGB}
333
334impl<T: fmt::Display, A: fmt::Display> fmt::Display for RGBA<T, A> {
335    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
336        write!(f, "rgba({},{},{},{})", self.r, self.g, self.b, self.a)
337    }
338}
339
340impl<T: fmt::Display, A: fmt::Display> fmt::Display for BGRA<T, A> {
341    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
342        write!(f, "bgra({},{},{},{})", self.r, self.g, self.b, self.a)
343    }
344}
345
346#[test]
347fn rgba_test() {
348    let neg = RGBA::new(1,2,3i32,1000).map(|x| -x);
349    assert_eq!(neg.r, -1);
350    assert_eq!(neg.rgb().r, -1);
351    assert_eq!(neg.g, -2);
352    assert_eq!(neg.rgb().g, -2);
353    assert_eq!(neg.b, -3);
354    assert_eq!(neg.rgb().b, -3);
355    assert_eq!(neg.a, -1000);
356    assert_eq!(neg.map_alpha(|x| x+1).a, -999);
357    assert_eq!(neg, neg.as_slice().iter().copied().collect());
358    assert!(neg < RGBA::new(0,0,0,0));
359
360    #[allow(deprecated)]
361    let neg = RGBA::new(1u8,2,3,4).map_rgb(|c| -(c as i16));
362    assert_eq!(-1i16, neg.r);
363    assert_eq!(4i16, neg.a);
364    let neg = RGBA::new(1u8,2,3,4).map_colors(|c| -(c as i16));
365    assert_eq!(-1i16, neg.r);
366    assert_eq!(4u8, neg.a);
367
368    let mut px = RGBA{r:1,g:2,b:3,a:4};
369    px.as_mut_slice()[3] = 100;
370    assert_eq!(1, px.rgb_mut().r);
371    assert_eq!(2, px.rgb_mut().g);
372    px.rgb_mut().b = 4;
373    assert_eq!(4, px.rgb_mut().b);
374    assert_eq!(100, px.a);
375
376    #[cfg(feature = "as-bytes")]
377    {
378        let v = vec![RGBA::new(1u8,2,3,4), RGBA::new(5,6,7,8)];
379        assert_eq!(&[1,2,3,4,5,6,7,8], v.as_bytes());
380    }
381}
382
383#[test]
384#[cfg(feature = "as-bytes")]
385fn abgr_test() {
386    let abgr = ABGR {r:1,g:2,b:3,a:4};
387    assert_eq!(4, abgr.as_slice()[0]);
388    use crate::AsPixels;
389    assert_eq!(abgr, [abgr].as_bytes().as_pixels()[0]);
390}
391
392#[test]
393#[allow(deprecated)]
394fn bgra_test() {
395    let neg = BGRA::new(1, 2, 3i32, 1000).map(|x| -x);
396    let _ = neg.as_slice();
397
398    #[cfg(feature = "as-bytes")]
399    {
400        let _ = [neg].as_bytes();
401    }
402    assert_eq!(neg.r, -1);
403    assert_eq!(neg.bgr().r, -1);
404    assert_eq!(neg.g, -2);
405    assert_eq!(neg.bgr().g, -2);
406    assert_eq!(neg.b, -3);
407    assert_eq!(neg.bgr().b, -3);
408    assert_eq!(neg.a, -1000);
409    assert_eq!(&[-3,-2,-1,-1000], neg.as_slice());
410    assert!(neg < BGRA::new(0, 0, 0, 0));
411
412    let neg = BGRA::new(1u8, 2u8, 3u8, 4u8).map_rgb(|c| -(c as i16));
413    assert_eq!(-1i16, neg.r);
414    assert_eq!(4i16, neg.a);
415    #[allow(deprecated)]
416    let neg = BGRA::new(1u8, 2u8, 3u8, 4u8).map_c(|c| -(c as i16));
417    assert_eq!(-1i16, neg.r);
418    assert_eq!(4u8, neg.a);
419
420    let mut px = BGRA{r:1,g:2,b:3,a:-9}.alpha(4);
421    px.as_mut_slice()[3] = 100;
422    assert_eq!(1, px.bgr_mut().r);
423    assert_eq!(2, px.bgr_mut().g);
424    px.bgr_mut().b = 4;
425    assert_eq!(4, px.bgr_mut().b);
426    assert_eq!(100, px.a);
427
428
429    #[cfg(feature = "as-bytes")]
430    {
431        let v = vec![BGRA::new(3u8, 2, 1, 4), BGRA::new(7, 6, 5, 8)];
432        assert_eq!(&[1,2,3,4,5,6,7,8], v.as_bytes());
433    }
434}