//! holds scaling operations, at current only the Nearest Neighbor
use crate::Image;
/// [Nearest Neighbor](https://en.wikipedia.org/wiki/Nearest-neighbor_interpolation) image scaling algorithm implementation.
/// Use [`Nearest::scale`].
pub struct Nearest;
impl Nearest {
/// Resize a image.
/// # Safety
///
/// `image` must be as big or bigger than `width`, `height.
#[must_use = "function does not modify the original image"]
pub unsafe fn scale<const N: usize>(
image: Image<&[u8], N>,
width: u32,
height: u32,
) -> Image<Vec<u8>, N> {
let x_scale = image.width() as f32 / width as f32;
let y_scale = image.height() as f32 / height as f32;
let mut out = Image::alloc(width, height);
for y in 0..height {
for x in 0..width {
let x1 = ((x as f32 + 0.5) * x_scale).floor() as u32;
let y1 = ((y as f32 + 0.5) * y_scale).floor() as u32;
// SAFETY: i asked the caller to make sure its ok
let px = unsafe { image.pixel(x1, y1) };
// SAFETY: were looping over the width and height of out. its ok.
unsafe { out.set_pixel(x, y, px) };
}
}
out
}
}
#[test]
fn test_nearest() {
let i = Image::<_, 3>::open("tdata/cat.png");
assert_eq!(
unsafe { Nearest::scale(i.as_ref(), 268, 178) }.buffer,
Image::<_, 3>::open("tdata/small_cat.png").buffer
);
}