easy_color/
common.rs

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}