1use embedded_graphics::pixelcolor::raw::RawU16;
2use embedded_graphics::pixelcolor::*;
3
4#[derive(Eq, PartialEq, Clone, Copy)]
6pub struct Rgb16(pub u8, pub u8);
7
8impl Rgb16 {
9 pub const fn from_rgb(r: u16, g: u16, b: u16) -> Self {
10 let r = r >> 3;
11 let g = g >> 2;
12 let b = b >> 3;
13 let raw = (b << 11) | ((g & 0b_0011_1111) << 5) | (r & 0b_0001_1111);
14 let raw = raw.to_le_bytes();
15 Self(!raw[0], !raw[1])
16 }
17
18 pub const fn into_rgb(self) -> (u8, u8, u8) {
19 let raw = u16::from_le_bytes([!self.0, !self.1]);
20 let r = (raw << 3) as u8;
21 let g = ((raw >> 5) << 2) as u8;
22 let b = ((raw >> 11) << 3) as u8;
23 (r, g, b)
24 }
25}
26
27impl PixelColor for Rgb16 {
28 type Raw = RawU16;
29}
30
31impl RgbColor for Rgb16 {
32 const MAX_R: u8 = 32;
33 const MAX_G: u8 = 64;
34 const MAX_B: u8 = 32;
35 const BLACK: Self = Self::from_rgb(0, 0, 0);
36 const RED: Self = Self::from_rgb(255, 0, 0);
37 const GREEN: Self = Self::from_rgb(0, 255, 0);
38 const BLUE: Self = Self::from_rgb(0, 0, 255);
39 const YELLOW: Self = Self::from_rgb(255, 255, 0);
40 const MAGENTA: Self = Self::from_rgb(255, 0, 255);
41 const CYAN: Self = Self::from_rgb(0, 255, 255);
42 const WHITE: Self = Self::from_rgb(255, 255, 255);
43
44 fn r(&self) -> u8 {
45 let (r, _, _) = self.into_rgb();
46 r
47 }
48
49 fn g(&self) -> u8 {
50 let (_, g, _) = self.into_rgb();
51 g
52 }
53
54 fn b(&self) -> u8 {
55 let (_, _, b) = self.into_rgb();
56 b
57 }
58}
59
60impl From<Rgb888> for Rgb16 {
61 fn from(c: Rgb888) -> Self {
62 let r = u16::from(c.r());
63 let g = u16::from(c.g());
64 let b = u16::from(c.b());
65 Self::from_rgb(r, g, b)
66 }
67}
68
69impl From<Rgb16> for Rgb888 {
70 fn from(c: Rgb16) -> Self {
71 let (mut r, mut g, mut b) = c.into_rgb();
72 if r == 0b1111_1000 {
73 r = 0xff;
74 }
75 if g == 0b1111_1100 {
76 g = 0xff;
77 }
78 if b == 0b1111_1000 {
79 b = 0xff;
80 }
81 Self::new(r, g, b)
82 }
83}
84
85pub trait FromRGB {
87 const BG: Self;
89 const PRIMARY: Self;
91 const ACCENT: Self;
93 const DANGER: Self;
95 const MUTED: Self;
97
98 fn from_rgb(rgb: Rgb16) -> Self;
99}
100
101impl FromRGB for Rgb16 {
102 const BG: Self = Self::from_rgb(0xf4, 0xf4, 0xf4);
103 const PRIMARY: Self = Self::from_rgb(0x1a, 0x1c, 0x2c);
104 const ACCENT: Self = Self::from_rgb(0x38, 0xb7, 0x64);
105 const DANGER: Self = Self::from_rgb(0xb1, 0x3e, 0x53);
106 const MUTED: Self = Self::from_rgb(0x94, 0xb0, 0xc2);
107
108 fn from_rgb(rgb: Self) -> Self {
109 rgb
110 }
111}
112
113impl FromRGB for Rgb565 {
114 const BG: Self = new_rgb565(0xf4, 0xf4, 0xf4);
115 const PRIMARY: Self = new_rgb565(0x1a, 0x1c, 0x2c);
116 const ACCENT: Self = new_rgb565(0x38, 0xb7, 0x64);
117 const DANGER: Self = new_rgb565(0xb1, 0x3e, 0x53);
118 const MUTED: Self = new_rgb565(0x94, 0xb0, 0xc2);
119
120 fn from_rgb(rgb: Rgb16) -> Self {
121 let (r, g, b) = rgb.into_rgb();
122 Self::new(r, g, b)
123 }
124}
125
126impl FromRGB for Rgb888 {
127 const BG: Self = Self::new(0xf4, 0xf4, 0xf4);
128 const PRIMARY: Self = Self::new(0x1a, 0x1c, 0x2c);
129 const ACCENT: Self = Self::new(0x38, 0xb7, 0x64);
130 const DANGER: Self = Self::new(0xb1, 0x3e, 0x53);
131 const MUTED: Self = Self::new(0x94, 0xb0, 0xc2);
132
133 fn from_rgb(rgb: Rgb16) -> Self {
134 rgb.into()
135 }
136}
137
138const fn new_rgb565(r: u8, g: u8, b: u8) -> Rgb565 {
139 let r = r as u32 * Rgb565::MAX_R as u32 / Rgb888::MAX_R as u32;
140 let g = g as u32 * Rgb565::MAX_G as u32 / Rgb888::MAX_G as u32;
141 let b = b as u32 * Rgb565::MAX_B as u32 / Rgb888::MAX_B as u32;
142 debug_assert!(r < 256);
143 debug_assert!(g < 256);
144 debug_assert!(b < 256);
145 Rgb565::new(r as u8, g as u8, b as u8)
146}