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:
2026-03-06 01:54:57 +02:00
parent c445f71163
commit 545bf27fe4
3 changed files with 123 additions and 0 deletions

View File

@@ -1,3 +1,5 @@
pub mod resize;
use serde::{Deserialize, Serialize};
use crate::types::{Dimensions, ImageFormat, QualityPreset};

View 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))
}