1#![allow(clippy::excessive_precision)]
30
31use crate::math::bartlett::{bartlett, bartlett_hann};
32use crate::math::bc_spline::{
33 b_spline, catmull_rom, hermite_spline, mitchell_netravalli, robidoux, robidoux_sharp,
34};
35use crate::math::bilinear::bilinear;
36use crate::math::blackman::blackman;
37use crate::math::bohman::bohman;
38use crate::math::cubic::{bicubic_spline, cubic_spline};
39use crate::math::gaussian::gaussian;
40use crate::math::hann::{hamming, hann, hanning};
41use crate::math::kaiser::kaiser;
42use crate::math::lagrange::{lagrange2, lagrange3};
43use crate::math::lanczos::{
44 lanczos2, lanczos2_jinc, lanczos3, lanczos3_jinc, lanczos4, lanczos4_jinc, lanczos6,
45 lanczos6_jinc,
46};
47use crate::math::quadric::quadric;
48use crate::math::sinc::sinc;
49use crate::math::sphinx::sphinx;
50use crate::math::spline_n::{spline16, spline36, spline64};
51use crate::math::welch::welch;
52use crate::math::{ConstPI, ConstSqrt2, Jinc};
53use num_traits::{AsPrimitive, Float, Signed};
54use std::ops::{AddAssign, MulAssign, Neg};
55
56#[inline(always)]
57pub(crate) fn box_weight<V: Copy + 'static>(_: V) -> V
58where
59 f32: AsPrimitive<V>,
60{
61 1f32.as_()
62}
63
64#[derive(Debug, Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq)]
65pub enum ResamplingFunction {
67 Bilinear,
68 Nearest,
69 Cubic,
70 #[default]
71 MitchellNetravalli,
72 CatmullRom,
73 Hermite,
74 BSpline,
75 Hann,
76 Bicubic,
77 Hamming,
78 Hanning,
79 Blackman,
80 Welch,
81 Quadric,
82 Gaussian,
83 Sphinx,
84 Bartlett,
85 Robidoux,
86 RobidouxSharp,
87 Spline16,
88 Spline36,
89 Spline64,
90 Kaiser,
91 BartlettHann,
92 Box,
93 Bohman,
94 Lanczos2,
95 Lanczos3,
96 Lanczos4,
97 Lanczos2Jinc,
98 Lanczos3Jinc,
99 Lanczos4Jinc,
100 Ginseng,
101 HaasnSoft,
102 Lagrange2,
103 Lagrange3,
104 Lanczos6,
105 Lanczos6Jinc,
106 Area,
108}
109
110impl From<u32> for ResamplingFunction {
111 fn from(value: u32) -> Self {
112 match value {
113 0 => ResamplingFunction::Bilinear,
114 1 => ResamplingFunction::Nearest,
115 2 => ResamplingFunction::Cubic,
116 3 => ResamplingFunction::MitchellNetravalli,
117 4 => ResamplingFunction::CatmullRom,
118 5 => ResamplingFunction::Hermite,
119 6 => ResamplingFunction::BSpline,
120 7 => ResamplingFunction::Hann,
121 8 => ResamplingFunction::Bicubic,
122 9 => ResamplingFunction::Hamming,
123 10 => ResamplingFunction::Hanning,
124 11 => ResamplingFunction::Blackman,
125 12 => ResamplingFunction::Welch,
126 13 => ResamplingFunction::Quadric,
127 14 => ResamplingFunction::Gaussian,
128 15 => ResamplingFunction::Sphinx,
129 16 => ResamplingFunction::Bartlett,
130 17 => ResamplingFunction::Robidoux,
131 18 => ResamplingFunction::RobidouxSharp,
132 19 => ResamplingFunction::Spline16,
133 20 => ResamplingFunction::Spline36,
134 21 => ResamplingFunction::Spline64,
135 22 => ResamplingFunction::Kaiser,
136 23 => ResamplingFunction::BartlettHann,
137 24 => ResamplingFunction::Box,
138 25 => ResamplingFunction::Bohman,
139 26 => ResamplingFunction::Lanczos2,
140 27 => ResamplingFunction::Lanczos3,
141 28 => ResamplingFunction::Lanczos4,
142 29 => ResamplingFunction::Lanczos2Jinc,
143 30 => ResamplingFunction::Lanczos3Jinc,
144 31 => ResamplingFunction::Lanczos4Jinc,
145 32 => ResamplingFunction::Ginseng,
146 33 => ResamplingFunction::HaasnSoft,
147 34 => ResamplingFunction::Lagrange2,
148 35 => ResamplingFunction::Lagrange3,
149 36 => ResamplingFunction::Lanczos6,
150 37 => ResamplingFunction::Lanczos6Jinc,
151 38 => ResamplingFunction::Area,
152 _ => ResamplingFunction::Bilinear,
153 }
154 }
155}
156
157#[derive(Debug, Copy, Clone)]
158pub(crate) struct ResamplingWindow<T> {
159 pub(crate) window: fn(T) -> T,
160 pub(crate) window_size: f32,
161 pub(crate) blur: f32,
162 pub(crate) taper: f32,
163}
164
165impl<T> ResamplingWindow<T> {
166 fn new(window: fn(T) -> T, window_size: f32, blur: f32, taper: f32) -> ResamplingWindow<T> {
167 ResamplingWindow {
168 window,
169 window_size,
170 blur,
171 taper,
172 }
173 }
174}
175
176#[derive(Debug, Copy, Clone)]
177pub(crate) struct ResamplingFilter<T> {
178 pub kernel: fn(T) -> T,
179 pub window: Option<ResamplingWindow<T>>,
180 pub min_kernel_size: f32,
181 pub is_resizable_kernel: bool,
182 pub is_area_filter: bool,
183}
184
185impl<T> ResamplingFilter<T> {
186 fn new(kernel: fn(T) -> T, min_kernel_size: f32) -> ResamplingFilter<T> {
187 ResamplingFilter {
188 kernel,
189 window: None,
190 min_kernel_size,
191 is_resizable_kernel: true,
192 is_area_filter: false,
193 }
194 }
195
196 fn new_area(kernel: fn(T) -> T, min_kernel_size: f32) -> ResamplingFilter<T> {
197 ResamplingFilter {
198 kernel,
199 window: None,
200 min_kernel_size,
201 is_resizable_kernel: true,
202 is_area_filter: true,
203 }
204 }
205
206 fn new_with_window(
207 kernel: fn(T) -> T,
208 window: ResamplingWindow<T>,
209 min_kernel_size: f32,
210 ) -> ResamplingFilter<T> {
211 ResamplingFilter::<T> {
212 kernel,
213 window: Some(window),
214 min_kernel_size,
215 is_resizable_kernel: true,
216 is_area_filter: false,
217 }
218 }
219
220 fn new_with_fixed_kernel(kernel: fn(T) -> T, min_kernel_size: f32) -> ResamplingFilter<T> {
221 ResamplingFilter::<T> {
222 kernel,
223 window: None,
224 min_kernel_size,
225 is_resizable_kernel: false,
226 is_area_filter: false,
227 }
228 }
229}
230
231impl ResamplingFunction {
232 pub(crate) fn get_resampling_filter<T>(&self) -> ResamplingFilter<T>
233 where
234 T: Copy
235 + Neg
236 + Signed
237 + Float
238 + 'static
239 + ConstPI
240 + MulAssign<T>
241 + AddAssign<T>
242 + AsPrimitive<f64>
243 + AsPrimitive<usize>
244 + Jinc<T>
245 + ConstSqrt2,
246 f32: AsPrimitive<T>,
247 f64: AsPrimitive<T>,
248 usize: AsPrimitive<T>,
249 {
250 match self {
251 ResamplingFunction::Bilinear => ResamplingFilter::new(bilinear, 1f32),
252 ResamplingFunction::Area => ResamplingFilter::new_area(box_weight, 0.5f32),
253 ResamplingFunction::Nearest => {
254 ResamplingFilter::new(bilinear, 2f32)
256 }
257 ResamplingFunction::Cubic => ResamplingFilter::new(cubic_spline, 2f32),
258 ResamplingFunction::MitchellNetravalli => {
259 ResamplingFilter::new(mitchell_netravalli, 2f32)
260 }
261 ResamplingFunction::Lanczos3 => ResamplingFilter::new(lanczos3, 3f32),
262 ResamplingFunction::CatmullRom => ResamplingFilter::new(catmull_rom, 2f32),
263 ResamplingFunction::Hermite => ResamplingFilter::new(hermite_spline, 2f32),
264 ResamplingFunction::BSpline => ResamplingFilter::new(b_spline, 2f32),
265 ResamplingFunction::Hann => ResamplingFilter::new(hann, 3f32),
266 ResamplingFunction::Bicubic => ResamplingFilter::new(bicubic_spline, 2f32),
267 ResamplingFunction::Lanczos4 => ResamplingFilter::new(lanczos4, 4f32),
268 ResamplingFunction::Lanczos2 => ResamplingFilter::new(lanczos2, 2f32),
269 ResamplingFunction::Hamming => ResamplingFilter::new(hamming, 1f32),
270 ResamplingFunction::Hanning => ResamplingFilter::new(hanning, 2f32),
271 ResamplingFunction::Welch => ResamplingFilter::new(welch, 2f32),
272 ResamplingFunction::Quadric => ResamplingFilter::new(quadric, 2f32),
273 ResamplingFunction::Gaussian => ResamplingFilter::new(gaussian, 2f32),
274 ResamplingFunction::Sphinx => ResamplingFilter::new(sphinx, 2f32),
275 ResamplingFunction::Bartlett => ResamplingFilter::new(bartlett, 2f32),
276 ResamplingFunction::Robidoux => ResamplingFilter::new(robidoux, 2f32),
277 ResamplingFunction::RobidouxSharp => ResamplingFilter::new(robidoux_sharp, 2f32),
278 ResamplingFunction::Spline16 => ResamplingFilter::new_with_fixed_kernel(spline16, 2f32),
279 ResamplingFunction::Spline36 => ResamplingFilter::new_with_fixed_kernel(spline36, 4f32),
280 ResamplingFunction::Spline64 => ResamplingFilter::new_with_fixed_kernel(spline64, 6f32),
281 ResamplingFunction::Kaiser => ResamplingFilter::new(kaiser, 2f32),
282 ResamplingFunction::BartlettHann => ResamplingFilter::new(bartlett_hann, 2f32),
283 ResamplingFunction::Box => ResamplingFilter::new(box_weight, 2f32),
284 ResamplingFunction::Bohman => ResamplingFilter::new(bohman, 2f32),
285 ResamplingFunction::Lanczos2Jinc => ResamplingFilter::new(lanczos2_jinc, 2f32),
286 ResamplingFunction::Lanczos3Jinc => ResamplingFilter::new(lanczos3_jinc, 3f32),
287 ResamplingFunction::Lanczos4Jinc => ResamplingFilter::new(lanczos4_jinc, 4f32),
288 ResamplingFunction::Blackman => ResamplingFilter::new(blackman, 2f32),
289 ResamplingFunction::Ginseng => ResamplingFilter::new_with_window(
290 sinc,
291 ResamplingWindow::new(T::jinc(), 3f32, 1f32, 0f32),
292 3f32,
293 ),
294 ResamplingFunction::HaasnSoft => ResamplingFilter::new_with_window(
295 T::jinc(),
296 ResamplingWindow::new(hanning, 3f32, 1.11f32, 0f32),
297 3f32,
298 ),
299 ResamplingFunction::Lagrange2 => ResamplingFilter::new(lagrange2, 2f32),
300 ResamplingFunction::Lagrange3 => ResamplingFilter::new(lagrange3, 3f32),
301 ResamplingFunction::Lanczos6Jinc => ResamplingFilter::new(lanczos6_jinc, 6f32),
302 ResamplingFunction::Lanczos6 => ResamplingFilter::new(lanczos6, 6f32),
303 }
304 }
305}