palette/rgb/
channels.rs

1//! Channel orders for packed RGBA types.
2
3use crate::{cast::ComponentOrder, rgb};
4
5/// RGBA color packed in ABGR order.
6///
7/// See [Packed](crate::cast::Packed) for more details.
8#[derive(Copy, Clone, Debug, PartialEq, Eq)]
9pub struct Abgr;
10
11impl<S, T> ComponentOrder<rgb::Rgba<S, T>, [T; 4]> for Abgr {
12    #[inline]
13    fn pack(color: rgb::Rgba<S, T>) -> [T; 4] {
14        let [red, green, blue, alpha]: [T; 4] = color.into();
15        [alpha, blue, green, red]
16    }
17
18    #[inline]
19    fn unpack(packed: [T; 4]) -> rgb::Rgba<S, T> {
20        let [alpha, blue, green, red] = packed;
21        rgb::Rgba::new(red, green, blue, alpha)
22    }
23}
24
25/// RGBA color packed in ARGB order.
26///
27/// See [Packed](crate::cast::Packed) for more details.
28#[derive(Copy, Clone, Debug, PartialEq, Eq)]
29pub struct Argb;
30
31impl<S, T> ComponentOrder<rgb::Rgba<S, T>, [T; 4]> for Argb {
32    #[inline]
33    fn pack(color: rgb::Rgba<S, T>) -> [T; 4] {
34        let [red, green, blue, alpha]: [T; 4] = color.into();
35        [alpha, red, green, blue]
36    }
37
38    #[inline]
39    fn unpack(packed: [T; 4]) -> rgb::Rgba<S, T> {
40        let [alpha, red, green, blue] = packed;
41        rgb::Rgba::new(red, green, blue, alpha)
42    }
43}
44
45/// RGBA color packed in BGRA order.
46///
47/// See [Packed](crate::cast::Packed) for more details.
48#[derive(Copy, Clone, Debug, PartialEq, Eq)]
49pub struct Bgra;
50
51impl<S, T> ComponentOrder<rgb::Rgba<S, T>, [T; 4]> for Bgra {
52    #[inline]
53    fn pack(color: rgb::Rgba<S, T>) -> [T; 4] {
54        let [red, green, blue, alpha]: [T; 4] = color.into();
55        [blue, green, red, alpha]
56    }
57
58    #[inline]
59    fn unpack(packed: [T; 4]) -> rgb::Rgba<S, T> {
60        let [blue, green, red, alpha] = packed;
61        rgb::Rgba::new(red, green, blue, alpha)
62    }
63}
64
65/// RGBA color packed in RGBA order.
66///
67/// See [Packed](crate::cast::Packed) for more details.
68#[derive(Copy, Clone, Debug, PartialEq, Eq)]
69pub struct Rgba;
70
71impl<S, T> ComponentOrder<rgb::Rgba<S, T>, [T; 4]> for Rgba {
72    #[inline]
73    fn pack(color: rgb::Rgba<S, T>) -> [T; 4] {
74        let [red, green, blue, alpha]: [T; 4] = color.into();
75        [red, green, blue, alpha]
76    }
77
78    #[inline]
79    fn unpack(packed: [T; 4]) -> rgb::Rgba<S, T> {
80        let [red, green, blue, alpha] = packed;
81        rgb::Rgba::new(red, green, blue, alpha)
82    }
83}
84
85#[cfg(feature = "approx")]
86#[cfg(test)]
87mod test {
88    use super::{Abgr, Argb, Bgra, Rgba};
89    use crate::{cast::Packed, Srgb, Srgba};
90
91    #[test]
92    fn rgba() {
93        let a1: Packed<Rgba, u32> = Srgb::new(0.5, 0.0, 0.0).into_format().into();
94        let a2: Packed<Rgba, u32> = Srgb::new(0.0, 1.0, 0.0).into_format().into();
95        let a3: Packed<Rgba, u32> = Srgb::new(0.0, 0.0, 0.5).into_format().into();
96        let x1: u32 = 0x8000_00FF;
97        let x2: u32 = 0x00FF_00FF;
98        let x3: u32 = 0x0000_80FF;
99        assert_eq!(a1.color, x1);
100        assert_eq!(a2.color, x2);
101        assert_eq!(a3.color, x3);
102
103        let unpacked: Srgb<u8> = Packed::<Rgba, u32>::from(0x80FF_80FF).into();
104        assert_relative_eq!(
105            Srgb::new(0.5, 1.0, 0.5),
106            unpacked.into_format(),
107            epsilon = 0.01
108        );
109
110        let b1: Packed<Rgba, u32> = Srgba::new(0.5, 0.0, 0.0, 0.0).into_format().into();
111        let b2: Packed<Rgba, u32> = Srgba::new(0.0, 1.0, 0.0, 0.0).into_format().into();
112        let b3: Packed<Rgba, u32> = Srgba::new(0.0, 0.0, 0.5, 0.0).into_format().into();
113        let b4: Packed<Rgba, u32> = Srgba::new(0.0, 0.0, 0.0, 1.0).into_format().into();
114        let y1: u32 = 0x8000_0000;
115        let y2: u32 = 0x00FF_0000;
116        let y3: u32 = 0x0000_8000;
117        let y4: u32 = 0x0000_00FF;
118        assert_eq!(b1.color, y1);
119        assert_eq!(b2.color, y2);
120        assert_eq!(b3.color, y3);
121        assert_eq!(b4.color, y4);
122
123        let unpacked: Srgba<u8> = Packed::<Rgba, u32>::from(0x80FF_80FF).into();
124        assert_relative_eq!(
125            Srgba::new(0.5, 1.0, 0.5, 1.0),
126            unpacked.into_format(),
127            epsilon = 0.01
128        );
129    }
130
131    #[test]
132    fn argb() {
133        let a1: Packed<Argb, u32> = Srgb::new(0.5, 0.0, 0.0).into_format().into();
134        let a2: Packed<Argb, u32> = Srgb::new(0.0, 1.0, 0.0).into_format().into();
135        let a3: Packed<Argb, u32> = Srgb::new(0.0, 0.0, 0.5).into_format().into();
136        let x1: u32 = 0xFF80_0000;
137        let x2: u32 = 0xFF00_FF00;
138        let x3: u32 = 0xFF00_0080;
139        assert_eq!(a1.color, x1);
140        assert_eq!(a2.color, x2);
141        assert_eq!(a3.color, x3);
142
143        let unpacked: Srgb<u8> = Packed::<Argb, u32>::from(0x80FF_80FF).into();
144        assert_relative_eq!(
145            Srgb::new(1.0, 0.5, 1.0),
146            unpacked.into_format(),
147            epsilon = 0.01
148        );
149
150        let b1: Packed<Argb, u32> = Srgba::new(0.5, 0.0, 0.0, 0.0).into_format().into();
151        let b2: Packed<Argb, u32> = Srgba::new(0.0, 1.0, 0.0, 0.0).into_format().into();
152        let b3: Packed<Argb, u32> = Srgba::new(0.0, 0.0, 0.5, 0.0).into_format().into();
153        let b4: Packed<Argb, u32> = Srgba::new(0.0, 0.0, 0.0, 1.0).into_format().into();
154        let y1: u32 = 0x0080_0000;
155        let y2: u32 = 0x0000_FF00;
156        let y3: u32 = 0x0000_0080;
157        let y4: u32 = 0xFF00_0000;
158        assert_eq!(b1.color, y1);
159        assert_eq!(b2.color, y2);
160        assert_eq!(b3.color, y3);
161        assert_eq!(b4.color, y4);
162
163        let unpacked: Srgba<u8> = Packed::<Argb, u32>::from(0x80FF_80FF).into();
164        assert_relative_eq!(
165            Srgba::new(1.0, 0.5, 1.0, 0.5),
166            unpacked.into_format(),
167            epsilon = 0.01
168        );
169    }
170
171    #[test]
172    fn bgra() {
173        let a1: Packed<Bgra, u32> = Srgb::new(0.5, 0.0, 0.0).into_format().into();
174        let a2: Packed<Bgra, u32> = Srgb::new(0.0, 1.0, 0.0).into_format().into();
175        let a3: Packed<Bgra, u32> = Srgb::new(0.0, 0.0, 0.5).into_format().into();
176        let x1: u32 = 0x0000_80FF;
177        let x2: u32 = 0x00FF_00FF;
178        let x3: u32 = 0x8000_00FF;
179        assert_eq!(a1.color, x1);
180        assert_eq!(a2.color, x2);
181        assert_eq!(a3.color, x3);
182
183        let unpacked: Srgb<u8> = Packed::<Bgra, u32>::from(0x80FF_FF80).into();
184        assert_relative_eq!(
185            Srgb::new(1.0, 1.0, 0.5),
186            unpacked.into_format(),
187            epsilon = 0.01
188        );
189
190        let b1: Packed<Bgra, u32> = Srgba::new(0.5, 0.0, 0.0, 0.0).into_format().into();
191        let b2: Packed<Bgra, u32> = Srgba::new(0.0, 1.0, 0.0, 0.0).into_format().into();
192        let b3: Packed<Bgra, u32> = Srgba::new(0.0, 0.0, 0.5, 0.0).into_format().into();
193        let b4: Packed<Bgra, u32> = Srgba::new(0.0, 0.0, 0.0, 1.0).into_format().into();
194        let y1: u32 = 0x0000_8000;
195        let y2: u32 = 0x00FF_0000;
196        let y3: u32 = 0x8000_0000;
197        let y4: u32 = 0x0000_00FF;
198        assert_eq!(b1.color, y1);
199        assert_eq!(b2.color, y2);
200        assert_eq!(b3.color, y3);
201        assert_eq!(b4.color, y4);
202
203        let unpacked: Srgba<u8> = Packed::<Bgra, u32>::from(0x80FF_FF80).into();
204        assert_relative_eq!(
205            Srgba::new(1.0, 1.0, 0.5, 0.5),
206            unpacked.into_format(),
207            epsilon = 0.01
208        );
209    }
210
211    #[test]
212    fn abgr() {
213        let a1: Packed<Abgr, u32> = Srgb::new(0.5, 0.0, 0.0).into_format().into();
214        let a2: Packed<Abgr, u32> = Srgb::new(0.0, 1.0, 0.0).into_format().into();
215        let a3: Packed<Abgr, u32> = Srgb::new(0.0, 0.0, 0.5).into_format().into();
216        let x1: u32 = 0xFF00_0080;
217        let x2: u32 = 0xFF00_FF00;
218        let x3: u32 = 0xFF80_0000;
219        assert_eq!(a1.color, x1);
220        assert_eq!(a2.color, x2);
221        assert_eq!(a3.color, x3);
222
223        let unpacked: Srgb<u8> = Packed::<Abgr, u32>::from(0x80FF_FF80).into();
224        assert_relative_eq!(
225            Srgb::new(0.5, 1.0, 1.0),
226            unpacked.into_format(),
227            epsilon = 0.01
228        );
229
230        let b1: Packed<Abgr, u32> = Srgba::new(0.5, 0.0, 0.0, 0.0).into_format().into();
231        let b2: Packed<Abgr, u32> = Srgba::new(0.0, 1.0, 0.0, 0.0).into_format().into();
232        let b3: Packed<Abgr, u32> = Srgba::new(0.0, 0.0, 0.5, 0.0).into_format().into();
233        let b4: Packed<Abgr, u32> = Srgba::new(0.0, 0.0, 0.0, 1.0).into_format().into();
234        let y1: u32 = 0x0000_0080;
235        let y2: u32 = 0x0000_FF00;
236        let y3: u32 = 0x0080_0000;
237        let y4: u32 = 0xFF00_0000;
238        assert_eq!(b1.color, y1);
239        assert_eq!(b2.color, y2);
240        assert_eq!(b3.color, y3);
241        assert_eq!(b4.color, y4);
242
243        let unpacked: Srgba<u8> = Packed::<Abgr, u32>::from(0x80FF_FF80).into();
244        assert_relative_eq!(
245            Srgba::new(0.5, 1.0, 1.0, 0.5),
246            unpacked.into_format(),
247            epsilon = 0.01
248        );
249    }
250
251    #[test]
252    fn u32_to_color() {
253        assert_eq!(0xFFFF_FF80, u32::from(Srgb::new(255u8, 255, 128)));
254        assert_eq!(0x7FFF_FF80, u32::from(Srgba::new(127u8, 255u8, 255, 128)));
255    }
256}