about summary refs log tree commit diff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs175
1 files changed, 0 insertions, 175 deletions
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index f1915f8..0000000
--- a/src/main.rs
+++ /dev/null
@@ -1,175 +0,0 @@
-use std::time::Instant;
-use std::{collections::HashMap, env::args};
-
-use image::io::Reader as ImageReader;
-use image::Rgb;
-
-use ahash::RandomState;
-
-use rayon::prelude::*;
-
-const MAX_COLORS: usize = 16;
-
-const RGB_TOLERANCE: f32 = 0.25 + (1.0 - (MAX_COLORS as f32 / 256.0));
-
-fn main() {
-    let filename = args().nth(1).unwrap();
-    let outname = args().nth(2).unwrap();
-    // The percent of RGB value difference a color has to surpass to be considered unique
-
-    let imageread = ImageReader::open(&filename).expect("Failed to open image!");
-    let mut image = imageread
-        .decode()
-        .expect("Failed to decode image!")
-        .into_rgb8();
-
-    //let mem_before_sort = mallinfo().hblkhd as usize;
-    let start_sort = Instant::now();
-    let sorted_colors = unique_and_sort(image.pixels());
-    println!("Sort took {}s", start_sort.elapsed().as_secs_f32());
-
-    //let mem_before_selection = mallinfo().hblkhd as usize;
-    let start_selection = Instant::now();
-    let selected_colors = select_colors(&sorted_colors);
-    println!(
-        "Color Selection took {}s. Count {}",
-        start_selection.elapsed().as_secs_f32(),
-        selected_colors.len()
-    );
-
-    let start_array = Instant::now();
-    let mut array = vec![0usize; 256 * 256 * 256];
-    println!(
-        "Array creation took {}s",
-        start_array.elapsed().as_secs_f32()
-    );
-
-    let start_map = Instant::now();
-
-    for (sorted, _) in &sorted_colors {
-        let mut min_diff = f32::MAX;
-        let mut min_index = usize::MAX;
-
-        for (index, selected) in selected_colors.iter().enumerate() {
-            let diff = rgb_difference(sorted, selected);
-            if diff < min_diff {
-                min_diff = diff;
-                min_index = index;
-            }
-        }
-
-        array[color_index(sorted)] = min_index;
-    }
-
-    println!(
-        "Creating color map {:.2}s",
-        start_map.elapsed().as_secs_f32()
-    );
-
-    let start_fill = Instant::now();
-    // Max complexity is O(n * max_colors)
-    for color in image.pixels_mut() {
-        let index = array[color_index(color)];
-
-        *color = selected_colors[index];
-    }
-    println!(
-        "Took {:.2}s to fill in the image.\nTotal time from sort {:.2}s",
-        start_fill.elapsed().as_secs_f32(),
-        start_sort.elapsed().as_secs_f32()
-    );
-
-    image.save(outname).expect("Failed to write out");
-}
-
-fn unique_and_sort<'a, T>(pixels: T) -> Vec<(Rgb<u8>, usize)>
-where
-    T: Iterator<Item = &'a Rgb<u8>>,
-{
-    let mut colors: HashMap<Rgb<u8>, usize, RandomState> = HashMap::default();
-
-    //count pixels
-    for pixel in pixels {
-        match colors.get_mut(pixel) {
-            None => {
-                colors.insert(*pixel, 1);
-            }
-            Some(n) => *n += 1,
-        }
-    }
-
-    let mut sorted: Vec<(Rgb<u8>, usize)> = colors.into_par_iter().collect();
-    sorted.sort_by(|(colour1, freq1), (colour2, freq2)| {
-        freq2
-            .cmp(freq1)
-            .then(colour2[0].cmp(&colour1[0]))
-            .then(colour2[1].cmp(&colour1[1]))
-            .then(colour2[2].cmp(&colour1[2]))
-    });
-
-    sorted
-}
-
-fn select_colors(sorted: &[(Rgb<u8>, usize)]) -> Vec<Rgb<u8>> {
-    let mut selected_colors: Vec<Rgb<u8>> = Vec::with_capacity(MAX_COLORS);
-
-    for (key, _value) in sorted.iter() {
-        if selected_colors.len() >= MAX_COLORS {
-            break;
-        } else if selected_colors
-            .iter()
-            .all(|color| rgb_difference(key, color) > RGB_TOLERANCE)
-        {
-            selected_colors.push(*key);
-        }
-    }
-
-    selected_colors
-}
-
-#[inline(always)]
-fn color_index(c: &Rgb<u8>) -> usize {
-    c.0[0] as usize * (256 * 256) + c.0[1] as usize * 256 + c.0[2] as usize
-}
-
-#[allow(clippy::many_single_char_names)]
-#[inline(always)]
-fn rgb_difference(a: &Rgb<u8>, z: &Rgb<u8>) -> f32 {
-    let (a, b, c) = pixel_rgb_to_hsv(a);
-    let (d, e, f) = pixel_rgb_to_hsv(z);
-
-    (((c - f) * (c - f)) + ((a - d).abs() / 90.0) + (b - e).abs()) as f32
-}
-
-#[allow(clippy::float_cmp)]
-fn pixel_rgb_to_hsv(a: &Rgb<u8>) -> (f32, f32, f32) {
-    let (r, g, b) = (
-        a.0[0] as f32 / 256.0,
-        a.0[1] as f32 / 256.0,
-        a.0[2] as f32 / 256.0,
-    );
-
-    let value = r.max(g.max(b));
-    let x_min = r.min(g.min(b));
-    let chroma = value - x_min;
-
-    let hue = if chroma == 0.0 {
-        0.0
-    } else if value == r {
-        60.0 * ((g - b) / chroma)
-    } else if value == g {
-        60.0 * (2.0 + (b - r) / chroma)
-    } else if value == b {
-        60.0 * (4.0 + (r - g) / chroma)
-    } else {
-        unreachable!()
-    };
-
-    let value_saturation = if value == 0.0 { 0.0 } else { chroma / value };
-
-    /* Rotate the color wheel counter clockwise to the negative location
-          |       Keep the wheel in place and remove any full rotations
-     _____V____ _____V____
-    |          |          |*/
-    ((hue + 360.0) % 360.0, value_saturation * 2.0, value * 2.0)
-}