- Add ResizeAlgorithm enum (Lanczos3/CatmullRom/Bilinear/Nearest) to core - Thread algorithm selection from UI ComboRow through ProcessingJob to resize_image - Add OverwriteBehavior enum (AutoRename/Overwrite/Skip) to core - Implement overwrite handling in executor with auto-rename suffix logic - Wire overwrite behavior from output step through to processing job - Fix rotation/flip to apply when resize step is enabled, not just adjustments
75 lines
2.3 KiB
Rust
75 lines
2.3 KiB
Rust
use fast_image_resize::{images::Image, Resizer, ResizeOptions, ResizeAlg, FilterType};
|
|
|
|
use crate::error::{PixstripError, Result};
|
|
use crate::types::Dimensions;
|
|
|
|
use super::{ResizeConfig, ResizeAlgorithm};
|
|
|
|
pub fn resize_image(
|
|
src: &image::DynamicImage,
|
|
config: &ResizeConfig,
|
|
) -> Result<image::DynamicImage> {
|
|
resize_image_with_algorithm(src, config, ResizeAlgorithm::default())
|
|
}
|
|
|
|
pub fn resize_image_with_algorithm(
|
|
src: &image::DynamicImage,
|
|
config: &ResizeConfig,
|
|
algorithm: ResizeAlgorithm,
|
|
) -> Result<image::DynamicImage> {
|
|
let original = Dimensions {
|
|
width: src.width(),
|
|
height: src.height(),
|
|
};
|
|
let target = config.target_for(original);
|
|
|
|
if target.width == original.width && target.height == original.height {
|
|
return Ok(src.clone());
|
|
}
|
|
|
|
let src_rgba = src.to_rgba8();
|
|
let (src_w, src_h) = (src_rgba.width(), src_rgba.height());
|
|
|
|
let src_image = Image::from_vec_u8(
|
|
src_w,
|
|
src_h,
|
|
src_rgba.into_raw(),
|
|
fast_image_resize::PixelType::U8x4,
|
|
)
|
|
.map_err(|e| PixstripError::Processing {
|
|
operation: "resize".into(),
|
|
reason: format!("Failed to create source image: {}", e),
|
|
})?;
|
|
|
|
let mut dst_image = Image::new(
|
|
target.width,
|
|
target.height,
|
|
fast_image_resize::PixelType::U8x4,
|
|
);
|
|
|
|
let mut resizer = Resizer::new();
|
|
let alg = match algorithm {
|
|
ResizeAlgorithm::Lanczos3 => ResizeAlg::Convolution(FilterType::Lanczos3),
|
|
ResizeAlgorithm::CatmullRom => ResizeAlg::Convolution(FilterType::CatmullRom),
|
|
ResizeAlgorithm::Bilinear => ResizeAlg::Convolution(FilterType::Bilinear),
|
|
ResizeAlgorithm::Nearest => ResizeAlg::Nearest,
|
|
};
|
|
let options = ResizeOptions::new().resize_alg(alg);
|
|
|
|
resizer
|
|
.resize(&src_image, &mut dst_image, &options)
|
|
.map_err(|e| PixstripError::Processing {
|
|
operation: "resize".into(),
|
|
reason: format!("Resize failed: {}", e),
|
|
})?;
|
|
|
|
let result_buf: image::RgbaImage =
|
|
image::ImageBuffer::from_raw(target.width, target.height, dst_image.into_vec())
|
|
.ok_or_else(|| PixstripError::Processing {
|
|
operation: "resize".into(),
|
|
reason: "Failed to create output image buffer".into(),
|
|
})?;
|
|
|
|
Ok(image::DynamicImage::ImageRgba8(result_buf))
|
|
}
|