diff options
author | gennyble <gen@nyble.dev> | 2024-01-14 07:33:52 -0600 |
---|---|---|
committer | gennyble <gen@nyble.dev> | 2024-01-14 07:33:52 -0600 |
commit | 88656a81d8e1480c3e37a3402901525aee1a596c (patch) | |
tree | 3263cc0726b8b05981c11083473e271a2f82d0c8 /squash/src | |
parent | 2b3181f3c4675d744338f497564faa00bc5d76db (diff) | |
download | colorsquash-88656a81d8e1480c3e37a3402901525aee1a596c.tar.gz colorsquash-88656a81d8e1480c3e37a3402901525aee1a596c.zip |
allow choosing selection algorithm
Diffstat (limited to 'squash/src')
-rw-r--r-- | squash/src/cli.rs | 51 | ||||
-rw-r--r-- | squash/src/image.rs | 2 | ||||
-rw-r--r-- | squash/src/main.rs | 24 |
3 files changed, 63 insertions, 14 deletions
diff --git a/squash/src/cli.rs b/squash/src/cli.rs index dec36fa..ba1658a 100644 --- a/squash/src/cli.rs +++ b/squash/src/cli.rs @@ -1,6 +1,7 @@ use std::cmp::Ordering; use camino::Utf8PathBuf; +use colorsquash::difference::{self, DiffFn}; const NAME: &str = env!("CARGO_PKG_NAME"); const VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -9,7 +10,8 @@ const AUTHORS: &str = env!("CARGO_PKG_AUTHORS"); pub struct Cli { pub color_count: u8, pub tolerance: Option<f32>, - pub difference: DifferenceFn, + pub selector: Selector, + pub difference: &'static DiffFn, pub input: Utf8PathBuf, pub in_type: InType, pub output: Utf8PathBuf, @@ -23,6 +25,7 @@ struct BuildingCli { pub color_count: Option<u8>, pub tolerance: Option<f32>, pub difference: DifferenceFn, + pub selector: Selector, } impl BuildingCli { @@ -58,10 +61,16 @@ impl BuildingCli { } }; + let difference = match self.difference { + DifferenceFn::Rgb => &difference::rgb as &DiffFn, + DifferenceFn::Redmean => &difference::redmean as &DiffFn, + }; + Cli { color_count: self.color_count.unwrap_or(Self::DEFAULT_COLORS), tolerance: self.tolerance, - difference: self.difference, + selector: self.selector, + difference, input, in_type, output, @@ -87,6 +96,13 @@ pub enum DifferenceFn { Redmean, } +#[derive(Debug, Default)] +pub enum Selector { + #[default] + SortSelect, + Kmeans, +} + pub fn build() -> Cli { let mut free = vec![]; let mut building = BuildingCli::default(); @@ -142,7 +158,16 @@ pub fn build() -> Cli { std::process::exit(1); } }, + Some(("selector", sel)) | Some(("sel", sel)) => match sel { + "sort/select" => building.selector = Selector::SortSelect, + "kmeans" => building.selector = Selector::Kmeans, + _ => { + eprintln!("'{sel}' is not recognized as a selector. See help=selectors"); + std::process::exit(1); + } + }, Some(("help", "algorithms")) => print_help_algorithms(), + Some(("help", "selectors")) => print_help_selectors(), Some(("help", _)) => print_help(), Some(("version", _)) => print_version(), Some((key, _)) => { @@ -174,12 +199,16 @@ fn print_help() -> ! { println!(" the number of colours the final image should contain"); println!(" a whole number more than 0 and less than, or equal, 256"); println!(" [Default 256]\n"); - println!(" difference=<algorithm> | did=<algorithm>"); + println!(" difference=<algorithm> | dif=<algorithm>"); println!(" the color comparison function to use. one of: rgb, redmean"); - println!(" for more details use help=algorithms. [Default rgb]"); + println!(" for more details use help=algorithms. [Default rgb]\n"); + println!(" selection=<selector> | sel=<selector>"); + println!(" the algorithm for picking the palette. one of: means, sort/select"); + println!(" for more details use help=selectors. [Default sort/select]"); println!(" tolerance=<float> | tol=<float>"); println!(" how different colours should be to be added to the palette"); - println!(" a number > 0 and <= 100\n"); + println!(" only sort/select usese this value."); + println!(" a number > 0 and <= 100 [Default 3]\n"); println!(" help= | -h | --help"); println!(" print this message and exit\n"); println!(" version= | -V | --version"); @@ -199,6 +228,18 @@ fn print_help_algorithms() -> ! { std::process::exit(0) } +fn print_help_selectors() -> ! { + println!("SELECTORS:"); + println!("sort/select:"); + println!(" the original colorsquash algorithm. sorts colors from most to least"); + println!(" frequent and then picks the most frequent colors so long as they are"); + println!(" sufficiently different (configurable with tolerance=)\n"); + println!("kmeans:"); + println!(" uses the kmeans clustering algorithm to select colours."); + println!(" Ignores tolerance="); + std::process::exit(0) +} + fn print_version() -> ! { println!("squash version {VERSION}"); println!("written by {AUTHORS}"); diff --git a/squash/src/image.rs b/squash/src/image.rs index 5c7b45a..ff6650f 100644 --- a/squash/src/image.rs +++ b/squash/src/image.rs @@ -2,7 +2,7 @@ use std::{fs::File, io::BufWriter}; use anyhow::{anyhow, bail}; use camino::{Utf8Path, Utf8PathBuf}; -use colorsquash::Squasher; +use colorsquash::{selection::SortSelect, Squasher}; use gifed::{writer::ImageBuilder, Gif}; use png::{ColorType, Decoder, Encoder}; use zune_jpeg::{zune_core::colorspace::ColorSpace, JpegDecoder}; diff --git a/squash/src/main.rs b/squash/src/main.rs index 8e3a79b..b443f57 100644 --- a/squash/src/main.rs +++ b/squash/src/main.rs @@ -1,5 +1,8 @@ use cli::DifferenceFn; -use colorsquash::SquasherBuilder; +use colorsquash::{ + selection::{Kmeans, Selector, SortSelect}, + SquasherBuilder, +}; use crate::cli::{InType, OutType}; @@ -16,15 +19,20 @@ fn main() -> Result<(), anyhow::Error> { InType::Jpeg => image::get_jpg(cli.input)?, }; - let mut builder = SquasherBuilder::default().max_colors(cli.color_count); + let mut builder = SquasherBuilder::new() + .max_colors(cli.color_count) + .mapper_difference(cli.difference); - if let Some(tol) = cli.tolerance { - builder = builder.tolerance(tol); - } + match cli.selector { + cli::Selector::SortSelect => { + let mut sorsel = SortSelect::default().difference(cli.difference); + if let Some(tol) = cli.tolerance { + sorsel = sorsel.tolerance(tol) + } - builder = match cli.difference { - DifferenceFn::Rgb => builder.difference(&colorsquash::difference::rgb), - DifferenceFn::Redmean => builder.difference(&colorsquash::difference::redmean), + builder = builder.selector(sorsel); + } + cli::Selector::Kmeans => builder = builder.selector(Kmeans), }; let mut squasher = builder.build(&image.data); |