diff --git a/Cargo.lock b/Cargo.lock index d83ec0c..10157b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -835,7 +835,7 @@ checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "snapcrop" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "blake3", diff --git a/Cargo.toml b/Cargo.toml index 148569b..52f68f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "snapcrop" description = "CLI for crop/resize of large amounts of images with configurable resolutions" -version = "0.1.0" +version = "0.1.1" edition = "2021" license = "MIT" diff --git a/README.md b/README.md index e25f28c..5d5700f 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,50 @@ Options: Print help (see a summary with '-h') ``` +## Visual examples + +``` +snapcrop squares --res 256 +``` +![](./examples/squares/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png) +![](./examples/squares/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png) +![](./examples/squares/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png) +![](./examples/squares/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png) + +``` +snapcrop landscape --res 256x128 +``` +![](./examples/landscape/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png) +![](./examples/landscape/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png) +![](./examples/landscape/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png) +![](./examples/landscape/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png) + + +``` +snapcrop portrait --res 128x256 +``` +![](./examples/portrait/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png) +![](./examples/portrait/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png) +![](./examples/portrait/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png) +![](./examples/portrait/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png) + + +``` +snapcrop mixed --res 256,[128x256] +``` +![](./examples/mixed/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png) +![](./examples/mixed/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png) +![](./examples/mixed/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png) +![](./examples/mixed/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png) + +``` +snapcrop steps --res [128:256:8x128:256:8] +``` +![](./examples/steps/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png) +![](./examples/steps/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png) +![](./examples/steps/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png) +![](./examples/steps/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png) + ## Dependencies The main libraries this CLI uses are: @@ -90,4 +134,4 @@ The main libraries this CLI uses are: - rayon: For parallel processing. - clap: For command-line argument parsing. - simplelog: For logging. -- blake3: For hashing the image content. +- blake3: For hashing the image content. \ No newline at end of file diff --git a/examples/landscape/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png b/examples/landscape/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png new file mode 100644 index 0000000..32b1f02 Binary files /dev/null and b/examples/landscape/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png differ diff --git a/examples/landscape/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png b/examples/landscape/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png new file mode 100644 index 0000000..16d984a Binary files /dev/null and b/examples/landscape/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png differ diff --git a/examples/landscape/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png b/examples/landscape/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png new file mode 100644 index 0000000..be6a1c5 Binary files /dev/null and b/examples/landscape/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png differ diff --git a/examples/landscape/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png b/examples/landscape/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png new file mode 100644 index 0000000..b6ff14f Binary files /dev/null and b/examples/landscape/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png differ diff --git a/examples/mixed/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png b/examples/mixed/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png new file mode 100644 index 0000000..06fea8b Binary files /dev/null and b/examples/mixed/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png differ diff --git a/examples/mixed/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png b/examples/mixed/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png new file mode 100644 index 0000000..e5f7e97 Binary files /dev/null and b/examples/mixed/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png differ diff --git a/examples/mixed/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png b/examples/mixed/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png new file mode 100644 index 0000000..be6a1c5 Binary files /dev/null and b/examples/mixed/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png differ diff --git a/examples/mixed/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png b/examples/mixed/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png new file mode 100644 index 0000000..b6ff14f Binary files /dev/null and b/examples/mixed/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png differ diff --git a/examples/portrait/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png b/examples/portrait/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png new file mode 100644 index 0000000..ddb141e Binary files /dev/null and b/examples/portrait/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png differ diff --git a/examples/portrait/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png b/examples/portrait/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png new file mode 100644 index 0000000..647c7cb Binary files /dev/null and b/examples/portrait/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png differ diff --git a/examples/portrait/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png b/examples/portrait/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png new file mode 100644 index 0000000..4f9862b Binary files /dev/null and b/examples/portrait/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png differ diff --git a/examples/portrait/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png b/examples/portrait/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png new file mode 100644 index 0000000..58979ed Binary files /dev/null and b/examples/portrait/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png differ diff --git a/examples/run.sh b/examples/run.sh new file mode 100755 index 0000000..2278386 --- /dev/null +++ b/examples/run.sh @@ -0,0 +1,9 @@ +#! /usr/bin/env bash + +rm -f {squares,landscape,portrait,mixed,steps}/* + +find source -type f | ../target/release/snapcrop squares --res 256 +find source -type f | ../target/release/snapcrop landscape --res 256x128 +find source -type f | ../target/release/snapcrop portrait --res 128x256 +find source -type f | ../target/release/snapcrop mixed --res "256,[128x256]" +find source -type f | ../target/release/snapcrop steps --res "[128:256:8x128:256:8]" \ No newline at end of file diff --git a/examples/source/fruit-bowl-square.jpg b/examples/source/fruit-bowl-square.jpg new file mode 100644 index 0000000..457cdca Binary files /dev/null and b/examples/source/fruit-bowl-square.jpg differ diff --git a/examples/source/mieming-panorama-landscape.jpg b/examples/source/mieming-panorama-landscape.jpg new file mode 100644 index 0000000..b5b76a0 Binary files /dev/null and b/examples/source/mieming-panorama-landscape.jpg differ diff --git a/examples/source/stockholm-landscape.jpg b/examples/source/stockholm-landscape.jpg new file mode 100644 index 0000000..c7fdb53 Binary files /dev/null and b/examples/source/stockholm-landscape.jpg differ diff --git a/examples/source/stockholm-portrait.jpg b/examples/source/stockholm-portrait.jpg new file mode 100644 index 0000000..00369ca Binary files /dev/null and b/examples/source/stockholm-portrait.jpg differ diff --git a/examples/squares/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png b/examples/squares/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png new file mode 100644 index 0000000..06fea8b Binary files /dev/null and b/examples/squares/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png differ diff --git a/examples/squares/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png b/examples/squares/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png new file mode 100644 index 0000000..e5f7e97 Binary files /dev/null and b/examples/squares/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png differ diff --git a/examples/squares/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png b/examples/squares/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png new file mode 100644 index 0000000..ea60a56 Binary files /dev/null and b/examples/squares/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png differ diff --git a/examples/squares/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png b/examples/squares/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png new file mode 100644 index 0000000..9968a9e Binary files /dev/null and b/examples/squares/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png differ diff --git a/examples/steps/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png b/examples/steps/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png new file mode 100644 index 0000000..06fea8b Binary files /dev/null and b/examples/steps/4de26fac0cc3162259bf785a64e836fb88e5550082ff2233d8f58de5263facf6.png differ diff --git a/examples/steps/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png b/examples/steps/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png new file mode 100644 index 0000000..babfbb4 Binary files /dev/null and b/examples/steps/50a5a51eb1d57307579b86508196fbb44fb770e7cd170257f573b3260b0b8feb.png differ diff --git a/examples/steps/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png b/examples/steps/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png new file mode 100644 index 0000000..8c7bf20 Binary files /dev/null and b/examples/steps/653d96fb41779dda5ff6cc7a10745d33f4775e1267cd232403854b3656028678.png differ diff --git a/examples/steps/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png b/examples/steps/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png new file mode 100644 index 0000000..b6ff14f Binary files /dev/null and b/examples/steps/6b6fe23717af8d18ca11788013f0e789d90e40f6f4debff0cd2fcfb725d2a7d4.png differ diff --git a/src/main.rs b/src/main.rs index f4e216c..7ac6d07 100644 --- a/src/main.rs +++ b/src/main.rs @@ -169,6 +169,8 @@ fn resize_and_crop(src_view: fr::DynamicImageView, res: Vec<(u32, u32)>) -> Resu }) .ok_or_else(|| anyhow!("Could not find a valid resolution target"))?; + println!("{}x{} -> {}x{}", img_w, img_h, valid_w, valid_h); + if img_w < valid_w || img_h < valid_h { return Err(anyhow!( "Image too small, skipping: {}x{} < {}x{}", @@ -179,11 +181,12 @@ fn resize_and_crop(src_view: fr::DynamicImageView, res: Vec<(u32, u32)>) -> Resu )); } - // Determine the resize dimensions let (resize_w, resize_h) = if img_ratio > valid_w as f64 / valid_h as f64 { - (valid_w, (valid_w as f64 / img_ratio).round() as u32) + // If the image is more "landscape" than the target, match its height to the target height + ((img_w as f64 * valid_h as f64 / img_h as f64).round() as u32, valid_h) } else { - ((valid_h as f64 * img_ratio).round() as u32, valid_h) + // If the image is more "portrait" or equal to the target, match its width to the target width + (valid_w, (valid_w as f64 * img_h as f64 / img_w as f64).round() as u32) }; // Resize the image while maintaining its original aspect ratio @@ -283,6 +286,7 @@ fn main() -> Result<()> { res.sort(); res.dedup(); + res.reverse(); // Ensure res is not empty and no dimension is 0 if res.is_empty() || res.iter().any(|&(w, h)| w == 0 || h == 0) {