1#![allow(clippy::excessive_precision)]
30
31use crate::bartlett::{bartlett, bartlett_hann};
32use crate::bc_spline::{
33 b_spline, catmull_rom, hermite_spline, mitchell_netravalli, robidoux, robidoux_sharp,
34};
35use crate::bilinear::bilinear;
36use crate::blackman::blackman;
37use crate::bohman::bohman;
38use crate::cubic::{bicubic_spline, cubic_spline};
39use crate::gaussian::gaussian;
40use crate::hann::{hamming, hann, hanning};
41use crate::kaiser::kaiser;
42use crate::lagrange::{lagrange2, lagrange3};
43use crate::lanczos::{
44 lanczos2, lanczos2_jinc, lanczos3, lanczos3_jinc, lanczos4, lanczos4_jinc, lanczos6,
45 lanczos6_jinc,
46};
47use crate::quadric::quadric;
48use crate::sinc::sinc;
49use crate::sphinx::sphinx;
50use crate::spline_n::{spline16, spline36, spline64};
51use crate::welch::welch;
52use crate::{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 EwaHanning,
80 Blackman,
81 EwaBlackman,
82 Welch,
83 Quadric,
84 EwaQuadric,
85 Gaussian,
86 Sphinx,
87 Bartlett,
88 Robidoux,
89 EwaRobidoux,
90 RobidouxSharp,
91 EwaRobidouxSharp,
92 Spline16,
93 Spline36,
94 Spline64,
95 Kaiser,
96 BartlettHann,
97 Box,
98 Bohman,
99 Lanczos2,
100 Lanczos3,
101 Lanczos4,
102 Lanczos2Jinc,
103 Lanczos3Jinc,
104 Lanczos4Jinc,
105 EwaLanczos3Jinc,
106 Ginseng,
107 EwaGinseng,
108 EwaLanczosSharp,
109 EwaLanczos4Sharpest,
110 EwaLanczosSoft,
111 HaasnSoft,
112 Lagrange2,
113 Lagrange3,
114 Lanczos6,
115 Lanczos6Jinc,
116 Area,
118}
119
120impl From<u32> for ResamplingFunction {
121 fn from(value: u32) -> Self {
122 match value {
123 0 => ResamplingFunction::Bilinear,
124 1 => ResamplingFunction::Nearest,
125 2 => ResamplingFunction::Cubic,
126 3 => ResamplingFunction::MitchellNetravalli,
127 4 => ResamplingFunction::CatmullRom,
128 5 => ResamplingFunction::Hermite,
129 6 => ResamplingFunction::BSpline,
130 7 => ResamplingFunction::Hann,
131 8 => ResamplingFunction::Bicubic,
132 9 => ResamplingFunction::Hamming,
133 10 => ResamplingFunction::Hanning,
134 11 => ResamplingFunction::Blackman,
135 12 => ResamplingFunction::Welch,
136 13 => ResamplingFunction::Quadric,
137 14 => ResamplingFunction::Gaussian,
138 15 => ResamplingFunction::Sphinx,
139 16 => ResamplingFunction::Bartlett,
140 17 => ResamplingFunction::Robidoux,
141 18 => ResamplingFunction::RobidouxSharp,
142 19 => ResamplingFunction::Spline16,
143 20 => ResamplingFunction::Spline36,
144 21 => ResamplingFunction::Spline64,
145 22 => ResamplingFunction::Kaiser,
146 23 => ResamplingFunction::BartlettHann,
147 24 => ResamplingFunction::Box,
148 25 => ResamplingFunction::Bohman,
149 26 => ResamplingFunction::Lanczos2,
150 27 => ResamplingFunction::Lanczos3,
151 28 => ResamplingFunction::Lanczos4,
152 29 => ResamplingFunction::Lanczos2Jinc,
153 30 => ResamplingFunction::Lanczos3Jinc,
154 31 => ResamplingFunction::Lanczos4Jinc,
155 32 => ResamplingFunction::EwaHanning,
156 33 => ResamplingFunction::EwaRobidoux,
157 34 => ResamplingFunction::EwaBlackman,
158 35 => ResamplingFunction::EwaQuadric,
159 36 => ResamplingFunction::EwaRobidouxSharp,
160 37 => ResamplingFunction::EwaLanczos3Jinc,
161 38 => ResamplingFunction::Ginseng,
162 39 => ResamplingFunction::EwaGinseng,
163 40 => ResamplingFunction::EwaLanczosSharp,
164 41 => ResamplingFunction::EwaLanczos4Sharpest,
165 42 => ResamplingFunction::EwaLanczosSoft,
166 43 => ResamplingFunction::HaasnSoft,
167 44 => ResamplingFunction::Lagrange2,
168 45 => ResamplingFunction::Lagrange3,
169 46 => ResamplingFunction::Lanczos6,
170 47 => ResamplingFunction::Lanczos6Jinc,
171 48 => ResamplingFunction::Area,
172 _ => ResamplingFunction::Bilinear,
173 }
174 }
175}
176
177#[derive(Debug, Copy, Clone)]
179pub(crate) struct ResamplingWindow<T> {
180 pub(crate) window: fn(T) -> T,
181 pub(crate) window_size: f32,
182 pub(crate) blur: f32,
183 pub(crate) taper: f32,
184}
185
186impl<T> ResamplingWindow<T> {
187 fn new(window: fn(T) -> T, window_size: f32, blur: f32, taper: f32) -> ResamplingWindow<T> {
188 ResamplingWindow {
189 window,
190 window_size,
191 blur,
192 taper,
193 }
194 }
195}
196
197#[derive(Debug, Copy, Clone)]
199pub(crate) struct ResamplingFilter<T> {
200 pub kernel: fn(T) -> T,
201 pub window: Option<ResamplingWindow<T>>,
202 pub min_kernel_size: f32,
203 pub is_ewa: bool,
204 pub is_resizable_kernel: bool,
205 pub is_area: bool,
206}
207
208impl<T> ResamplingFilter<T> {
209 fn new(kernel: fn(T) -> T, min_kernel_size: f32, is_ewa: bool) -> ResamplingFilter<T> {
210 ResamplingFilter {
211 kernel,
212 window: None,
213 min_kernel_size,
214 is_ewa,
215 is_resizable_kernel: true,
216 is_area: false,
217 }
218 }
219
220 fn new_with_window(
221 kernel: fn(T) -> T,
222 window: ResamplingWindow<T>,
223 min_kernel_size: f32,
224 is_ewa: bool,
225 ) -> ResamplingFilter<T> {
226 ResamplingFilter::<T> {
227 kernel,
228 window: Some(window),
229 min_kernel_size,
230 is_ewa,
231 is_resizable_kernel: true,
232 is_area: false,
233 }
234 }
235
236 fn new_with_fixed_kernel(
237 kernel: fn(T) -> T,
238 min_kernel_size: f32,
239 is_ewa: bool,
240 ) -> ResamplingFilter<T> {
241 ResamplingFilter::<T> {
242 kernel,
243 window: None,
244 min_kernel_size,
245 is_ewa,
246 is_resizable_kernel: false,
247 is_area: false,
248 }
249 }
250
251 fn new_with_area(kernel: fn(T) -> T, min_kernel_size: f32) -> ResamplingFilter<T> {
252 ResamplingFilter {
253 kernel,
254 window: None,
255 min_kernel_size,
256 is_ewa: false,
257 is_resizable_kernel: true,
258 is_area: true,
259 }
260 }
261}
262
263const JINC_R3: f32 = 3.2383154841662362f32;
264const JINC_R4: f32 = 4.2410628637960699f32;
265
266impl ResamplingFunction {
267 pub(crate) fn get_resampling_filter<T>(&self) -> ResamplingFilter<T>
268 where
269 T: Copy
270 + Neg
271 + Signed
272 + Float
273 + 'static
274 + ConstPI
275 + MulAssign<T>
276 + AddAssign<T>
277 + AsPrimitive<f64>
278 + AsPrimitive<usize>
279 + Jinc<T>
280 + ConstSqrt2,
281 f32: AsPrimitive<T>,
282 f64: AsPrimitive<T>,
283 usize: AsPrimitive<T>,
284 {
285 match self {
286 ResamplingFunction::Bilinear => ResamplingFilter::new(bilinear, 2f32, false),
287 ResamplingFunction::Nearest => {
288 ResamplingFilter::new(bilinear, 2f32, false)
290 }
291 ResamplingFunction::Cubic => ResamplingFilter::new(cubic_spline, 2f32, false),
292 ResamplingFunction::MitchellNetravalli => {
293 ResamplingFilter::new(mitchell_netravalli, 2f32, false)
294 }
295 ResamplingFunction::Lanczos3 => ResamplingFilter::new(lanczos3, 3f32, false),
296 ResamplingFunction::CatmullRom => ResamplingFilter::new(catmull_rom, 2f32, false),
297 ResamplingFunction::Hermite => ResamplingFilter::new(hermite_spline, 2f32, false),
298 ResamplingFunction::BSpline => ResamplingFilter::new(b_spline, 2f32, false),
299 ResamplingFunction::Hann => ResamplingFilter::new(hann, 3f32, false),
300 ResamplingFunction::Bicubic => ResamplingFilter::new(bicubic_spline, 2f32, false),
301 ResamplingFunction::Lanczos4 => ResamplingFilter::new(lanczos4, 4f32, false),
302 ResamplingFunction::Lanczos2 => ResamplingFilter::new(lanczos2, 2f32, false),
303 ResamplingFunction::Hamming => ResamplingFilter::new(hamming, 2f32, false),
304 ResamplingFunction::Hanning => ResamplingFilter::new(hanning, 2f32, false),
305 ResamplingFunction::EwaHanning => ResamplingFilter::new_with_window(
306 T::jinc(),
307 ResamplingWindow::new(hanning, 2f32, 0f32, 0f32),
308 1f32,
309 true,
310 ),
311 ResamplingFunction::Welch => ResamplingFilter::new(welch, 2f32, false),
312 ResamplingFunction::Quadric => ResamplingFilter::new(quadric, 2f32, false),
313 ResamplingFunction::EwaQuadric => ResamplingFilter::new(quadric, 2f32, true),
314 ResamplingFunction::Gaussian => ResamplingFilter::new(gaussian, 2f32, false),
315 ResamplingFunction::Sphinx => ResamplingFilter::new(sphinx, 2f32, false),
316 ResamplingFunction::Bartlett => ResamplingFilter::new(bartlett, 2f32, false),
317 ResamplingFunction::Robidoux => ResamplingFilter::new(robidoux, 2f32, false),
318 ResamplingFunction::EwaRobidoux => ResamplingFilter::new(robidoux, 2f32, true),
319 ResamplingFunction::RobidouxSharp => ResamplingFilter::new(robidoux_sharp, 2f32, false),
320 ResamplingFunction::EwaRobidouxSharp => {
321 ResamplingFilter::new(robidoux_sharp, 2f32, true)
322 }
323 ResamplingFunction::Spline16 => {
324 ResamplingFilter::new_with_fixed_kernel(spline16, 2f32, false)
325 }
326 ResamplingFunction::Spline36 => {
327 ResamplingFilter::new_with_fixed_kernel(spline36, 4f32, false)
328 }
329 ResamplingFunction::Spline64 => {
330 ResamplingFilter::new_with_fixed_kernel(spline64, 6f32, false)
331 }
332 ResamplingFunction::Kaiser => ResamplingFilter::new(kaiser, 2f32, false),
333 ResamplingFunction::BartlettHann => ResamplingFilter::new(bartlett_hann, 2f32, false),
334 ResamplingFunction::Box => ResamplingFilter::new(box_weight, 2f32, false),
335 ResamplingFunction::Area => ResamplingFilter::new_with_area(box_weight, 2f32),
336 ResamplingFunction::Bohman => ResamplingFilter::new(bohman, 2f32, false),
337 ResamplingFunction::Lanczos2Jinc => ResamplingFilter::new(lanczos2_jinc, 2f32, false),
338 ResamplingFunction::Lanczos3Jinc => ResamplingFilter::new(lanczos3_jinc, 3f32, false),
339 ResamplingFunction::EwaLanczos3Jinc => ResamplingFilter::new(lanczos3_jinc, 3f32, true),
340 ResamplingFunction::Lanczos4Jinc => ResamplingFilter::new(lanczos4_jinc, 4f32, false),
341 ResamplingFunction::Blackman => ResamplingFilter::new(blackman, 2f32, false),
342 ResamplingFunction::EwaBlackman => ResamplingFilter::new(blackman, 2f32, true),
343 ResamplingFunction::Ginseng => ResamplingFilter::new_with_window(
344 sinc,
345 ResamplingWindow::new(T::jinc(), 3f32, 1f32, 0f32),
346 3f32,
347 false,
348 ),
349 ResamplingFunction::EwaGinseng => ResamplingFilter::new_with_window(
350 sinc,
351 ResamplingWindow::new(T::jinc(), JINC_R3, 1f32, 0f32),
352 3f32,
353 true,
354 ),
355 ResamplingFunction::EwaLanczosSharp => ResamplingFilter::new_with_window(
356 T::jinc(),
357 ResamplingWindow::new(T::jinc(), JINC_R3, 0.9812505837223707f32, 0f32),
358 3f32,
359 true,
360 ),
361 ResamplingFunction::EwaLanczos4Sharpest => ResamplingFilter::new_with_window(
362 T::jinc(),
363 ResamplingWindow::new(T::jinc(), JINC_R4, 0.8845120932605005f32, 0f32),
364 4f32,
365 true,
366 ),
367 ResamplingFunction::EwaLanczosSoft => ResamplingFilter::new_with_window(
368 T::jinc(),
369 ResamplingWindow::new(T::jinc(), JINC_R3, 1.0164667662867047f32, 0f32),
370 3f32,
371 true,
372 ),
373 ResamplingFunction::HaasnSoft => ResamplingFilter::new_with_window(
374 T::jinc(),
375 ResamplingWindow::new(hanning, 3f32, 1.11f32, 0f32),
376 3f32,
377 false,
378 ),
379 ResamplingFunction::Lagrange2 => ResamplingFilter::new(lagrange2, 2f32, false),
380 ResamplingFunction::Lagrange3 => ResamplingFilter::new(lagrange3, 3f32, false),
381 ResamplingFunction::Lanczos6Jinc => ResamplingFilter::new(lanczos6_jinc, 6f32, false),
382 ResamplingFunction::Lanczos6 => ResamplingFilter::new(lanczos6, 6f32, false),
383 }
384 }
385}