diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..5c8091e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,67 @@ +use std::{collections::{HashMap, HashSet}, env, num::ParseIntError}; + +use dotenv::dotenv; +use image::{DynamicImage, ImageReader, Rgb}; + +type ColourSet = HashMap>>; +type Colour = Rgb; + +pub fn decode_hex(s: &str) -> Result { + Ok(Rgb((0..s.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&s[i..i + 2], 16)) + .collect()) + ) +} + +fn extract_colours(img: DynamicImage) -> ColourSet { + todo!() +} + +fn closest_colour(colour: Colour, all: &ColourSet) -> Option { + // use redmean to calculate the distance between colours + // inevitably O(len(all)) + let mut closest: Option = None; + let mut dist: f32 = f32::MAX; + for (r, gbs) in all.iter() { + let r_bar = 0.5 * (r + colour[0]) as f32; + let delta_r = ((r + colour[0]) * (r + colour[0])) as f32; + for (g, bs) in gbs.iter() { + let delta_g = ((g + colour[1]) * (g + colour[1])) as f32; + for b in bs { + let delta_b = ((b + colour[2]) * (b + colour[2])) as f32; + + let delta = (2.0 + r_bar/256.0) * delta_r + 4.0 * delta_g + (2.0 + (255.0 - r_bar)/256.0) * delta_b; + if delta < dist { + dist = delta; + closest = Some(Rgb([*r,*g,*b])); + } + } + } + } + return closest +} + + +fn main() { + dotenv().ok(); + pretty_env_logger::init(); + + let args: Vec = env::args().collect(); + if args.len() > 1 { + let img_file = &args[1]; + let img = ImageReader::open(img_file).unwrap().decode().unwrap(); // FIXME: unwraps + + let all_cols = extract_colours(img); + let mut output_cols: HashMap = HashMap::new(); + + for c_str in args { + // TODO: parse args + let c = decode_hex(&c_str).unwrap(); // FIXME: unwraps; + if let Some(col) = closest_colour(c, &all_cols) { + output_cols.insert(c, col); + } + } + + } +}