image_effects/colour/
utils.rs1use palette::{Srgb, FromColor, Lch};
2
3use super::comparisons::rgb_weighted_euclidean;
4
5#[inline] pub fn collapse_angle(angle: f32) -> f32 {
6 ((angle % 360.0) + 360.0) % 360.0
7}
8
9pub fn quantize_hue(original_hue: f32, hues: &[f32]) -> f32 {
10 let mut closest_dist = f32::MAX;
11 let pixel_hue = collapse_angle(original_hue);
12 let mut current_hue = pixel_hue;
13
14 for hue in hues.iter() {
15 let normalized = collapse_angle(*hue);
16 let distance = (normalized - pixel_hue).abs();
17 if distance < closest_dist {
18 closest_dist = distance;
19 current_hue = normalized;
20 }
21 }
22
23 current_hue
24}
25
26pub const ONE_BIT: &'static [Srgb] = &[
27 Srgb::new(0.0, 0.0, 0.0),
28 Srgb::new(1.0, 1.0, 1.0),
29];
30
31fn quantize_colour(
32 original: (f32, f32, f32),
33 palette: &[(f32, f32, f32)],
34 distance_fn: fn((f32, f32, f32), (f32, f32, f32)) -> f32,
35) -> (f32, f32, f32) {
36 let mut closest_distance = f32::MAX;
37 let mut current_colour = &original;
38
39 for colour in palette.iter() {
40 let distance = distance_fn(
41 original,
42 *colour,
43 );
44 if distance < closest_distance {
45 current_colour = colour;
46 closest_distance = distance;
47 };
48 }
49
50 *current_colour
51}
52
53pub fn quantize_rgb(original_rgb: Srgb, palette: &[Srgb]) -> Srgb {
54 let srgb = quantize_colour(
55 original_rgb.into_components(),
56 &palette.into_iter().map(|&col| col.into_components()).collect::<Vec<_>>(),
57 rgb_weighted_euclidean
58 );
59
60 Srgb::from_components(srgb)
61}
62
63pub fn compute_rgb_error(main: Srgb, other: Srgb) -> (f32, f32, f32) {
64 (main - other).into_components()
65}
66
67pub fn grayscale_rgb(rgb: Srgb) -> Srgb {
68 let mut lch = Lch::from_color(rgb);
69 lch.chroma = 0.0;
70 Srgb::from_color(lch)
71}
72
73pub fn hexcode_to_srgb(value: &str) -> Srgb {
74 let r = u8::from_str_radix(&value[0..=1], 16);
75 let g = u8::from_str_radix(&value[2..=3], 16);
76 let b = u8::from_str_radix(&value[4..=5], 16);
77
78 if let (Ok(r), Ok(g), Ok(b)) = (r, g, b) {
79 let (r, g, b) = (
80 r as f32 / 255.0,
81 g as f32 / 255.0,
82 b as f32 / 255.0,
83 );
84 Srgb::new(r, g, b)
85 } else {
86 println!(
87 "WARNING! Couldn't convert {} into an RGB value. Returning black.",
88 value
89 );
90 Srgb::new(0.0, 0.0, 0.0)
91 }
92}