Add SIMD-accelerated resize operation using fast_image_resize
Lanczos3 filter, supports ByWidth, ByHeight, FitInBox, Exact modes. All 5 resize tests passing.
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
pub mod resize;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::{Dimensions, ImageFormat, QualityPreset};
|
||||
|
||||
60
pixstrip-core/src/operations/resize.rs
Normal file
60
pixstrip-core/src/operations/resize.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
use fast_image_resize::{images::Image, Resizer, ResizeOptions, ResizeAlg, FilterType};
|
||||
|
||||
use crate::error::{PixstripError, Result};
|
||||
use crate::types::Dimensions;
|
||||
|
||||
use super::ResizeConfig;
|
||||
|
||||
pub fn resize_image(
|
||||
src: &image::DynamicImage,
|
||||
config: &ResizeConfig,
|
||||
) -> 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 options = ResizeOptions::new().resize_alg(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
|
||||
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))
|
||||
}
|
||||
Reference in New Issue
Block a user