diff --git a/CHANGELOG.md b/CHANGELOG.md index 4dcd9be..0ac8529 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ### Added - Color converting to HSL, LCh, and RGB. - - TOML configuration (optional): - - Color distance - - Benchmark - - Midpoints + - TOML configuration (optional). + +## \[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..e69de29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,302 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] -name = "anyhow" -version = "1.0.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "color-blender-rs" -version = "0.3.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" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 657caf9..0b7bd1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ [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 [dependencies] -structopt = "0.3" anyhow = "1.0" rayon = "1.8" +clap = { version = "4.4.13", features = ["derive"] } \ No newline at end of file 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 b0353c8..385e088 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,28 +1,34 @@ -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, + #[arg(short, long, help = "Output file path")] + output: Option, + + #[arg(short, long, help = "Calculates the sRGB distance between two colors")] + distance: bool, + #[structopt(short, long, help = "Output file path")] output: Option, @@ -35,7 +41,7 @@ struct Opt { 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,6 +50,32 @@ fn main() -> Result<()> { let mut colors: Vec = Vec::new(); if opt.benchmark { + 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 / opt.midpoints as u32).as_nanos(); + + for color in &colors { + println!("{}", color); + } + + 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 (r, g, b) = firstcolors; + let first_colors = (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 num_iterations = &opt.midpoints; let start_time = Instant::now(); @@ -94,19 +126,16 @@ fn main() -> Result<()> { return Ok(()); } + colors = blender.blend_colors(); 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 - )) - }); + + return write_colors(colors, writer) + .with_context(|| format!("Error while writing file to '{}'", path.display())); } None => { for color in colors { @@ -125,15 +154,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() }