From 00f059108af0226eb0effd96f5f6cc866d2b0ba4 Mon Sep 17 00:00:00 2001 From: djairoh Date: Thu, 25 Jun 2026 16:21:41 +0200 Subject: [PATCH] ft: commenting --- src/cli.rs | 4 ++++ src/colours.rs | 35 +++++++++++++++++++++++++++++++++++ src/main.rs | 3 +++ 3 files changed, 42 insertions(+) diff --git a/src/cli.rs b/src/cli.rs index 8b4ad89..4aa4315 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -42,6 +42,9 @@ impl Debug for Cli { } } +// Validates that a given string represents a hex code for a RGB colour. +// +// Optionally accepts a leading '#'. fn valid_hex_code(s: &str) -> Result { // accept leading '#' for hex values let start = match s.chars().nth(0) == Some('#') { @@ -60,6 +63,7 @@ fn valid_hex_code(s: &str) -> Result { Ok(Rgb(rgb)) } +// Validates that agiven string points to a valid image file. fn valid_image_file(s: &str) -> Result { ImageReader::open(s) .map_err(|e| format!("{}", e))? diff --git a/src/colours.rs b/src/colours.rs index a200727..aef122d 100644 --- a/src/colours.rs +++ b/src/colours.rs @@ -6,9 +6,15 @@ use std::fmt::Debug; use crate::encode_hex; +// This type is used to efficiently store all colour values from an image. +// By using nested hashmaps we can save on space for colours with identical r and g values. +// Additionally stores a Vec of points to remember which colour maps to which pixel(s). pub type ColourMap = HashMap>>>; + +// We use one colour type. pub type Colour = Rgb; +// Struct to represent a point in an image. #[derive(Clone)] pub struct Point { x: u32, @@ -21,11 +27,16 @@ impl Debug for Point { } } +// Struct to save found matches for colours. +// includes the matched colour, and a list of pixels with that colour. pub struct Match { + // matched colour pub colour: Colour, + // list of pixels with the matching colour pub positions: Vec, } +// Extract all colours from a provided image into a nested ColourMap pub fn extract_colours(img: DynamicImage) -> ColourMap { let mut out: ColourMap = HashMap::new(); for (x, y, p) in img.pixels() { @@ -40,6 +51,7 @@ pub fn extract_colours(img: DynamicImage) -> ColourMap { out } +// Extract all colours in a provided image into a flat hashmap. fn extract_colours_set(img: DynamicImage) -> HashSet> { let mut out = HashSet::new(); img.pixels().for_each(|(_x, _y, p)| { @@ -48,6 +60,11 @@ fn extract_colours_set(img: DynamicImage) -> HashSet> { out.into_iter().map(|c| Rgb([c[0], c[1], c[2]])).collect() } +// Finds the "closest" match to a colour in the provided map. Uses redmean distance. +// +// arguments: +// colour: Colour which will be matched against all. +// all: Map of Colours to match against. fn closest_colour(colour: &Colour, all: &ColourMap) -> Option { // use redmean to calculate the distance between colours let mut closest: Option = None; @@ -55,16 +72,20 @@ fn closest_colour(colour: &Colour, all: &ColourMap) -> Option { let (colour_r, colour_g, colour_b) = (colour[0] as f32, colour[1] as f32, colour[2] as f32); for (r, gbs) in all.iter() { + // iterate over all reds let r_bar = 0.5 * (*r as f32 + colour_r); let r_squared = (*r as f32 - colour_r) * (*r as f32 - colour_r); for (g, bs) in gbs.iter() { + // iterate over all greens let g_squared = (*g as f32 - colour_g) * (*g as f32 - colour_g); for (b, vec) in bs.iter() { + // iterate over all blues let b_squared = (*b as f32 - colour_b) * (*b as f32 - colour_b); let delta = (2.0 + r_bar / 256.0) * r_squared + 4.0 * g_squared + (2.0 + (255.0 - r_bar) / 256.0) * b_squared; if delta < dist { + // update closest if better match found dist = delta; closest = Some(Match { colour: Rgb([*r, *g, *b]), @@ -79,6 +100,13 @@ fn closest_colour(colour: &Colour, all: &ColourMap) -> Option { return closest; } +// Maps a list of colours to the closest equivalents in the provided map. +// +// arguments: +// all_cols: Map of colours match against. +// cols: Vec of Colours which will be matched against all_cols. +// +// returns: Hashmap of colour, match pairs. pub fn map_image_list(all_cols: &ColourMap, cols: Vec) -> HashMap { let mut output_cols: HashMap = HashMap::new(); @@ -91,6 +119,13 @@ pub fn map_image_list(all_cols: &ColourMap, cols: Vec) -> HashMap HashMap { let img_2_cols = extract_colours_set(img_2); diff --git a/src/main.rs b/src/main.rs index 3a7120b..7037b44 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,10 +9,12 @@ use dotenv::dotenv; use crate::cli::Cli; use crate::colours::{Colour, Match, extract_colours, map_image_image, map_image_list}; +// Encodes a RGB colour as a hex code. fn encode_hex(c: &Colour) -> String { format!("#{:02x}{:02x}{:02x}", c[0], c[1], c[2]) } +// Formats found matches for CLI otuput. fn pretty_print(h: HashMap) { h.iter().for_each(|(k, v)| { println!( @@ -24,6 +26,7 @@ fn pretty_print(h: HashMap) { }) } +// Driver code. fn main() { dotenv().ok(); pretty_env_logger::init();