|
| 1 | +use palette::{Hsl, Hsv, Srgb}; |
| 2 | + |
1 | 3 | #[derive(Clone)]
|
2 |
| -pub struct RGBA { |
3 |
| - pub red: u8, |
4 |
| - pub green: u8, |
5 |
| - pub blue: u8, |
6 |
| - pub alpha: u8, |
| 4 | +pub enum Color { |
| 5 | + RGB(Srgb), |
| 6 | + HSV(Hsv), |
| 7 | + HSL(Hsl), |
7 | 8 | }
|
8 | 9 |
|
9 |
| -impl Default for RGBA { |
| 10 | +impl Default for Color { |
10 | 11 | fn default() -> Self {
|
11 |
| - Self { |
12 |
| - red: Default::default(), |
13 |
| - green: Default::default(), |
14 |
| - blue: Default::default(), |
15 |
| - alpha: u8::MAX, |
16 |
| - } |
| 12 | + Self::RGB(Srgb::new(0.0, 0.0, 0.0)) |
17 | 13 | }
|
18 | 14 | }
|
19 | 15 |
|
20 |
| -impl RGBA { |
21 |
| - pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self { |
22 |
| - Self { |
23 |
| - red: r, |
24 |
| - green: g, |
25 |
| - blue: b, |
26 |
| - alpha: a, |
27 |
| - } |
28 |
| - } |
29 |
| - |
30 |
| - pub fn new_rgb(r: u8, g: u8, b: u8) -> Self { |
31 |
| - Self { |
32 |
| - red: r, |
33 |
| - green: g, |
34 |
| - blue: b, |
35 |
| - alpha: u8::MAX, |
36 |
| - } |
37 |
| - } |
38 |
| - |
39 |
| - pub fn to_hex_string(&self) -> String { |
40 |
| - if self.alpha == u8::MAX { |
41 |
| - format!("#{:02X}{:02X}{:02X}", self.red, self.green, self.blue) |
42 |
| - } else { |
43 |
| - format!( |
44 |
| - "#{:02X}{:02X}{:02X}{:02X}", |
45 |
| - self.red, self.green, self.blue, self.alpha |
46 |
| - ) |
47 |
| - } |
| 16 | +impl From<Srgb> for Color { |
| 17 | + fn from(value: Srgb) -> Self { |
| 18 | + Self::RGB(value) |
48 | 19 | }
|
49 | 20 | }
|
50 | 21 |
|
51 |
| -impl From<HSV> for RGBA { |
52 |
| - fn from(value: HSV) -> Self { |
53 |
| - let HSV { |
54 |
| - hue: h, |
55 |
| - saturation: s, |
56 |
| - value: v, |
57 |
| - alpha, |
58 |
| - } = value; |
59 |
| - let h = f64::from(h); |
60 |
| - |
61 |
| - let c = v * s; |
62 |
| - let x = c * (1.0 - f64::abs(((h / 60.0) % 2.0) - 1.0)); |
63 |
| - let m = v - c; |
64 |
| - |
65 |
| - let (r, g, b) = if (0.0..60.0).contains(&h) { |
66 |
| - (c, x, 0.0) |
67 |
| - } else if (60.0..120.0).contains(&h) { |
68 |
| - (x, c, 0.0) |
69 |
| - } else if (120.0..180.0).contains(&h) { |
70 |
| - (0.0, c, x) |
71 |
| - } else if (180.0..240.0).contains(&h) { |
72 |
| - (0.0, x, c) |
73 |
| - } else if (240.0..300.0).contains(&h) { |
74 |
| - (x, 0.0, c) |
75 |
| - } else if (300.0..360.0).contains(&h) { |
76 |
| - (c, 0.0, x) |
77 |
| - } else { |
78 |
| - (c, x, 0.0) |
79 |
| - }; |
80 |
| - |
81 |
| - let (r, g, b) = ( |
82 |
| - ((r + m) * 255.0) as u8, |
83 |
| - ((g + m) * 255.0) as u8, |
84 |
| - ((b + m) * 255.0) as u8, |
85 |
| - ); |
86 |
| - |
87 |
| - RGBA::new(r, g, b, alpha) |
| 22 | +impl From<Hsv> for Color { |
| 23 | + fn from(value: Hsv) -> Self { |
| 24 | + Self::HSV(value) |
88 | 25 | }
|
89 | 26 | }
|
90 | 27 |
|
91 |
| -#[derive(Clone)] |
92 |
| -pub struct HSV { |
93 |
| - pub hue: u16, |
94 |
| - pub saturation: f64, |
95 |
| - pub value: f64, |
96 |
| - pub alpha: u8, |
97 |
| -} |
98 |
| - |
99 |
| -impl HSV { |
100 |
| - pub fn new(hue: u16, saturation: f64, value: f64) -> Self { |
101 |
| - Self { |
102 |
| - hue, |
103 |
| - saturation, |
104 |
| - value, |
105 |
| - alpha: u8::MAX, |
106 |
| - } |
107 |
| - } |
108 |
| - |
109 |
| - pub fn new_alpha(hue: u16, saturation: f64, value: f64, alpha: u8) -> Self { |
110 |
| - Self { |
111 |
| - hue, |
112 |
| - saturation, |
113 |
| - value, |
114 |
| - alpha, |
115 |
| - } |
116 |
| - } |
117 |
| -} |
118 |
| - |
119 |
| -impl From<RGBA> for HSV { |
120 |
| - fn from(value: RGBA) -> Self { |
121 |
| - let RGBA { |
122 |
| - red: r, |
123 |
| - green: g, |
124 |
| - blue: b, |
125 |
| - alpha, |
126 |
| - } = value; |
127 |
| - |
128 |
| - let (r, g, b) = (r as f64 / 255.0, g as f64 / 255.0, b as f64 / 255.0); |
129 |
| - |
130 |
| - let c_max = f64::max(r, f64::max(g, b)); |
131 |
| - let c_min = f64::min(r, f64::min(g, b)); |
132 |
| - let delta = c_max - c_min; |
133 |
| - |
134 |
| - let hue = if delta == 0.0 { |
135 |
| - 0.0 |
136 |
| - } else if c_max == r { |
137 |
| - 60.0 * (((g - b) / delta) % 6.0) |
138 |
| - } else if c_max == g { |
139 |
| - 60.0 * (((b - r) / delta) + 2.0) |
140 |
| - } else if c_max == b { |
141 |
| - 60.0 * (((r - g) / delta) + 4.0) |
142 |
| - } else { |
143 |
| - unreachable!() |
144 |
| - }; |
145 |
| - |
146 |
| - let saturation = match c_max == 0.0 { |
147 |
| - true => 0.0, |
148 |
| - false => delta / c_max, |
149 |
| - }; |
150 |
| - |
151 |
| - let value = c_max; |
152 |
| - |
153 |
| - HSV { |
154 |
| - hue: hue.to_string().parse().unwrap(), |
155 |
| - saturation, |
156 |
| - value, |
157 |
| - alpha, |
158 |
| - } |
| 28 | +impl From<Hsl> for Color { |
| 29 | + fn from(value: Hsl) -> Self { |
| 30 | + Self::HSL(value) |
159 | 31 | }
|
160 | 32 | }
|
0 commit comments