1#[derive(Debug, Clone)]
2pub enum ColorError {
3 FormatErr(String),
4 ValueErr(String),
5}
6
7pub fn calc_rgb_with_alpha(v: u8, alpha: f32) -> f32 {
8 v as f32 * alpha + 255.0 * (1.0 - alpha)
9}
10
11pub fn rgb_to_hsl(r: u8, g: u8, b: u8) -> (u32, u32, u32) {
12 calc_rgb_to_hsl(r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0)
13}
14pub fn rgba_to_hsla(r: u8, g: u8, b: u8, a: f32) -> (u32, u32, u32, f32) {
15 let (h, s, l) = rgb_to_hsl(r, g, b);
16 (h, s, l, a)
17}
18
19pub fn calc_rgb_to_hsl(r: f32, g: f32, b: f32) -> (u32, u32, u32) {
20 let c_max = r.max(g).max(b);
21 let c_min = r.min(g).min(b);
22 let delta = c_max - c_min;
23 let mut h = if delta == 0.0 {
24 0.0
25 } else if c_max == r {
26 60.0 * ((g - b) / delta % 6.0)
27 } else if c_max == g {
28 60.0 * ((b - r) / delta + 2.0)
29 } else {
30 60.0 * ((r - g) / delta + 4.0)
31 };
32 if h < 0.0 {
33 h += 360.0;
34 }
35 let l = (c_max + c_min) / 2.0;
36 let s = if delta == 0.0 {
37 0.0
38 } else {
39 delta / (1.0 - (2.0 * l - 1.0).abs())
40 };
41 (
42 h.round() as u32,
43 (s * 100.0).round() as u32,
44 (l * 100.0).round() as u32,
45 )
46}
47
48pub fn hsl_to_rgb(h: u32, s: u32, l: u32) -> (u8, u8, u8) {
49 let s = s as f32 / 100.0;
50 let l = l as f32 / 100.0;
51 let c = (1.0 - (l * 2.0 - 1.0).abs()) * s;
52 let x = c * (1.0 - ((h as f32 / 60.0) % 2.0 - 1.0).abs());
53 let m = l - c / 2.0;
54 let (mut r, mut g, mut b) = match h {
55 n if n < 60 => (c, x, 0.0),
56 n if (60..120).contains(&n) => (x, c, 0.0),
57 n if (120..180).contains(&n) => (0.0, c, x),
58 n if (180..240).contains(&n) => (0.0, x, c),
59 n if (240..300).contains(&n) => (x, 0.0, c),
60 n if (300..360).contains(&n) => (c, 0.0, x),
61 _ => (0.0, 0.0, 0.0),
62 };
63 r = (r + m) * 255.0;
64 g = (g + m) * 255.0;
65 b = (b + m) * 255.0;
66 (r.round() as u8, g as u8, b.round() as u8)
67}
68
69pub fn rgb_to_hsv(r: u8, g: u8, b: u8) -> (u32, u32, u32) {
70 let r = r as f32 / 255.0;
71 let g = g as f32 / 255.0;
72 let b = b as f32 / 255.0;
73
74 let c_max = r.max(g).max(b);
75 let c_min = r.min(g).min(b);
76 let delta = c_max - c_min;
77
78 let mut h = if delta == 0.0 {
79 0.0
80 } else if c_max == r {
81 60.0 * (((g - b) / delta) % 6.0)
82 } else if c_max == g {
83 60.0 * (((b - r) / delta) + 2.0)
84 } else {
85 60.0 * (((r - g) / delta) + 4.0)
86 };
87
88 if h < 0.0 {
89 h += 360.0;
90 }
91
92 let s = if c_max == 0.0 { 0.0 } else { delta / c_max };
93
94 let v = c_max;
95 (
96 h.round() as u32,
97 (s * 100.0).round() as u32,
98 (v * 100.0).round() as u32,
99 )
100}
101
102pub fn hsv_to_rgb(h: u32, s: u32, v: u32) -> (u8, u8, u8) {
103 let s = s as f32 / 100.0;
104 let v = v as f32 / 100.0;
105 let c = v * s;
106 let x = c * (1.0 - ((h as f32 / 60.0) % 2.0 - 1.0).abs());
107 let m = v - c;
108 let (mut r, mut g, mut b) = match h {
109 n if n < 60 => (c, x, 0.0),
110 n if (60..120).contains(&n) => (x, c, 0.0),
111 n if (120..180).contains(&n) => (0.0, c, x),
112 n if (180..240).contains(&n) => (0.0, x, c),
113 n if (240..300).contains(&n) => (x, 0.0, c),
114 n if (300..360).contains(&n) => (c, 0.0, x),
115 _ => (0.0, 0.0, 0.0),
116 };
117 r = (r + m) * 255.0;
118 g = (g + m) * 255.0;
119 b = (b + m) * 255.0;
120 (r as u8, g as u8, b.round() as u8)
121}
122
123pub fn rgb_to_cmyk(r: u8, g: u8, b: u8) -> (u8, u8, u8, u8) {
124 let r = r as f32 / 255.0;
125 let g = g as f32 / 255.0;
126 let b = b as f32 / 255.0;
127
128 let k = 1.0 - r.max(g).max(b);
129 let (c, m, y) = if k == 1.0 {
130 (0.0, 0.0, 0.0)
131 } else {
132 (
133 (1.0 - r - k) / (1.0 - k),
134 (1.0 - g - k) / (1.0 - k),
135 (1.0 - b - k) / (1.0 - k),
136 )
137 };
138 (
139 (c * 100.0).round() as u8,
140 (m * 100.0).round() as u8,
141 (y * 100.0).round() as u8,
142 (k * 100.0).round() as u8,
143 )
144}
145
146pub fn cmyk_to_rgb(c: u8, m: u8, y: u8, k: u8) -> (u8, u8, u8) {
147 let c = c as f32 / 100.0;
148 let m = m as f32 / 100.0;
149 let y = y as f32 / 100.0;
150 let k = k as f32 / 100.0;
151 let t = 1.0 - k;
152 let r = ((1.0 - c) * t * 255.0).round() as u8;
153 let g = ((1.0 - m) * t * 255.0).round() as u8;
154 let b = ((1.0 - y) * t * 255.0).round() as u8;
155 (r, g, b)
156}
157
158pub fn process_hex(hex_str: &str, chunk_size: usize) -> Vec<u8> {
159 hex_str
160 .chars()
161 .collect::<Vec<_>>()
162 .chunks(chunk_size)
163 .map(|c| c.iter().collect::<String>())
164 .map(|v| u8::from_str_radix(&v.repeat(2)[0..2], 16))
165 .filter_map(|v| v.ok())
166 .collect::<Vec<_>>()
167}