150 lines
5.3 KiB
Rust
150 lines
5.3 KiB
Rust
#![warn(unused_crate_dependencies)]
|
|
|
|
use clap::Parser;
|
|
use magick_rust::MagickWand;
|
|
use std::{fs, path::{Path, PathBuf}};
|
|
use rand::seq::IteratorRandom;
|
|
use xdg::BaseDirectories;
|
|
|
|
#[derive(Parser)]
|
|
#[command(version, about, long_about = None)]
|
|
struct Cli {
|
|
/// Which folder to use to locate the images
|
|
#[arg(short, long, value_name = "DIRECTORY")]
|
|
directory: PathBuf,
|
|
|
|
/// Size of the image to be output
|
|
#[arg(short, long, value_name = "WIDTH")]
|
|
size: usize,
|
|
|
|
/// Search directory recursively
|
|
#[arg(short = 'r', long = "recursive", action = clap::ArgAction::SetTrue)]
|
|
recursive: Option<bool>,
|
|
}
|
|
|
|
pub struct ImgOps {
|
|
width: usize,
|
|
height: usize,
|
|
x_offset: isize,
|
|
y_offset: isize
|
|
}
|
|
|
|
pub fn get_random_image(directory: &Path,recursive: Option<bool>) -> Result<PathBuf,String> {
|
|
match directory.canonicalize() {
|
|
Ok(d) => match d.is_dir() {
|
|
true => {
|
|
let mut rng = rand::rng();
|
|
let walker =
|
|
globwalk::GlobWalkerBuilder::from_patterns(&d, &["*.{png,jpg,gif,webp,heic}"])
|
|
.case_insensitive(true);
|
|
let imgs = match recursive.is_some_and(|x|x) {
|
|
true => {
|
|
walker.build().unwrap()
|
|
},
|
|
false => {
|
|
walker.max_depth(1).build().unwrap()
|
|
},
|
|
};
|
|
match imgs.choose(&mut rng).unwrap() {
|
|
Ok(o) => Ok(PathBuf::from(o.path())),
|
|
Err(e) => Err(e.to_string()),
|
|
}
|
|
},
|
|
false => Err(format!("{} is not a directory",d.to_str().unwrap_or_default())),
|
|
},
|
|
Err(e) => Err(e.to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn output_path(image_path: PathBuf) -> Result<PathBuf,String> {
|
|
let xdg_dirs = BaseDirectories::with_prefix("random-image-scaler");
|
|
//;
|
|
match xdg_dirs.get_cache_home() {
|
|
Some(cache) => match xdg_dirs.create_cache_directory(cache) {
|
|
Ok(mut cache) => {
|
|
cache.push(image_path.strip_prefix("/").unwrap());
|
|
cache.add_extension("jpg");
|
|
Ok(cache)
|
|
},
|
|
Err(e) => Err(e.to_string()),
|
|
}
|
|
None => Err("Could not resolve cache home?".to_string()),
|
|
}
|
|
}
|
|
|
|
pub fn calc_img_ops(orig_height: usize, orig_width: usize, size: usize) -> ImgOps {
|
|
let r = orig_width as f32 / orig_height as f32;
|
|
//println!("r: {:#?}",r);
|
|
let w = match r.gt(&1.0) {
|
|
true => (r.abs() * size as f32) as usize,
|
|
false => size,
|
|
};
|
|
//println!("w: {:#?}",w);
|
|
let h = match r.lt(&1.0) {
|
|
true => (size as f32 / r) as usize,
|
|
false => size,
|
|
};
|
|
//println!("h: {:#?}",h);
|
|
let x = match r.gt(&1.0) {
|
|
true => (w - size) / 2,
|
|
false => 0_usize,
|
|
} as isize;
|
|
//println!("x: {:#?}",x);
|
|
let y = match r.lt(&1.0) {
|
|
true => (h - size) / 2,
|
|
false => 0_usize,
|
|
} as isize;
|
|
//println!("y: {:#?}",y);
|
|
ImgOps{ width: w, height: h, x_offset: x, y_offset: y }
|
|
}
|
|
|
|
pub fn scale_image(image_path: PathBuf, cached_image_path: PathBuf, size: usize) -> Result<PathBuf,String> {
|
|
let magick_image = MagickWand::new();
|
|
match image_path.to_str() {
|
|
Some(img_str) => {
|
|
match magick_image.read_image(img_str) {
|
|
Ok(_) => {
|
|
let ops = calc_img_ops(magick_image.get_image_height(), magick_image.get_image_width(), size);
|
|
match magick_image.resize_image(ops.width, ops.height, magick_rust::FilterType::Undefined) {
|
|
Ok(_) => match magick_image.crop_image(size, size, ops.x_offset, ops.y_offset) {
|
|
Ok(_) => {
|
|
let mut dir = fs::DirBuilder::new();
|
|
let _ = dir.recursive(true).create(cached_image_path.parent().unwrap());
|
|
match cached_image_path.to_str() {
|
|
Some(cache_str) => match magick_image.write_image(cache_str) {
|
|
Ok(_) => Ok(cached_image_path),
|
|
Err(e) => Err(e.to_string()),
|
|
},
|
|
None => Err("Undefined filepath error".to_string()),
|
|
}
|
|
},
|
|
Err(_) => todo!(),
|
|
}
|
|
Err(e) => Err(e.to_string()),
|
|
}
|
|
},
|
|
Err(e) => Err(e.to_string()),
|
|
}
|
|
},
|
|
None => Err("Undefined filepath error".to_string()),
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let cli = Cli::parse();
|
|
match get_random_image(&cli.directory, cli.recursive) {
|
|
Ok(image_path) => {
|
|
match output_path(image_path.clone()) {
|
|
Ok(cached_image_path) => match cached_image_path.exists() {
|
|
true => println!("{}",cached_image_path.to_str().unwrap_or_default()),
|
|
false => match scale_image(image_path, cached_image_path, cli.size) {
|
|
Ok(final_path) => println!("{}",final_path.to_str().unwrap_or_default()),
|
|
Err(e) => eprintln!("{}",e),
|
|
},
|
|
},
|
|
Err(e) => eprintln!("{}",e),
|
|
}
|
|
},
|
|
Err(e) => eprintln!("{}",e),
|
|
}
|
|
}
|