diff --git a/Cargo.lock b/Cargo.lock index 9d28a70..ed13c23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -815,6 +815,15 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -886,6 +895,7 @@ version = "0.1.1" dependencies = [ "clap", "image", + "walkdir", ] [[package]] @@ -1018,6 +1028,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1084,6 +1104,37 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +[[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-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 86fc015..d8fa76d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,4 @@ categories = ["command-line-utilities"] [dependencies] clap = { version = "4.5.4", features = ["derive"] } image = "0.25.1" +walkdir = "2.5.0" diff --git a/src/main.rs b/src/main.rs index b4403ea..51d4f90 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,13 +2,15 @@ use clap::Parser; use image::*; use std::path::PathBuf; use std::{fs, process, vec}; +use walkdir::WalkDir; /// Command-line arguments for splix. #[derive(Parser)] struct Cli { - /// Path of the image to convert. - #[arg(short, long)] - image: PathBuf, + /// Path of the image(s) to convert. + /// Specify the path of an image, or a directory of images. + #[arg(short, long, visible_alias = "image", verbatim_doc_comment)] + images: PathBuf, /// The number of rows to split the image into. /// Specify an integer, or a list of integers: @@ -43,15 +45,27 @@ struct Cli { /// /// * `Ok(())` if the arguments are valid, otherwise returns an error message. fn validate_args(cli: &Cli) -> Result<(), String> { - let image_path = cli.image.clone(); + let img_dir = cli.images.clone(); let rows = &cli.rows; let cols = &cli.cols; - // Validate image - if let Err(_) = image::open(&image_path) { + let mut is_valid_image_found = false; + for entry in WalkDir::new(&img_dir) { + match entry { + Ok(entry) => { + if image::open(entry.path()).is_ok() { + is_valid_image_found = true; + break; + } + } + Err(_) => continue, + } + } + + if !is_valid_image_found { return Err(format!( - "splix: image: The provided file '{}' is not a valid image", - image_path.display() + "splix: image: The provided file or directory '{}' is not or does not contain a valid image", + img_dir.display() )); } @@ -89,8 +103,7 @@ fn validate_args(cli: &Cli) -> Result<(), String> { /// # Returns /// /// A vector of split images. -fn split_image(img_path: &PathBuf, rows: &Vec, cols: &Vec) -> Vec { - let mut img = image::open(img_path).unwrap(); +fn split_image(mut img: DynamicImage, rows: &Vec, cols: &Vec) -> Vec { let mut split_images = Vec::new(); let (width, height) = img.dimensions(); @@ -217,19 +230,6 @@ fn save_images( } } -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_split_image_correct_number_of_images() { - let path = &PathBuf::from("./assets/16x16.png"); - assert!(split_image(path, &vec![3], &vec![5]).len() == 15); - assert!(split_image(path, &vec![1], &vec![1]).len() == 1); - assert!(split_image(path, &vec![16], &vec![16]).len() == 256); - } -} - fn main() { let cli = Cli::parse(); @@ -238,32 +238,39 @@ fn main() { return; } - let img_path = cli.image; + let img_dir = cli.images; let rows = cli.rows.unwrap_or(vec![1]); let cols = cli.cols.unwrap_or(vec![1]); let output_directory = cli.output_dir.unwrap_or(PathBuf::from("splixed-images")); - let img_file_name = img_path.file_stem().unwrap().to_string_lossy(); - let img_format = io::Reader::open(&img_path).unwrap().format().unwrap(); - let img_format_str = img_format.extensions_str()[0]; - - let split_images = split_image(&img_path, &rows, &cols); - - save_images( - &split_images, - &output_directory, - &img_file_name, - &img_format, - img_format_str, - if rows.len() > 1 { - rows.len() - } else { - rows[0] as usize - }, - if cols.len() > 1 { - cols.len() - } else { - cols[0] as usize - }, - ); + for entry in WalkDir::new(&img_dir) { + match entry { + Ok(entry) => { + if let Ok(img) = image::open(entry.path()) { + let split_images = split_image(img, &rows, &cols); + let img_file_name = &entry.path().file_stem().unwrap().to_string_lossy(); + let img_format = &ImageFormat::from_path(entry.path()).unwrap(); + let img_format_str = img_format.extensions_str()[0]; + save_images( + &split_images, + &output_directory, + img_file_name, + img_format, + img_format_str, + if rows.len() > 1 { + rows.len() + } else { + rows[0] as usize + }, + if cols.len() > 1 { + cols.len() + } else { + cols[0] as usize + }, + ) + } + } + Err(_) => continue, + } + } }