use super::{traits::*, *}; use std::num::NonZeroU32; /// [Nearest Neighbor](https://en.wikipedia.org/wiki/Nearest-neighbor_interpolation) image scaling algorithm. pub struct Nearest; impl ScalingAlgorithm for Nearest { /// Can be used on non opaque too! (Nearest is special like that). fn scale_opaque( i: Image<&[u8], N>, w: NonZeroU32, h: NonZeroU32, ) -> Image, N> where ChannelCount: ToImageView, { let mut dst = fr::Image::new(w, h); // SAFETY: swear, the pixel types are the same unsafe { fr::Resizer::new(fr::ResizeAlg::Nearest) .resize(&ChannelCount::::wrap(i), &mut dst.view_mut()) }; // SAFETY: ctor unsafe { Image::new(dst.width(), dst.height(), dst.into_vec().into()) } } #[inline] fn scale_transparent( i: Image<&mut [u8], N>, w: NonZeroU32, h: NonZeroU32, ) -> Image, N> where ChannelCount: AlphaDiv, { Self::scale_opaque(i.as_ref(), w, h) } } macro_rules! alg { ($for:ident) => { impl ScalingAlgorithm for $for { fn scale_opaque( i: Image<&[u8], N>, w: NonZeroU32, h: NonZeroU32, ) -> Image, N> where ChannelCount: ToImageView, { let mut dst = fr::Image::new(w, h); // SAFETY: swear, the pixel types are the same unsafe { fr::Resizer::new(fr::ResizeAlg::Convolution(fr::FilterType::$for)) .resize(&ChannelCount::::wrap(i), &mut dst.view_mut()) }; // SAFETY: ctor unsafe { Image::new(dst.width(), dst.height(), dst.into_vec().into()) } } fn scale_transparent( i: Image<&mut [u8], N>, w: NonZeroU32, h: NonZeroU32, ) -> Image, N> where ChannelCount: AlphaDiv, { let mut dst = fr::Image::new(w, h); // SAFETY: yes unsafe { fr::Resizer::new(fr::ResizeAlg::Convolution(fr::FilterType::$for)) .resize(&ChannelCount::::handle(i).view(), &mut dst.view_mut()) } ChannelCount::::unhandle(&mut dst); // SAFETY: ctor unsafe { Image::new(dst.width(), dst.height(), dst.into_vec().into()) } } } }; } /// [Lanczos](https://en.wikipedia.org/wiki/Lanczos_resampling) scaling with a filter size (*a*) of 3. pub struct Lanczos3 {} alg!(Lanczos3); /// [Catmull-Rom](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline) bicubic filtering. pub struct CatmullRom {} alg!(CatmullRom); /// Linear interpolation. pub struct Bilinear {} alg!(Bilinear); /// The opposite of [`Nearest`]. pub struct Box {} alg!(Box); /// Hamming filtering has the same performance as a [`Bilinear`] filter, while /// providing image (downscaling) quality comparable to bicubic filters like /// [`CatmullRom`] or [`Mitchell`]. Creates a sharper image than [`Bilinear`] filtering, /// and doesn't have dislocations on local level like [`Box`] suffers from. /// Not recommended for upscaling. pub struct Hamming {} alg!(Hamming); /// [Mitchell–Netravali](https://en.wikipedia.org/wiki/Mitchell%E2%80%93Netravali_filters) bicubic filtering. pub struct Mitchell {} alg!(Mitchell);