From c9cda602b742a16dcc20c1c42acef5ff62975cb7 Mon Sep 17 00:00:00 2001 From: #84837 Date: Sun, 24 Dec 2023 14:30:34 +0100 Subject: [PATCH 1/7] update deps --- Cargo.lock | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++---- Cargo.toml | 3 +- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5fe6e2a..c5657aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" [[package]] name = "atty" @@ -28,12 +28,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "clap" version = "2.34.0" @@ -54,9 +66,47 @@ name = "color-blender-rs" version = "0.2.0" dependencies = [ "anyhow", + "rayon", "structopt", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "heck" version = "0.3.3" @@ -83,9 +133,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "proc-macro-error" @@ -113,9 +163,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" dependencies = [ "unicode-ident", ] @@ -129,6 +179,26 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "strsim" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index 6e59d67..657caf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "color-blender-rs" -version = "0.2.0" +version = "0.3.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -8,3 +8,4 @@ edition = "2021" [dependencies] structopt = "0.3" anyhow = "1.0" +rayon = "1.8" From bd9903640e5348d2e3703d04bd90e6807ac11a9b Mon Sep 17 00:00:00 2001 From: #84837 Date: Sun, 24 Dec 2023 14:30:47 +0100 Subject: [PATCH 2/7] update readme and changelog --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ README.md | 10 +++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 257da80..4dcd9be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ## \[Unreleased\] +### Added + + - Color converting to HSL, LCh, and RGB. + - TOML configuration (optional): + - Color distance + - Benchmark + - Midpoints + +## \[0.3.0\] - 2023-12-24 + +### Added + + - Added the option to benchmark the color blending. + - Added the possibility to calculate the difference between two hexadecimal + colors. + +### Changed + + - Updated dependencies in `Cargo.lock` (`anyhow`, `libc`, `proc-macro2`, `rayon`). + - The GitHub Actions workflows now check, test and build on Windows and Linux. + - Bumped version in `Cargo.toml` (0.2.0 -\> 0.3.0). + +### Removed + + - Removed the `-w, --write` flag, as the `-o, --output` flag is more concise. + ## \[0.2.0\] - 2023-12-09 ### Fixed diff --git a/README.md b/README.md index 277012c..4925360 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,14 @@ $ cargo build --release ## Usage ```console -$ ./color-blender-rs [-m --write -o ] +$ ./color-blender-rs [-m -o --benchmark>] ``` - ``: The starting hexadecimal color (e.g., "\#ff0000" for red). - ``: The ending hexadecimal color (e.g., "\#00ff00" for green). - ``: The number of midpoints to generate between the start and end colors. The default is 10. - - ``: Specify if you want to write the blended colors to a file. If you won't, it will display the colors in the console. - - ``: Self-explanatory. + - ``: The output file to write the blended colors. (default: print colors to console). + - ``: Gets the time it takes to blend the colors in microseconds. ### Examples @@ -47,7 +47,7 @@ $ ./color-blender-rs "#ff0000" "#00ff00" 5 Blend 10 midpoints between blue (\#0000ff) and yellow (\#ffff00) and write the output to default (output.txt): ```console -$ ./color-blender-rs "#0000ff" "#ffff00" 10 --write +$ ./color-blender-rs "#0000ff" "#ffff00" 10 -o output.txt ``` ## Contributing @@ -74,4 +74,4 @@ This project is licensed under the [GNU General Public License, version 3](LICEN ## Project status -Development is not particularly active as [I](https://github.com/walker84837) work on it when I have time. Contributions are welcome. \ No newline at end of file +Development is not particularly active as [I](https://github.com/walker84837) work on it when I have time. Contributions are welcome. From 01e5ce66a438a9172b6a311427866189fd840b3e Mon Sep 17 00:00:00 2001 From: #84837 Date: Sun, 24 Dec 2023 14:30:58 +0100 Subject: [PATCH 3/7] update workflow --- .github/workflows/rust.yml | 41 +++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 31000a2..9b43031 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,22 +1,35 @@ name: Rust on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] env: - CARGO_TERM_COLOR: always + CARGO_TERM_COLOR: always jobs: - build: + build-linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Check on Linux + run: cargo check --verbose + - name: Build on Linux + run: cargo build --verbose + - name: Run tests on Linux + run: cargo test --verbose - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Build - run: cargo build --verbose - - name: Run tests - run: cargo test --verbose + build-windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Rust on Windows + uses: actions/setup-rust@v1 + - name: Check on Windows + run: cargo check --verbose + - name: Build on Windows + run: cargo build --verbose + - name: Run tests on Windows + run: cargo test --verbose \ No newline at end of file From 050d7d893e099a0c1134c783d415e12bf012e398 Mon Sep 17 00:00:00 2001 From: #84837 Date: Sun, 24 Dec 2023 14:31:18 +0100 Subject: [PATCH 4/7] add features --- src/color_blender.rs | 71 +++++++++++++++++----- src/main.rs | 141 ++++++++++++++++++++++++++++++------------- 2 files changed, 154 insertions(+), 58 deletions(-) diff --git a/src/color_blender.rs b/src/color_blender.rs index 4226f13..36eee18 100644 --- a/src/color_blender.rs +++ b/src/color_blender.rs @@ -1,3 +1,5 @@ +use anyhow::Result; +use rayon::prelude::*; use std::cmp::Ordering; #[derive(Clone)] @@ -7,6 +9,16 @@ pub struct ColorBlender { precision: usize, } +impl Default for ColorBlender { + fn default() -> Self { + ColorBlender { + start_color: "#000000".to_string(), + end_color: "#ffffff".to_string(), + precision: 10, + } + } +} + impl ColorBlender { pub fn new(start_color: String, end_color: String, precision: usize) -> ColorBlender { ColorBlender { @@ -23,14 +35,15 @@ impl ColorBlender { let count = self.precision + 2; (0..count) + .into_par_iter() .map(|i| { - let t = i as f64 / (count - 1) as f64; - let r = start.red + ((end.red - start.red) as f64 * t) as i32; - let g = start.green + ((end.green - start.green) as f64 * t) as i32; - let b = start.blue + ((end.blue - start.blue) as f64 * t) as i32; + let step = i as f64 / (count - 1) as f64; + let r = start.red + ((end.red - start.red) as f64 * step) as i32; + let g = start.green + ((end.green - start.green) as f64 * step) as i32; + let b = start.blue + ((end.blue - start.blue) as f64 * step) as i32; Color::new(r, g, b) }) - .map(Self::color_to_hex) + .map(ColorConverter::rgb_to_hex) .collect() } @@ -43,24 +56,32 @@ impl ColorBlender { hex_to_int(&hex_color[5..7]), ) } +} - fn color_to_hex(color: Color) -> String { - format!("#{:02X}{:02X}{:02X}", color.red, color.green, color.blue) +pub struct ColorConverter; + +impl ColorConverter { + pub fn rgb_to_hex(color: Color) -> String { + format!("#{:02x}{:02x}{:02x}", color.red, color.green, color.blue) } -} -impl Default for ColorBlender { - fn default() -> Self { - ColorBlender { - start_color: "#000000".to_string(), - end_color: "#ffffff".to_string(), - precision: 10, + pub fn hex_to_rgb(hex_color: &str) -> Result<(u8, u8, u8)> { + if !hex_color.starts_with('#') { + return Err(anyhow::Error::msg("Error while parsing color")); } + + let hex_to_u8 = |s: &str| u8::from_str_radix(s, 16).unwrap_or(0); + + let r = hex_to_u8(&hex_color[1..3]); + let g = hex_to_u8(&hex_color[3..5]); + let b = hex_to_u8(&hex_color[5..7]); + + Ok((r, g, b)) } } -#[derive(/*Debug, */PartialEq, Eq/*, Clone*/)] -struct Color { +#[derive(PartialEq, Eq)] +pub struct Color { red: i32, green: i32, blue: i32, @@ -86,3 +107,21 @@ impl PartialOrd for Color { Some(self.cmp(other)) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn color_blending() { + let blender = ColorBlender::new("#ff0000".to_string(), "#00ff00".to_string(), 5); + let blended_colors = blender.blend_colors(); + assert_eq!(blended_colors.len(), 7); + } + + #[test] + fn hex_to_rgb_converting() { + let rgb_result = ColorConverter::hex_to_rgb("#ff0000").unwrap(); + assert_eq!(rgb_result, (255, 0, 0)); + } +} diff --git a/src/main.rs b/src/main.rs index 10a9df5..2cd8931 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,17 @@ -use anyhow::Result; +use anyhow::{Error, Result}; use std::{ fs::File, io::{BufWriter, Write}, path::PathBuf, + time::Instant, }; use structopt::StructOpt; pub struct Blending; mod color_blender; -use color_blender::ColorBlender; +use color_blender::{ColorBlender, ColorConverter}; -#[derive(StructOpt, Debug)] +#[derive(StructOpt)] #[structopt(name = "color-blender-rs", about = "A color blender, written in Rust.")] struct Opt { #[structopt(help = "The first color in hex format")] @@ -22,60 +23,116 @@ struct Opt { #[structopt(short, long, default_value = "10", help = "Number of midpoints")] midpoints: usize, - #[structopt(short, long, help = "Output file path", default_value = "output.txt")] - output: PathBuf, + #[structopt(short, long, help = "Output file path")] + output: Option, - #[structopt( - short = "w", - long = "write", - help = "Write the blended colors to a file" - )] - should_write: bool, + #[structopt(short, long, help = "Calculates the sRGB distance between two colors")] + distance: bool, + + #[structopt(short, long, help = "Prints the time it took to blend colors")] + benchmark: bool, } + fn main() -> Result<()> { let opt = Opt::from_args(); - let blender = ColorBlender::new(opt.first_color, opt.second_color, opt.midpoints); - let colors = blender.blend_colors(); + let first_color = opt.first_color.to_string(); + let second_color = opt.second_color.to_string(); - let file = File::create(opt.output)?; - let writer = BufWriter::new(file); + let blender = ColorBlender::new(first_color, second_color, opt.midpoints); + let mut colors: Vec = Vec::new(); - match opt.should_write { - true => match Blending::write(colors, writer) { - Ok(_) => { - return Ok(()); - } - Err(err) => { - let error_msg = format!("Error: {}", err); - return Err(anyhow::Error::msg(error_msg)); - } - }, - false => { - Blending::print(colors); - } - }; + if opt.benchmark { + let num_iterations = &opt.midpoints; - Ok(()) -} + let start_time = Instant::now(); + colors = blender.blend_colors(); + let end_time = Instant::now(); -impl Blending { - pub fn write(blended_colors: Vec, mut writer: W) -> Result<()> { - let mut buffered_writer = BufWriter::new(&mut writer); + let elapsed_time = end_time - start_time; + let avg_time_per_iteration = (elapsed_time / *num_iterations as u32).as_nanos(); - for color in &blended_colors { - writeln!(buffered_writer, "{}", color)?; + for color in &colors { + println!("{}", color); } - buffered_writer.flush()?; - println!("Data written successfully."); + println!("Elapsed time: {}μs", elapsed_time.as_micros()); + println!("Average time per iteration: {}ns", avg_time_per_iteration); + return Ok(()); + } + + + if opt.distance { + let firstcolors = ColorConverter::hex_to_rgb(&opt.first_color)?; + let lastcolors = ColorConverter::hex_to_rgb(&opt.second_color)?; + + let first_colors = match firstcolors { + (r, g, b) => (r as f32, g as f32, b as f32), + }; - Ok(()) + let last_colors = match lastcolors { + (r, g, b) => (r as f32, g as f32, b as f32), + }; + + let distance = color_difference(first_colors, last_colors); + + println!("Distance: {distance}"); + + if distance == 0.0 { + println!("The colors are identical."); + } else if 0.0 < distance && distance < 0.1 { + println!("There is a difference in color, but it's not noticeable."); + } else if 0.1 < distance && distance < 0.5 { + println!("There is a noticeable but not significant difference in color"); + } else if 0.5 < distance && distance < 1.0 { + println!("There is a potentially significant and very noticeable color difference."); + } else if distance > 1.0 { + println!("There is a significant difference in the colors."); + } + + return Ok(()); } - pub fn print(blended_colors: Vec) { - for color in blended_colors { - println!("{}", color); + + match opt.output { + Some(path) => { + let file = File::create(&path)?; + let writer = BufWriter::new(file); + return write_colors(colors, writer).map_err(|err| { + Error::msg(format!( + "Error while writing file to '{}': {}", + path.display(), + err + )) + }); + } + None => { + colors = blender.blend_colors(); + for color in colors { + println!("{}", color); + } } + }; + Ok(()) +} + +fn write_colors(blended_colors: Vec, mut writer: W) -> Result<()> { + let mut buffered_writer = BufWriter::new(&mut writer); + + for color in &blended_colors { + writeln!(buffered_writer, "{}", color)?; } + + buffered_writer.flush()?; + println!("Data written successfully."); + + Ok(()) +} + +fn color_difference(first_color: (f32, f32, f32), second_color: (f32, f32, f32)) -> f32 { + let difference = ((second_color.0 - first_color.0) / 255.0).powf(2.0) + + ((second_color.1 - first_color.1) / 255.0).powf(2.0) + + ((second_color.2 - first_color.2) / 255.0).powf(2.0); + + difference.sqrt() } From 1c3beeea8e342ec2da7265cfc88d3c94b25c94d1 Mon Sep 17 00:00:00 2001 From: #84837 Date: Sun, 24 Dec 2023 14:33:17 +0100 Subject: [PATCH 5/7] update project version --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index c5657aa..ce3b554 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,7 +63,7 @@ dependencies = [ [[package]] name = "color-blender-rs" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "rayon", From 6fdeb2aa799fac9375288282166c5c93c8f9a9e1 Mon Sep 17 00:00:00 2001 From: #84837 Date: Sun, 14 Jan 2024 22:20:23 +0100 Subject: [PATCH 6/7] 0.3.1 --- CHANGELOG.md | 10 +- Cargo.lock | 270 +++++++++++++++++++++---------------------- Cargo.toml | 2 +- src/color_blender.rs | 2 +- src/main.rs | 55 ++++----- 5 files changed, 164 insertions(+), 175 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dcd9be..bfc2f57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,9 +11,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/). - Color converting to HSL, LCh, and RGB. - TOML configuration (optional): - - Color distance - - Benchmark - - Midpoints + +## \[0.3.1\] - 2024-01-14 + +### Added + + - sRGB color distance + - Benchmarking for color blending ## \[0.3.0\] - 2023-12-24 diff --git a/Cargo.lock b/Cargo.lock index ce3b554..23e3db5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,42 +3,64 @@ version = 3 [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", ] [[package]] -name = "anyhow" -version = "1.0.76" +name = "anstyle" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] -name = "atty" -version = "0.2.14" +name = "anstyle-parse" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ - "hermit-abi", - "libc", - "winapi", + "utf8parse", ] [[package]] -name = "autocfg" -version = "1.1.0" +name = "anstyle-query" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys", +] [[package]] -name = "bitflags" -version = "1.3.2" +name = "anyhow" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "cfg-if" @@ -48,28 +70,59 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "2.34.0" +version = "4.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642" dependencies = [ - "ansi_term", - "atty", - "bitflags", + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", - "vec_map", ] +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + [[package]] name = "color-blender-rs" version = "0.3.0" dependencies = [ "anyhow", + "clap", "rayon", - "structopt", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "crossbeam-deque" version = "0.8.4" @@ -109,57 +162,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.151" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "proc-macro2" @@ -201,102 +206,95 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] -name = "structopt" -version = "0.3.26" +name = "syn" +version = "2.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" +checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" dependencies = [ - "clap", - "lazy_static", - "structopt-derive", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "structopt-derive" -version = "0.4.18" +name = "unicode-ident" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "syn" -version = "1.0.109" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] -name = "textwrap" -version = "0.11.0" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "unicode-width", + "windows-targets", ] [[package]] -name = "unicode-ident" -version = "1.0.12" +name = "windows-targets" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] [[package]] -name = "unicode-segmentation" -version = "1.10.1" +name = "windows_aarch64_gnullvm" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] -name = "unicode-width" -version = "0.1.11" +name = "windows_aarch64_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] -name = "vec_map" -version = "0.8.2" +name = "windows_i686_gnu" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] -name = "version_check" -version = "0.9.4" +name = "windows_i686_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] -name = "winapi" -version = "0.3.9" +name = "windows_x86_64_gnu" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows_x86_64_gnullvm" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows_x86_64_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/Cargo.toml b/Cargo.toml index 657caf9..eaaecae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -structopt = "0.3" anyhow = "1.0" rayon = "1.8" +clap = { version = "4.4.13", features = ["derive"] } diff --git a/src/color_blender.rs b/src/color_blender.rs index 36eee18..401dcf0 100644 --- a/src/color_blender.rs +++ b/src/color_blender.rs @@ -14,7 +14,7 @@ impl Default for ColorBlender { ColorBlender { start_color: "#000000".to_string(), end_color: "#ffffff".to_string(), - precision: 10, + precision: 10usize, } } } diff --git a/src/main.rs b/src/main.rs index 2cd8931..013a86b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,41 +1,40 @@ -use anyhow::{Error, Result}; +use anyhow::{Context, Result}; +use clap::Parser; use std::{ fs::File, io::{BufWriter, Write}, path::PathBuf, time::Instant, }; -use structopt::StructOpt; pub struct Blending; mod color_blender; use color_blender::{ColorBlender, ColorConverter}; -#[derive(StructOpt)] +#[derive(Parser)] #[structopt(name = "color-blender-rs", about = "A color blender, written in Rust.")] struct Opt { - #[structopt(help = "The first color in hex format")] + #[arg(help = "The first color in hex format")] first_color: String, - #[structopt(help = "Second color in hex format")] + #[arg(help = "Second color in hex format")] second_color: String, - #[structopt(short, long, default_value = "10", help = "Number of midpoints")] + #[arg(short, long, default_value = "10", help = "Number of midpoints")] midpoints: usize, - #[structopt(short, long, help = "Output file path")] + #[arg(short, long, help = "Output file path")] output: Option, - #[structopt(short, long, help = "Calculates the sRGB distance between two colors")] + #[arg(short, long, help = "Calculates the sRGB distance between two colors")] distance: bool, - #[structopt(short, long, help = "Prints the time it took to blend colors")] + #[arg(short, long, help = "Prints the time it took to blend colors")] benchmark: bool, } - fn main() -> Result<()> { - let opt = Opt::from_args(); + let opt = Opt::parse(); let first_color = opt.first_color.to_string(); let second_color = opt.second_color.to_string(); @@ -44,14 +43,12 @@ fn main() -> Result<()> { let mut colors: Vec = Vec::new(); if opt.benchmark { - let num_iterations = &opt.midpoints; - let start_time = Instant::now(); colors = blender.blend_colors(); let end_time = Instant::now(); let elapsed_time = end_time - start_time; - let avg_time_per_iteration = (elapsed_time / *num_iterations as u32).as_nanos(); + let avg_time_per_iteration = (elapsed_time / opt.midpoints as u32).as_nanos(); for color in &colors { println!("{}", color); @@ -62,18 +59,15 @@ fn main() -> Result<()> { return Ok(()); } - if opt.distance { let firstcolors = ColorConverter::hex_to_rgb(&opt.first_color)?; let lastcolors = ColorConverter::hex_to_rgb(&opt.second_color)?; - let first_colors = match firstcolors { - (r, g, b) => (r as f32, g as f32, b as f32), - }; + let (r, g, b) = firstcolors; + let first_colors = (r as f32, g as f32, b as f32); - let last_colors = match lastcolors { - (r, g, b) => (r as f32, g as f32, b as f32), - }; + let (r, g, b) = lastcolors; + let last_colors = (r as f32, g as f32, b as f32); let distance = color_difference(first_colors, last_colors); @@ -98,13 +92,8 @@ fn main() -> Result<()> { Some(path) => { let file = File::create(&path)?; let writer = BufWriter::new(file); - return write_colors(colors, writer).map_err(|err| { - Error::msg(format!( - "Error while writing file to '{}': {}", - path.display(), - err - )) - }); + return write_colors(colors, writer) + .with_context(|| format!("Error while writing file to '{}'", path.display())); } None => { colors = blender.blend_colors(); @@ -124,15 +113,13 @@ fn write_colors(blended_colors: Vec, mut writer: W) -> Result< } buffered_writer.flush()?; - println!("Data written successfully."); - Ok(()) } fn color_difference(first_color: (f32, f32, f32), second_color: (f32, f32, f32)) -> f32 { - let difference = ((second_color.0 - first_color.0) / 255.0).powf(2.0) - + ((second_color.1 - first_color.1) / 255.0).powf(2.0) - + ((second_color.2 - first_color.2) / 255.0).powf(2.0); + let difference = ((second_color.0 - first_color.0) / 255.0).powf(2.0) + + ((second_color.1 - first_color.1) / 255.0).powf(2.0) + + ((second_color.2 - first_color.2) / 255.0).powf(2.0); - difference.sqrt() + difference.sqrt() } From b8a6e384af44f76c44dfabaa57dc9fcb86c2864e Mon Sep 17 00:00:00 2001 From: #84837 Date: Sun, 14 Jan 2024 22:24:39 +0100 Subject: [PATCH 7/7] fix cargo.toml --- CHANGELOG.md | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfc2f57..0ac8529 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ### Added - Color converting to HSL, LCh, and RGB. - - TOML configuration (optional): + - TOML configuration (optional). ## \[0.3.1\] - 2024-01-14 diff --git a/Cargo.toml b/Cargo.toml index eaaecae..dc3e758 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "color-blender-rs" -version = "0.3.0" +version = "0.3.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html