rgb/legacy/internal/
rgba.rs

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