use crate::RatioMode;
use image::{imageops, RgbImage};
pub fn resize_image(img: RgbImage, ratio_mode: RatioMode, width: u32, height: u32) -> RgbImage {
match ratio_mode {
RatioMode::Maintain => {
let mut new_img = RgbImage::new(width, height);
let (img_width, img_height) = img.dimensions();
let width_ratio = width as f32 / img_width as f32;
let height_ratio = height as f32 / img_height as f32;
let scale_factor = width_ratio.min(height_ratio);
let new_width = (img_width as f32 * scale_factor) as u32;
let new_height = (img_height as f32 * scale_factor) as u32;
let resized = image::imageops::resize(
&img,
new_width,
new_height,
imageops::FilterType::Lanczos3,
);
let x_offset = (width - new_width) / 2;
let y_offset = (height - new_height) / 2;
imageops::overlay(&mut new_img, &resized, x_offset as i64, y_offset as i64);
new_img
}
RatioMode::Stretch => imageops::resize(&img, width, height, imageops::FilterType::Lanczos3),
RatioMode::Crop => {
let (img_width, img_height) = img.dimensions();
let aspect_ratio = img_width as f32 / img_height as f32;
let display_aspect_ratio = width as f32 / height as f32;
let (crop_width, crop_height) = if aspect_ratio > display_aspect_ratio {
(img_height as f32 * display_aspect_ratio, img_height as f32)
} else {
(img_width as f32, img_width as f32 / display_aspect_ratio)
};
let x_offset = ((img_width as f32 - crop_width) / 2.0) as u32;
let y_offset = ((img_height as f32 - crop_height) / 2.0) as u32;
let cropped_img = imageops::crop_imm(
&img,
x_offset,
y_offset,
crop_width as u32,
crop_height as u32,
)
.to_image();
imageops::resize(&cropped_img, width, height, imageops::FilterType::Lanczos3)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::create_test_image;
use image::Rgb;
#[test]
fn test_resize_image_maintain() {
let img = create_test_image(100, 50);
let resized_img = resize_image(img, RatioMode::Maintain, 800, 480);
assert_eq!(resized_img.dimensions(), (800, 480));
assert_eq!(resized_img.get_pixel(0, 0), &Rgb([0, 0, 0]));
assert_eq!(resized_img.get_pixel(799, 479), &Rgb([0, 0, 0]));
}
#[test]
fn test_resize_image_stretch() {
let img = create_test_image(100, 50);
let resized_img = resize_image(img, RatioMode::Stretch, 800, 480);
assert_eq!(resized_img.dimensions(), (800, 480));
assert_eq!(resized_img.get_pixel(0, 0), &Rgb([0, 0, 0]));
assert_eq!(resized_img.get_pixel(799, 479), &Rgb([255, 255, 255]));
}
#[test]
fn test_resize_image_crop() {
let img = create_test_image(100, 50);
let resized_img = resize_image(img, RatioMode::Crop, 800, 800);
assert_eq!(resized_img.dimensions(), (800, 800));
assert_eq!(resized_img.get_pixel(0, 0), &Rgb([64, 0, 43]));
assert_eq!(resized_img.get_pixel(799, 799), &Rgb([190, 255, 211]));
}
}