1use crate::math::{Color3, Color4};
2
3pub trait IntoPixel<T, F>: Sized {
7 fn into_pixel(self) -> T;
9
10 fn into_pixel_fmt(self, _: F) -> T {
15 self.into_pixel()
16 }
17}
18
19#[derive(Copy, Clone, Default)]
21pub struct Rgb888;
22#[derive(Copy, Clone, Default)]
24pub struct Rgb565;
25
26#[derive(Copy, Clone, Default)]
28pub struct Xrgb8888;
29#[derive(Copy, Clone, Default)]
31pub struct Rgba8888;
32#[derive(Copy, Clone, Default)]
34pub struct Argb8888;
35#[derive(Copy, Clone, Default)]
37pub struct Bgra8888;
38
39#[derive(Copy, Clone, Default)]
41pub struct Rgba4444;
42
43impl IntoPixel<u32, Rgb888> for Color3 {
46 fn into_pixel(self) -> u32 {
47 let [r, g, b] = self.0;
48 u32::from_be_bytes([0, r, g, b])
50 }
51}
52impl IntoPixel<[u8; 3], Rgb888> for Color3 {
53 fn into_pixel(self) -> [u8; 3] {
54 self.0
55 }
56}
57
58impl IntoPixel<u16, Rgb565> for Color3 {
59 fn into_pixel(self) -> u16 {
60 let [r, g, b] = self.0;
61 (r as u16 >> 3 & 0x1F) << 11
62 | (g as u16 >> 2 & 0x3F) << 5
63 | (b as u16 >> 3 & 0x1F)
64 }
65}
66
67impl IntoPixel<[u8; 2], Rgb565> for Color3 {
68 fn into_pixel(self) -> [u8; 2] {
69 let c: u16 = self.into_pixel();
70 c.to_ne_bytes()
71 }
72}
73
74impl<F> IntoPixel<u32, F> for Color4
77where
78 Self: IntoPixel<[u8; 4], F>,
79{
80 fn into_pixel(self) -> u32 {
81 u32::from_be_bytes(self.into_pixel())
83 }
84}
85
86impl IntoPixel<u32, Xrgb8888> for Color4 {
87 fn into_pixel(self) -> u32 {
88 let [r, g, b, _] = self.0;
89 u32::from_be_bytes([0, r, g, b])
91 }
92}
93impl IntoPixel<[u8; 4], Rgba8888> for Color4 {
94 fn into_pixel(self) -> [u8; 4] {
95 self.0
96 }
97}
98impl IntoPixel<[u8; 4], Argb8888> for Color4 {
99 fn into_pixel(self) -> [u8; 4] {
100 let [r, g, b, a] = self.0;
101 [a, r, g, b]
102 }
103}
104impl IntoPixel<[u8; 4], Bgra8888> for Color4 {
105 fn into_pixel(self) -> [u8; 4] {
106 let [r, g, b, a] = self.0;
107 [b, g, r, a]
108 }
109}
110impl IntoPixel<[u8; 3], Rgb888> for Color4 {
111 fn into_pixel(self) -> [u8; 3] {
112 [self.r(), self.g(), self.b()]
113 }
114}
115impl IntoPixel<[u8; 2], Rgba4444> for Color4 {
116 fn into_pixel(self) -> [u8; 2] {
117 let c: u16 = self.into_pixel_fmt(Rgba4444);
118 c.to_ne_bytes()
119 }
120}
121impl IntoPixel<u16, Rgba4444> for Color4 {
122 fn into_pixel(self) -> u16 {
123 let [r, g, b, a] = self.0.map(|c| c as u16 >> 4);
124 r << 12 | g << 8 | b << 4 | a
126 }
127}
128impl IntoPixel<u16, Rgb565> for Color4 {
129 fn into_pixel(self) -> u16 {
130 self.to_rgb().into_pixel()
131 }
132}
133impl IntoPixel<[u8; 2], Rgb565> for Color4 {
134 fn into_pixel(self) -> [u8; 2] {
135 let c: u16 = self.into_pixel_fmt(Rgb565);
136 c.to_ne_bytes()
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use crate::math::{rgb, rgba};
143
144 use super::*;
145
146 const COL3: Color3 = rgb(0x11u8, 0x22, 0x33);
147
148 #[test]
149 fn color3_to_rgb888() {
150 let pix: u32 = COL3.into_pixel_fmt(Rgb888);
151 assert_eq!(pix, 0x00_11_22_33);
152 }
153
154 #[test]
155 fn color3_to_rgb565() {
156 let pix: u16 = rgb(0x40, 0x20, 0x10).into_pixel();
157 assert_eq!(pix, 0b01000_001000_00010_u16);
158
159 let pix: [u8; 2] = rgb(0x40u8, 0x20, 0x10).into_pixel_fmt(Rgb565);
160 assert_eq!(pix, [0b000_00010, 0b01000_001]);
161 }
162
163 #[test]
164 fn color4_to_rgba8888() {
165 let col = rgba(0x11u8, 0x22, 0x33, 0x44);
166
167 let pix: u32 = col.into_pixel_fmt(Rgba8888);
168 assert_eq!(pix, 0x11_22_33_44);
169
170 let pix: [u8; 4] = col.into_pixel_fmt(Rgba8888);
171 assert_eq!(pix, [0x11, 0x22, 0x33, 0x44]);
172 }
173
174 const COL4: Color4 = rgba(0x11u8, 0x22, 0x33, 0x44);
175
176 #[test]
177 fn color4_to_argb8888() {
178 let pix: u32 = COL4.into_pixel_fmt(Argb8888);
179 assert_eq!(pix, 0x44_11_22_33);
180
181 let pix: [u8; 4] = COL4.into_pixel_fmt(Argb8888);
182 assert_eq!(pix, [0x44, 0x11, 0x22, 0x33]);
183 }
184
185 #[test]
186 fn color4_to_bgra8888() {
187 let pix: u32 = COL4.into_pixel_fmt(Bgra8888);
188 assert_eq!(pix, 0x33_22_11_44);
189
190 let pix: [u8; 4] = COL4.into_pixel_fmt(Bgra8888);
191 assert_eq!(pix, [0x33, 0x22, 0x11, 0x44]);
192 }
193
194 #[test]
195 fn color4_to_rgba4444() {
196 let pix: [u8; 2] = COL4.into_pixel_fmt(Rgba4444);
197 assert_eq!(pix, [0x34, 0x12]);
198
199 let pix: u16 = COL4.into_pixel_fmt(Rgba4444);
200 assert_eq!(pix, 0x1234);
201 }
202}