add image transformations including crop, rotate, flip horizontal/vertical, filter, scale, and aspect ratio

This commit is contained in:
Waveplate 2024-12-15 07:33:48 -08:00
parent 34f2a1ef13
commit bb0ba0e990

View File

@ -1,213 +1,238 @@
use crate::args; use crate::args;
use photon_rs::{colour_spaces}; use photon_rs::{colour_spaces, channels, conv, effects, filters, monochrome, noise};
use photon_rs::{channels, conv, effects, filters, monochrome, noise}; use photon_rs::transform::{SamplingFilter, resize, crop, rotate, flipv, fliph};
use photon_rs::transform::{resize, SamplingFilter};
use photon_rs::PhotonImage; use photon_rs::PhotonImage;
fn calculate_dimensions(args: &args::Args, image: &PhotonImage) -> (u32, u32) {
let original_width = image.get_width() as f32;
let original_height = image.get_height() as f32;
let original_aspect = original_width / original_height;
let base_width;
let base_height;
let aspect_ratio = if let Some(aspect) = args.aspect {
aspect.0 / aspect.1
} else {
original_aspect
};
if args.width.is_none() && args.height.is_none() {
base_width = original_width;
base_height = original_height;
} else if args.width.is_none() {
let provided_height = args.height.unwrap();
base_height = provided_height as f32;
base_width = base_height * aspect_ratio;
} else if args.height.is_none() {
let provided_width = args.width.unwrap();
base_width = provided_width as f32;
base_height = base_width / aspect_ratio;
} else {
base_width = args.width.unwrap() as f32;
base_height = args.height.unwrap() as f32;
}
let (scaled_width, scaled_height) = if let Some(scale) = args.scale {
(base_width * scale.0, base_height * scale.1)
} else {
(base_width, base_height)
};
// Step 4: Round the scaled dimensions to the nearest integer and ensure a minimum size of 1.
let final_width = scaled_width.round().max(1.0) as u32;
let final_height = scaled_height.round().max(1.0) as u32;
(final_width, final_height)
}
pub fn apply_effects( pub fn apply_effects(
args: &args::Args, args: &args::Args,
mut photon_image: PhotonImage, mut photon_image: PhotonImage,
) -> PhotonImage { ) -> PhotonImage {
let (width, height) = calculate_dimensions(args, &photon_image);
// Resize to width if args.rotate != 0 {
let height = photon_image = rotate(&photon_image, args.rotate as i32);
(args.width as f32 / photon_image.get_width() as f32 * photon_image.get_height() as f32) as u32; }
let width = match args.qb { if args.fliph {
true => args.width * 2, fliph(&mut photon_image);
_ => args.width, }
if args.flipv {
flipv(&mut photon_image);
}
photon_image = resize(&photon_image, width, height, match args.filter {
args::SamplingFilter::Nearest => SamplingFilter::Nearest,
args::SamplingFilter::Triangle => SamplingFilter::Triangle,
args::SamplingFilter::CatmullRom => SamplingFilter::CatmullRom,
args::SamplingFilter::Gaussian => SamplingFilter::Gaussian,
args::SamplingFilter::Lanczos3 => SamplingFilter::Lanczos3,
});
type ColourFunc = fn(&mut PhotonImage, &str, f32);
let colour_func: ColourFunc = match args.colorspace {
args::ColourSpace::HSL => colour_spaces::hsl,
args::ColourSpace::HSV => colour_spaces::hsv,
args::ColourSpace::HSLUV => colour_spaces::hsluv,
args::ColourSpace::LCH => colour_spaces::lch,
}; };
photon_image = match args.qb { if args.dither > 0 {
true => resize(&photon_image, width, height, SamplingFilter::Lanczos3), effects::dither(&mut photon_image, args.dither);
_ => resize(&mut photon_image, width, height, SamplingFilter::Lanczos3), }
};
// Adjust brightness
match args.brightness { match args.brightness {
x if x > 0.0 => { x if x > 0.0 => {
colour_spaces::hsv(&mut photon_image, "brighten", args.brightness/255.0); colour_func(&mut photon_image, "lighten", args.brightness / 100.0);
} }
x if x < 0.0 => { x if x < 0.0 => {
colour_spaces::hsv(&mut photon_image, "darken", args.brightness.abs()/255.0); colour_func(&mut photon_image, "darken", args.brightness.abs() / 100.0);
}, },
_ => {} _ => {}
} }
// Adjust hue
if args.hue > 0.0 {
colour_spaces::hsv(&mut photon_image, "shift_hue", args.hue/360.0);
}
// Adjust contrast
if args.contrast != 0.0 {
effects::adjust_contrast(&mut photon_image, args.contrast);
}
// Adjust saturation
match args.saturation { match args.saturation {
x if x > 0.0 => { x if x > 0.0 => {
colour_spaces::hsv(&mut photon_image, "saturate", args.saturation/255.0); colour_func(&mut photon_image, "saturate", args.saturation/100.0);
} }
x if x < 0.0 => { x if x < 0.0 => {
colour_spaces::hsv(&mut photon_image, "desaturate", args.saturation.abs()/255.0); colour_func(&mut photon_image, "desaturate", args.saturation.abs()/100.0);
} }
_ => {} _ => {}
} }
// Adjust gamma if args.contrast != 0.0 {
effects::adjust_contrast(&mut photon_image, args.contrast);
}
if args.hue > 0.0 {
colour_func(&mut photon_image, "shift_hue", args.hue/360.0);
}
if args.gamma != 0.0 { if args.gamma != 0.0 {
let gamma_value = 1.0 - args.gamma/255.0; let gamma_value = 1.0 - args.gamma/255.0;
colour_spaces::gamma_correction(&mut photon_image, gamma_value, gamma_value, gamma_value); colour_spaces::gamma_correction(&mut photon_image, gamma_value, gamma_value, gamma_value);
} }
// Adjust dither if args.crop.is_some() {
if args.dither > 0 { let crop_args = args.crop.unwrap();
effects::dither(&mut photon_image, args.dither); photon_image = crop(&mut photon_image, crop_args.0, crop_args.1, crop_args.2, crop_args.3);
} }
// Adjust gaussian_blur
if args.gaussian_blur > 0 { if args.gaussian_blur > 0 {
conv::gaussian_blur(&mut photon_image, args.gaussian_blur); conv::gaussian_blur(&mut photon_image, args.gaussian_blur);
} }
// Adjust pixelize
if args.pixelize > 0 { if args.pixelize > 0 {
effects::pixelize(&mut photon_image, args.pixelize); effects::pixelize(&mut photon_image, args.pixelize);
} }
// Adjust halftone
if args.halftone { if args.halftone {
effects::halftone(&mut photon_image); effects::halftone(&mut photon_image);
} }
// Adjust invert
if args.invert { if args.invert {
channels::invert(&mut photon_image); channels::invert(&mut photon_image);
} }
// Adjust sepia
if args.sepia { if args.sepia {
monochrome::sepia(&mut photon_image); monochrome::sepia(&mut photon_image);
} }
// Adjust solarize
if args.solarize { if args.solarize {
effects::solarize(&mut photon_image); effects::solarize(&mut photon_image);
} }
// Adjust normalize
if args.normalize { if args.normalize {
effects::normalize(&mut photon_image); effects::normalize(&mut photon_image);
} }
// Adjust noise
if args.noise { if args.noise {
noise::add_noise_rand(&mut photon_image); noise::add_noise_rand(&mut photon_image);
} }
// Adjust sharpen
if args.sharpen { if args.sharpen {
conv::sharpen(&mut photon_image); conv::sharpen(&mut photon_image);
} }
// Adjust edge_detection
if args.edge_detection { if args.edge_detection {
conv::edge_detection(&mut photon_image); conv::edge_detection(&mut photon_image);
} }
// Adjust emboss
if args.emboss { if args.emboss {
conv::emboss(&mut photon_image); conv::emboss(&mut photon_image);
} }
// Adjust frosted_glass
if args.frosted_glass { if args.frosted_glass {
effects::frosted_glass(&mut photon_image); effects::frosted_glass(&mut photon_image);
} }
// Adjust box_blur
if args.box_blur { if args.box_blur {
conv::box_blur(&mut photon_image); conv::box_blur(&mut photon_image);
} }
// Adjust grayscale
if args.grayscale { if args.grayscale {
monochrome::grayscale(&mut photon_image); monochrome::grayscale(&mut photon_image);
} }
// Adjust identity
if args.identity { if args.identity {
conv::identity(&mut photon_image); conv::identity(&mut photon_image);
} }
// Adjust laplace
if args.laplace { if args.laplace {
conv::laplace(&mut photon_image); conv::laplace(&mut photon_image);
} }
// Adjust cali
if args.cali { if args.cali {
filters::cali(&mut photon_image); filters::cali(&mut photon_image);
} }
// Adjust dramatic
if args.dramatic { if args.dramatic {
filters::dramatic(&mut photon_image); filters::dramatic(&mut photon_image);
} }
// Adjust firenze
if args.firenze { if args.firenze {
filters::firenze(&mut photon_image); filters::firenze(&mut photon_image);
} }
// Adjust golden
if args.golden { if args.golden {
filters::golden(&mut photon_image); filters::golden(&mut photon_image);
} }
// Adjust lix
if args.lix { if args.lix {
filters::lix(&mut photon_image); filters::lix(&mut photon_image);
} }
// Adjust lofi
if args.lofi { if args.lofi {
filters::lofi(&mut photon_image); filters::lofi(&mut photon_image);
} }
// Adjust neue
if args.neue { if args.neue {
filters::neue(&mut photon_image); filters::neue(&mut photon_image);
} }
// Adjust obsidian
if args.obsidian { if args.obsidian {
filters::obsidian(&mut photon_image); filters::obsidian(&mut photon_image);
} }
// Adjust pastel_pink
if args.pastel_pink { if args.pastel_pink {
filters::pastel_pink(&mut photon_image); filters::pastel_pink(&mut photon_image);
} }
// Adjust ryo
if args.ryo { if args.ryo {
filters::ryo(&mut photon_image); filters::ryo(&mut photon_image);
} }
// Adjust oil
match &args.oil { match &args.oil {
Some(oil) => { Some(oil) => {
// split oil at comma
let vals: Vec<&str> = oil.split(",").collect(); let vals: Vec<&str> = oil.split(",").collect();
// check if args.oil has 2 values
if vals.len() == 2 { if vals.len() == 2 {
// convert oil values to i32 and f64
let radius: i32 = vals.get(0).unwrap().parse::<i32>().unwrap(); let radius: i32 = vals.get(0).unwrap().parse::<i32>().unwrap();
let intensity: f64 = vals.get(1).unwrap().parse::<f64>().unwrap(); let intensity: f64 = vals.get(1).unwrap().parse::<f64>().unwrap();
effects::oil(&mut photon_image, radius, intensity); effects::oil(&mut photon_image, radius, intensity);
} }
} }
@ -216,3 +241,64 @@ pub fn apply_effects(
photon_image photon_image
} }
pub fn apply_luma_effects(args: &args::Args, mut photon_image: PhotonImage) -> PhotonImage {
let (width, height) = calculate_dimensions(args, &photon_image);
if args.rotate != 0 {
photon_image = rotate(&photon_image, args.rotate);
}
if args.fliph {
fliph(&mut photon_image);
}
if args.flipv {
flipv(&mut photon_image);
}
photon_image = resize(&photon_image, width, height, match args.filter {
args::SamplingFilter::Nearest => SamplingFilter::Nearest,
args::SamplingFilter::Triangle => SamplingFilter::Triangle,
args::SamplingFilter::CatmullRom => SamplingFilter::CatmullRom,
args::SamplingFilter::Gaussian => SamplingFilter::Gaussian,
args::SamplingFilter::Lanczos3 => SamplingFilter::Lanczos3,
});
type ColourFunc = fn(&mut PhotonImage, &str, f32);
let colour_func: ColourFunc = match args.colorspace {
args::ColourSpace::HSL => colour_spaces::hsl,
args::ColourSpace::HSV => colour_spaces::hsv,
args::ColourSpace::HSLUV => colour_spaces::hsluv,
args::ColourSpace::LCH => colour_spaces::lch,
};
if args.luma_invert {
channels::invert(&mut photon_image);
}
if args.luma_contrast != 0.0 {
effects::adjust_contrast(&mut photon_image, args.luma_contrast);
}
if args.luma_gamma != 0.0 {
let gamma_value = 1.0 - args.luma_gamma/255.0;
colour_spaces::gamma_correction(&mut photon_image, gamma_value, gamma_value, gamma_value);
}
if args.luma_brightness > 0.0 {
colour_func(&mut photon_image, "lighten", args.luma_brightness/100.0);
} else if args.luma_brightness < 0.0 {
colour_func(&mut photon_image, "darken", args.luma_brightness.abs()/100.0);
}
if args.luma_saturation < 0.0 {
colour_func(&mut photon_image, "saturate", args.luma_saturation.abs()/100.0);
} else if args.luma_saturation > 0.0 {
colour_func(&mut photon_image, "desaturate", args.luma_saturation/100.0);
}
photon_image
}