#![allow(clippy::excessive_precision)]
use crate::math::bartlett::{bartlett, bartlett_hann};
use crate::math::bc_spline::{
b_spline, catmull_rom, hermite_spline, mitchell_netravalli, robidoux, robidoux_sharp,
};
use crate::math::bilinear::bilinear;
use crate::math::blackman::blackman;
use crate::math::bohman::bohman;
use crate::math::cubic::{bicubic_spline, cubic_spline};
use crate::math::gaussian::gaussian;
use crate::math::hann::{hamming, hann, hanning};
use crate::math::kaiser::kaiser;
use crate::math::lagrange::{lagrange2, lagrange3};
use crate::math::lanczos::{
lanczos2, lanczos2_jinc, lanczos3, lanczos3_jinc, lanczos4, lanczos4_jinc, lanczos6,
lanczos6_jinc,
};
use crate::math::quadric::quadric;
use crate::math::sinc::sinc;
use crate::math::sphinx::sphinx;
use crate::math::spline_n::{spline16, spline36, spline64};
use crate::math::welch::welch;
use crate::math::{ConstPI, ConstSqrt2, Jinc};
use num_traits::{AsPrimitive, Float, Signed};
use std::ops::{AddAssign, MulAssign, Neg};
#[inline(always)]
pub(crate) fn box_weight<V: Copy + 'static>(_: V) -> V
where
f32: AsPrimitive<V>,
{
1f32.as_()
}
#[derive(Debug, Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq)]
pub enum ResamplingFunction {
Bilinear,
Nearest,
Cubic,
#[default]
MitchellNetravalli,
CatmullRom,
Hermite,
BSpline,
Hann,
Bicubic,
Hamming,
Hanning,
Blackman,
Welch,
Quadric,
Gaussian,
Sphinx,
Bartlett,
Robidoux,
RobidouxSharp,
Spline16,
Spline36,
Spline64,
Kaiser,
BartlettHann,
Box,
Bohman,
Lanczos2,
Lanczos3,
Lanczos4,
Lanczos2Jinc,
Lanczos3Jinc,
Lanczos4Jinc,
Ginseng,
HaasnSoft,
Lagrange2,
Lagrange3,
Lanczos6,
Lanczos6Jinc,
}
impl From<u32> for ResamplingFunction {
fn from(value: u32) -> Self {
match value {
0 => ResamplingFunction::Bilinear,
1 => ResamplingFunction::Nearest,
2 => ResamplingFunction::Cubic,
3 => ResamplingFunction::MitchellNetravalli,
4 => ResamplingFunction::CatmullRom,
5 => ResamplingFunction::Hermite,
6 => ResamplingFunction::BSpline,
7 => ResamplingFunction::Hann,
8 => ResamplingFunction::Bicubic,
9 => ResamplingFunction::Hamming,
10 => ResamplingFunction::Hanning,
11 => ResamplingFunction::Blackman,
12 => ResamplingFunction::Welch,
13 => ResamplingFunction::Quadric,
14 => ResamplingFunction::Gaussian,
15 => ResamplingFunction::Sphinx,
16 => ResamplingFunction::Bartlett,
17 => ResamplingFunction::Robidoux,
18 => ResamplingFunction::RobidouxSharp,
19 => ResamplingFunction::Spline16,
20 => ResamplingFunction::Spline36,
21 => ResamplingFunction::Spline64,
22 => ResamplingFunction::Kaiser,
23 => ResamplingFunction::BartlettHann,
24 => ResamplingFunction::Box,
25 => ResamplingFunction::Bohman,
26 => ResamplingFunction::Lanczos2,
27 => ResamplingFunction::Lanczos3,
28 => ResamplingFunction::Lanczos4,
29 => ResamplingFunction::Lanczos2Jinc,
30 => ResamplingFunction::Lanczos3Jinc,
31 => ResamplingFunction::Lanczos4Jinc,
32 => ResamplingFunction::Ginseng,
33 => ResamplingFunction::HaasnSoft,
34 => ResamplingFunction::Lagrange2,
35 => ResamplingFunction::Lagrange3,
36 => ResamplingFunction::Lanczos6,
37 => ResamplingFunction::Lanczos6Jinc,
_ => ResamplingFunction::Bilinear,
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct ResamplingWindow<T> {
pub(crate) window: fn(T) -> T,
pub(crate) window_size: f32,
pub(crate) blur: f32,
pub(crate) taper: f32,
}
impl<T> ResamplingWindow<T> {
fn new(window: fn(T) -> T, window_size: f32, blur: f32, taper: f32) -> ResamplingWindow<T> {
ResamplingWindow {
window,
window_size,
blur,
taper,
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct ResamplingFilter<T> {
pub kernel: fn(T) -> T,
pub window: Option<ResamplingWindow<T>>,
pub min_kernel_size: f32,
pub is_resizable_kernel: bool,
}
impl<T> ResamplingFilter<T> {
fn new(kernel: fn(T) -> T, min_kernel_size: f32) -> ResamplingFilter<T> {
ResamplingFilter {
kernel,
window: None,
min_kernel_size,
is_resizable_kernel: true,
}
}
fn new_with_window(
kernel: fn(T) -> T,
window: ResamplingWindow<T>,
min_kernel_size: f32,
) -> ResamplingFilter<T> {
ResamplingFilter::<T> {
kernel,
window: Some(window),
min_kernel_size,
is_resizable_kernel: true,
}
}
fn new_with_fixed_kernel(kernel: fn(T) -> T, min_kernel_size: f32) -> ResamplingFilter<T> {
ResamplingFilter::<T> {
kernel,
window: None,
min_kernel_size,
is_resizable_kernel: false,
}
}
}
impl ResamplingFunction {
pub fn get_resampling_filter<T>(&self) -> ResamplingFilter<T>
where
T: Copy
+ Neg
+ Signed
+ Float
+ 'static
+ ConstPI
+ MulAssign<T>
+ AddAssign<T>
+ AsPrimitive<f64>
+ AsPrimitive<usize>
+ Jinc<T>
+ ConstSqrt2,
f32: AsPrimitive<T>,
f64: AsPrimitive<T>,
usize: AsPrimitive<T>,
{
match self {
ResamplingFunction::Bilinear => ResamplingFilter::new(bilinear, 2f32),
ResamplingFunction::Nearest => {
ResamplingFilter::new(bilinear, 1f32)
}
ResamplingFunction::Cubic => ResamplingFilter::new(cubic_spline::<T>, 2f32),
ResamplingFunction::MitchellNetravalli => {
ResamplingFilter::new(mitchell_netravalli::<T>, 2f32)
}
ResamplingFunction::Lanczos3 => ResamplingFilter::new(lanczos3, 3f32),
ResamplingFunction::CatmullRom => ResamplingFilter::new(catmull_rom::<T>, 2f32),
ResamplingFunction::Hermite => ResamplingFilter::new(hermite_spline::<T>, 2f32),
ResamplingFunction::BSpline => ResamplingFilter::new(b_spline::<T>, 2f32),
ResamplingFunction::Hann => ResamplingFilter::new(hann, 3f32),
ResamplingFunction::Bicubic => ResamplingFilter::new(bicubic_spline::<T>, 3f32),
ResamplingFunction::Lanczos4 => ResamplingFilter::new(lanczos4, 4f32),
ResamplingFunction::Lanczos2 => ResamplingFilter::new(lanczos2, 2f32),
ResamplingFunction::Hamming => ResamplingFilter::new(hamming, 1f32),
ResamplingFunction::Hanning => ResamplingFilter::new(hanning, 1f32),
ResamplingFunction::Welch => ResamplingFilter::new(welch, 1f32),
ResamplingFunction::Quadric => ResamplingFilter::new(quadric, 1.5f32),
ResamplingFunction::Gaussian => ResamplingFilter::new(gaussian, 2f32),
ResamplingFunction::Sphinx => ResamplingFilter::new(sphinx, 2f32),
ResamplingFunction::Bartlett => ResamplingFilter::new(bartlett, 1f32),
ResamplingFunction::Robidoux => ResamplingFilter::new(robidoux::<T>, 2f32),
ResamplingFunction::RobidouxSharp => ResamplingFilter::new(robidoux_sharp::<T>, 2f32),
ResamplingFunction::Spline16 => ResamplingFilter::new_with_fixed_kernel(spline16, 2f32),
ResamplingFunction::Spline36 => ResamplingFilter::new_with_fixed_kernel(spline36, 4f32),
ResamplingFunction::Spline64 => ResamplingFilter::new_with_fixed_kernel(spline64, 6f32),
ResamplingFunction::Kaiser => ResamplingFilter::new(kaiser, 2f32),
ResamplingFunction::BartlettHann => ResamplingFilter::new(bartlett_hann, 2f32),
ResamplingFunction::Box => ResamplingFilter::new(box_weight, 0.5f32),
ResamplingFunction::Bohman => ResamplingFilter::new(bohman, 2f32),
ResamplingFunction::Lanczos2Jinc => ResamplingFilter::new(lanczos2_jinc, 2f32),
ResamplingFunction::Lanczos3Jinc => ResamplingFilter::new(lanczos3_jinc, 3f32),
ResamplingFunction::Lanczos4Jinc => ResamplingFilter::new(lanczos4_jinc, 4f32),
ResamplingFunction::Blackman => ResamplingFilter::new(blackman, 2f32),
ResamplingFunction::Ginseng => ResamplingFilter::new_with_window(
sinc,
ResamplingWindow::new(T::jinc(), 3f32, 1f32, 0f32),
3f32,
),
ResamplingFunction::HaasnSoft => ResamplingFilter::new_with_window(
T::jinc(),
ResamplingWindow::new(hanning, 3f32, 1.11f32, 0f32),
3f32,
),
ResamplingFunction::Lagrange2 => ResamplingFilter::new(lagrange2, 2f32),
ResamplingFunction::Lagrange3 => ResamplingFilter::new(lagrange3, 3f32),
ResamplingFunction::Lanczos6Jinc => ResamplingFilter::new(lanczos6_jinc, 6f32),
ResamplingFunction::Lanczos6 => ResamplingFilter::new(lanczos6, 6f32),
}
}
}