use std::io::{self, Write, Read};
use std::ffi::{OsStr, OsString};
use std::path::{Path, PathBuf};
use clap::Parser;
#[derive(Parser, Debug)]
#[command(name = "alphafix")]
pub struct Cli {
#[arg(required = true, num_args = 1..)]
pub paths: Vec<String>,
#[arg(long = "append")]
pub append: Option<String>,
#[arg(long = "dir")]
pub dir: Option<String>,
#[arg(long = "auto")]
pub auto: bool,
#[arg(long = "verbose")]
pub verbose: bool,
#[arg(long)]
pub opaque: bool,
}
impl Cli {
pub fn run(&self) -> bool {
for path in self.paths.iter() {
let open_path = self.get_open_path(path);
let mut img_dynamic = match alphafix::open_image_file(&open_path) {
Ok(img) => img,
Err(err) => {
eprintln!("Could not open image, path: {}, error: {}", open_path.display(), err.to_string());
return false;
},
};
if self.verbose {println!("Opened image, path: {}", open_path.display());}
let img_rgba8 = match img_dynamic.as_mut_rgba8() {
Some(img) => img,
None => {
eprintln!("Could not process image, path: {}", open_path.display());
return false;
},
};
if self.opaque {
if self.verbose {println!("Making image opaque")};
alphafix::set_alpha(img_rgba8, 255);
}
else {
if self.verbose {println!("Fixing image");}
match alphafix::fix_alpha(img_rgba8) {
Err(err) => {
eprintln!("Error fixing image: {}", err.to_string());
return false;
}
_ => (),
}
}
let save_path = self.get_save_path(&open_path);
match img_dynamic.save(&save_path) {
Ok(_) if self.verbose => println!("Saved image, path: {}", save_path.display()),
Err(err) => {
eprintln!("Error saving image: {}, error: {}", save_path.display(), err.to_string());
return false;
}
_ => (),
};
}
println!("Finished.");
if !self.auto {
Self::term_pause();
}
return true;
}
fn get_open_path(&self, path_str: &str) -> PathBuf {
PathBuf::from(path_str)
}
fn get_save_path(&self, path: &PathBuf) -> PathBuf {
let file_parent: &Path = path.parent().unwrap();
let mut file_stem: OsString = path.file_stem().unwrap().to_os_string();
let file_ext: &OsStr = path.extension().unwrap();
let mut new_path = PathBuf::new();
new_path.push(if let Some(dir_str) = &self.dir {
dir_str.as_ref()
}
else {
file_parent
});
file_stem.push(if let Some(app_str) = &self.append {
app_str
}
else if self.opaque {
"_opaque"
}
else {
"_fixed"
});
new_path.push(file_stem);
new_path.set_extension(file_ext);
new_path
}
fn term_pause() {
print!("Press enter to continue...");
io::stdout().flush().unwrap();
io::stdin().read(&mut [0u8, 0]).unwrap();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn cli_many_0() {
let input = ["exe", "test/pngs/gummy_worm_idk.png", "test/pngs/navball_velocity_prograde.png", "--dir=test/dest"];
let args: Cli = Cli::parse_from(input);
args.run();
}
#[test]
fn cli_many_1() {
let input = ["exe", "test/pngs/gummy_worm_idk.png", "test/pngs/navball_velocity_prograde.png", "--dir=test/dest", "--opaque"];
let args: Cli = Cli::parse_from(input);
args.run();
}
#[test]
fn cli_many_2() {
let input = ["exe", "test/pngs/gummy_worm_idk.png", "test/pngs/navball_velocity_prograde.png", "--dir=test/dest", "--append=_fixed"];
let args: Cli = Cli::parse_from(input);
args.run();
}
#[test]
fn cli_opaque_0() {
let input = ["exe", "test/pngs/gummy_worm_idk.png", "--opaque"];
let args: Cli = Cli::parse_from(input);
args.run();
}
#[test]
fn cli_opaque_1() {
let input = ["exe", "test/pngs/gummy_worm_idk.png", "--opaque", "--dir=test/dest"];
let args: Cli = Cli::parse_from(input);
args.run();
}
#[test]
fn cli_get_save_path_0() {
let cli: Cli = Cli {
paths: Vec::new(),
append: Some("_fix".to_string()),
dir: Some("D:/idk/".to_string()),
opaque: false,
verbose: false,
auto: false,
};
let in_path = PathBuf::from("homework/hentai/blurry.png");
let out_path = cli.get_save_path(&in_path);
let expect_path = PathBuf::from("D:/idk/blurry_fix.png");
assert_eq!(out_path, expect_path);
}
#[test]
fn cli_get_save_path_1() {
let cli: Cli = Cli {
paths: Vec::new(),
append: Some("_fix".to_string()),
dir: Some("D:/idk/".to_string()),
opaque: true,
verbose: false,
auto: false,
};
let in_path = PathBuf::from("homework/hentai/blurry.png");
let out_path = cli.get_save_path(&in_path);
let expect_path = PathBuf::from("D:/idk/blurry_fix_opaque.png");
assert_eq!(out_path, expect_path);
}
}