diff --git a/Cargo.lock b/Cargo.lock index 079ab49..e029ef3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -198,6 +198,12 @@ dependencies = [ "spin", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "gif" version = "0.13.1" @@ -276,6 +282,7 @@ dependencies = [ "image", "image-compare", "img-parts", + "tempdir", "thiserror", "turbojpeg", ] @@ -385,6 +392,34 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rayon" version = "1.10.0" @@ -405,6 +440,24 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -443,6 +496,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand", + "remove_dir_all", +] + [[package]] name = "thiserror" version = "1.0.59" @@ -510,6 +573,28 @@ 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-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "zune-inflate" version = "0.2.54" diff --git a/Cargo.toml b/Cargo.toml index fce83f6..9d05105 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,4 @@ turbojpeg = {version = "1.0", features = ["image"]} [dev-dependencies] image-compare = "0.3.1" +tempdir = "0.3.7" diff --git a/src/bulk.rs b/src/bulk.rs index 007c59b..ac5f25d 100644 --- a/src/bulk.rs +++ b/src/bulk.rs @@ -103,11 +103,14 @@ impl StuffThatNeedsToBeSent { let Some(mut counter_guard) = local_counter.lock().ok() else { continue; }; + // if the counter matches the index... if !(*counter_guard == content.0) { continue; } else { + // ...increment this counter... *counter_guard = *counter_guard + 1; } + // ...and send it down the channel. match local_transmitter.send(compress_result) { Err(e) => { eprintln!("{e:#?}"); @@ -185,6 +188,7 @@ impl IntoIterator for Parallel { } } +/// Target type when converting [`Parallel`] into an iterator. pub struct ParallelIntoIterator { recv: channel::Receiver, error::Error>>, } @@ -197,6 +201,7 @@ impl ParallelIntoIterator { } } impl Iterator for ParallelIntoIterator { + /// A fallible containing compressed JPEG bytes. type Item = Result, error::Error>; fn next(&mut self) -> Option { if let Ok(result) = self.recv.recv() { diff --git a/src/lib.rs b/src/lib.rs index 99f5244..3653432 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,26 +33,58 @@ //!``` //! //! ## Multi-threaded bulk compressions with [`Parallel`] +//! Since [`Parallel`] returns items in the same order they were passed into, you can do something like the example below where you save the filenames of your JPEG into a vector, and later zip it with the [`Parallel`] iterator you've made. //!``` //! use jippigy::Parallel; +//! use std::path::PathBuf; +//! use tempdir::TempDir; +//! # const TEST_DIR: &str = "./tests/images/"; //! fn main() -> Result<(), Box> { -//! # use image::{RgbImage, ImageFormat::Jpeg}; -//! # use std::io::Cursor; -//! let mut vector_of_bytes: Vec> = Vec::new(); -//! # for _ in 0..10 { -//! # let mut bytes = Vec::new(); -//! # let img = RgbImage::new(1000, 1000); -//! # let _write = img.write_to(&mut Cursor::new(&mut bytes), Jpeg).unwrap(); -//! # vector_of_bytes.push(bytes); -//! # } -//! for result in Parallel::from_vec(vector_of_bytes) -//! .with_quality(80) -//! .with_device(4) // how many threads to use. +//! let image_dir_path = PathBuf::from(format!("{}", TEST_DIR)); +//! +//! let mut vec_of_bytes = Vec::new(); +//! let mut list_of_names = Vec::new(); +//! +//! // push the filenames and read bytes into a separate vector. +//! for file in std::fs::read_dir(image_dir_path.clone())? { +//! let filepath = file?.path(); +//! if filepath.is_file() { +//! let filename = filepath.clone() +//! .file_name() +//! .and_then(|osstr| osstr.to_str()) +//! .and_then(|a| Some(a.to_string())) +//! .unwrap_or_default(); +//! list_of_names.push(filename); +//! let read_file = std::fs::read(filepath); +//! vec_of_bytes.push(read_file?); +//! } +//! } + +//! // this temporary directory is here for doctest purposes, +//! // but you will create your own directory. +//! let tempdir = TempDir::new("compressed")?; +//! +//! // zip list_of_names vector with this iterator. +//! for zipped in Parallel::from_vec(vec_of_bytes) +//! .with_quality(50) +//! .with_device(4) //! .build() -//! .into_iter() { -//! let compressed_bytes: Vec = result?; -//! // do something with the compressed results. +//! .into_iter() +//! .zip(list_of_names) +//! { +//! // saves compresssed JPEG with the original name. +//! let (compressed_bytes, name) = zipped; +//! if let Ok(bytes) = compressed_bytes { +//! std::fs::write( +//! image_dir_path +//! .join(tempdir.path()) +//! .join(format!("{name}").as_str()), +//! bytes, +//! )?; +//! println!("saved: {name}"); +//! } //! } +//! tempdir.close()?; //! Ok(()) //! } //!```