1use crate::{AlphaColor, PremulColor, Srgb};
5
6#[derive(Clone, Copy, PartialEq, Eq, Debug)]
20#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
21#[repr(C)]
22pub struct Rgba8 {
23 pub r: u8,
25 pub g: u8,
27 pub b: u8,
29 pub a: u8,
33}
34
35impl Rgba8 {
36 #[must_use]
40 pub const fn to_u8_array(self) -> [u8; 4] {
41 [self.r, self.g, self.b, self.a]
42 }
43
44 #[must_use]
48 pub const fn from_u8_array([r, g, b, a]: [u8; 4]) -> Self {
49 Self { r, g, b, a }
50 }
51
52 #[must_use]
55 pub const fn to_u32(self) -> u32 {
56 u32::from_ne_bytes(self.to_u8_array())
57 }
58
59 #[must_use]
62 pub const fn from_u32(packed_bytes: u32) -> Self {
63 Self::from_u8_array(u32::to_ne_bytes(packed_bytes))
64 }
65}
66
67impl From<Rgba8> for AlphaColor<Srgb> {
68 fn from(value: Rgba8) -> Self {
69 Self::from_rgba8(value.r, value.g, value.b, value.a)
70 }
71}
72
73#[derive(Clone, Copy, PartialEq, Eq, Debug)]
86#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
87#[repr(C)]
88pub struct PremulRgba8 {
89 pub r: u8,
91 pub g: u8,
93 pub b: u8,
95 pub a: u8,
97}
98
99impl PremulRgba8 {
100 #[must_use]
104 pub const fn to_u8_array(self) -> [u8; 4] {
105 [self.r, self.g, self.b, self.a]
106 }
107
108 #[must_use]
112 pub const fn from_u8_array([r, g, b, a]: [u8; 4]) -> Self {
113 Self { r, g, b, a }
114 }
115
116 #[must_use]
119 pub const fn to_u32(self) -> u32 {
120 u32::from_ne_bytes(self.to_u8_array())
121 }
122
123 #[must_use]
126 pub const fn from_u32(packed_bytes: u32) -> Self {
127 Self::from_u8_array(u32::to_ne_bytes(packed_bytes))
128 }
129}
130
131impl From<PremulRgba8> for PremulColor<Srgb> {
132 fn from(value: PremulRgba8) -> Self {
133 Self::from_rgba8(value.r, value.g, value.b, value.a)
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::{PremulRgba8, Rgba8};
140
141 #[test]
142 fn to_u32() {
143 let c = Rgba8 {
144 r: 1,
145 g: 2,
146 b: 3,
147 a: 4,
148 };
149 assert_eq!(0x04030201_u32.to_le(), c.to_u32());
150
151 let p = PremulRgba8 {
152 r: 0xaa,
153 g: 0xbb,
154 b: 0xcc,
155 a: 0xff,
156 };
157 assert_eq!(0xffccbbaa_u32.to_le(), p.to_u32());
158 }
159
160 #[test]
161 fn from_u32() {
162 let c = Rgba8 {
163 r: 1,
164 g: 2,
165 b: 3,
166 a: 4,
167 };
168 assert_eq!(Rgba8::from_u32(0x04030201_u32.to_le()), c);
169
170 let p = PremulRgba8 {
171 r: 0xaa,
172 g: 0xbb,
173 b: 0xcc,
174 a: 0xff,
175 };
176 assert_eq!(PremulRgba8::from_u32(0xffccbbaa_u32.to_le()), p);
177 }
178
179 #[test]
180 fn to_u8_array() {
181 let c = Rgba8 {
182 r: 1,
183 g: 2,
184 b: 3,
185 a: 4,
186 };
187 assert_eq!([1, 2, 3, 4], c.to_u8_array());
188
189 let p = PremulRgba8 {
190 r: 0xaa,
191 g: 0xbb,
192 b: 0xcc,
193 a: 0xff,
194 };
195 assert_eq!([0xaa, 0xbb, 0xcc, 0xff], p.to_u8_array());
196 }
197
198 #[test]
199 fn from_u8_array() {
200 let c = Rgba8 {
201 r: 1,
202 g: 2,
203 b: 3,
204 a: 4,
205 };
206 assert_eq!(Rgba8::from_u8_array([1, 2, 3, 4]), c);
207
208 let p = PremulRgba8 {
209 r: 0xaa,
210 g: 0xbb,
211 b: 0xcc,
212 a: 0xff,
213 };
214 assert_eq!(PremulRgba8::from_u8_array([0xaa, 0xbb, 0xcc, 0xff]), p);
215 }
216
217 #[test]
218 #[cfg(feature = "bytemuck")]
219 fn bytemuck_to_u32() {
220 let c = Rgba8 {
221 r: 1,
222 g: 2,
223 b: 3,
224 a: 4,
225 };
226 assert_eq!(c.to_u32(), bytemuck::cast(c));
227
228 let p = PremulRgba8 {
229 r: 0xaa,
230 g: 0xbb,
231 b: 0xcc,
232 a: 0xff,
233 };
234 assert_eq!(p.to_u32(), bytemuck::cast(p));
235 }
236
237 #[test]
238 #[cfg(feature = "bytemuck")]
239 fn bytemuck_from_u32() {
240 let c = 0x04030201_u32.to_le();
241 assert_eq!(Rgba8::from_u32(c), bytemuck::cast(c));
242
243 let p = 0xffccbbaa_u32.to_le();
244 assert_eq!(PremulRgba8::from_u32(p), bytemuck::cast(p));
245 }
246
247 #[test]
248 #[cfg(feature = "bytemuck")]
249 fn bytemuck_to_u8_array() {
250 let c = Rgba8 {
251 r: 1,
252 g: 2,
253 b: 3,
254 a: 4,
255 };
256 assert_eq!(c.to_u8_array(), bytemuck::cast::<_, [u8; 4]>(c));
257 assert_eq!(c.to_u8_array(), bytemuck::cast::<_, [u8; 4]>(c.to_u32()));
258
259 let p = PremulRgba8 {
260 r: 0xaa,
261 g: 0xbb,
262 b: 0xcc,
263 a: 0xff,
264 };
265 assert_eq!(p.to_u8_array(), bytemuck::cast::<_, [u8; 4]>(p));
266 assert_eq!(p.to_u8_array(), bytemuck::cast::<_, [u8; 4]>(p.to_u32()));
267 }
268
269 #[test]
270 #[cfg(feature = "bytemuck")]
271 fn bytemuck_from_u8_array() {
272 let c = [1, 2, 3, 4];
273 assert_eq!(Rgba8::from_u8_array(c), bytemuck::cast(c));
274
275 let p = [0xaa, 0xbb, 0xcc, 0xff];
276 assert_eq!(PremulRgba8::from_u8_array(p), bytemuck::cast(p));
277 }
278}