Skip to content

Commit

Permalink
Rayon parallel Image Processing (#97)
Browse files Browse the repository at this point in the history
* rayon implementation for processing speedup

* remove unneeded imports

* only import what we need from rayon

* use immutable crop method to skip cloning

* skip another clone by not borrowing in immutable call
  • Loading branch information
0xk1f0 authored Feb 7, 2024
1 parent 73054ad commit 90a5045
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 46 deletions.
21 changes: 5 additions & 16 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ image = "0.24.8"
toml = "0.8.9"
serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.113"
rayon = "1.8.1"

# makes image lib faster for dev
[profile.dev-unopt]
Expand All @@ -20,4 +21,4 @@ opt-level = 3
# Ref: https://github.com/johnthagen/min-sized-rust
[profile.release]
strip = true
lto = true
lto = true
68 changes: 39 additions & 29 deletions src/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::wpaperd::Wpaperd;
use crate::Config;
use glob::glob;
use image::{imageops::FilterType, DynamicImage, GenericImageView};
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
use std::cmp;
use std::collections::hash_map;
use std::env;
Expand Down Expand Up @@ -192,39 +193,48 @@ impl Worker {
Crop image for screens
and push them to the result vector, taking into
account negative offsets
Doing it in parallel using rayon for speedup
*/
let mut result = Vec::with_capacity(self.monitors.len());
for monitor in &self.monitors {
// convert for cropping
let adjusted_x = u32::try_from(origin_x as i32 + monitor.x)
.map_err(|_| "x adjustment out of range")?;
let adjusted_y = u32::try_from(origin_y as i32 + monitor.y)
.map_err(|_| "y adjustment out of range")?;
// crop the image
let cropped_image = img.crop(
adjusted_x + resize_offset_x,
adjusted_y + resize_offset_y,
monitor.width,
monitor.height,
);

// get full image path
let path_image = format!("{}/rwps_{}_{}.png", save_path, &self.hash, &monitor.name,);

// save it
cropped_image
.save(&path_image)
.map_err(|err| err.to_string())?;
let result: Vec<Result<ResultPaper, String>> = self
.monitors
.par_iter()
.map(|monitor| -> Result<ResultPaper, String> {
let adjusted_x = u32::try_from(origin_x as i32 + monitor.x)
.map_err(|_| "x adjustment out of range")?;
let adjusted_y = u32::try_from(origin_y as i32 + monitor.y)
.map_err(|_| "y adjustment out of range")?;

// crop to size
let cropped_image = img.crop_imm(
adjusted_x + resize_offset_x,
adjusted_y + resize_offset_y,
monitor.width,
monitor.height,
);

// export to file
let path_image = format!("{}/rwps_{}_{}.png", save_path, &self.hash, &monitor.name);
cropped_image
.save(&path_image)
.map_err(|err| err.to_string())?;

// push to result vector
result.push(ResultPaper {
monitor_name: format!("{}", &monitor.name),
full_path: path_image,
image: cropped_image,
Ok(ResultPaper {
monitor_name: format!("{}", &monitor.name),
full_path: path_image,
image: cropped_image,
})
})
.collect();

if &result.iter().all(Result::is_ok) == &true {
let converted: Vec<ResultPaper> = result
.into_iter()
.filter_map(|result| result.ok())
.collect();
Ok(converted)
} else {
Err("Cropping Error".to_string())
}

Ok(result)
}

fn cleanup_cache(&self) {
Expand Down

0 comments on commit 90a5045

Please sign in to comment.