/rust/registry/src/index.crates.io-1949cf8c6b5b557f/pic-scale-safe-0.1.5/src/sampler.rs
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) Radzivon Bartoshyk, 10/2024. All rights reserved. |
3 | | * |
4 | | * Redistribution and use in source and binary forms, with or without modification, |
5 | | * are permitted provided that the following conditions are met: |
6 | | * |
7 | | * 1. Redistributions of source code must retain the above copyright notice, this |
8 | | * list of conditions and the following disclaimer. |
9 | | * |
10 | | * 2. Redistributions in binary form must reproduce the above copyright notice, |
11 | | * this list of conditions and the following disclaimer in the documentation |
12 | | * and/or other materials provided with the distribution. |
13 | | * |
14 | | * 3. Neither the name of the copyright holder nor the names of its |
15 | | * contributors may be used to endorse or promote products derived from |
16 | | * this software without specific prior written permission. |
17 | | * |
18 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
19 | | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
20 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
21 | | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
22 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
24 | | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
25 | | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
26 | | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
27 | | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | | */ |
29 | | #![allow(clippy::excessive_precision)] |
30 | | |
31 | | use crate::math::bartlett::{bartlett, bartlett_hann}; |
32 | | use crate::math::bc_spline::{ |
33 | | b_spline, catmull_rom, hermite_spline, mitchell_netravalli, robidoux, robidoux_sharp, |
34 | | }; |
35 | | use crate::math::bilinear::bilinear; |
36 | | use crate::math::blackman::blackman; |
37 | | use crate::math::bohman::bohman; |
38 | | use crate::math::cubic::{bicubic_spline, cubic_spline}; |
39 | | use crate::math::gaussian::gaussian; |
40 | | use crate::math::hann::{hamming, hann, hanning}; |
41 | | use crate::math::kaiser::kaiser; |
42 | | use crate::math::lagrange::{lagrange2, lagrange3}; |
43 | | use crate::math::lanczos::{ |
44 | | lanczos2, lanczos2_jinc, lanczos3, lanczos3_jinc, lanczos4, lanczos4_jinc, lanczos6, |
45 | | lanczos6_jinc, |
46 | | }; |
47 | | use crate::math::quadric::quadric; |
48 | | use crate::math::sinc::sinc; |
49 | | use crate::math::sphinx::sphinx; |
50 | | use crate::math::spline_n::{spline16, spline36, spline64}; |
51 | | use crate::math::welch::welch; |
52 | | use crate::math::{ConstPI, ConstSqrt2, Jinc}; |
53 | | use num_traits::{AsPrimitive, Float, Signed}; |
54 | | use std::ops::{AddAssign, MulAssign, Neg}; |
55 | | |
56 | | #[inline(always)] |
57 | 0 | pub(crate) fn box_weight<V: Copy + 'static>(_: V) -> V |
58 | 0 | where |
59 | 0 | f32: AsPrimitive<V>, |
60 | | { |
61 | 0 | 1f32.as_() |
62 | 0 | } |
63 | | |
64 | | #[derive(Debug, Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq)] |
65 | | /// Describes resampling function that will be used |
66 | | pub 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 | | /// This method replicates `INTER_AREA` behaviour from OpenCV |
107 | | Area, |
108 | | } |
109 | | |
110 | | impl From<u32> for ResamplingFunction { |
111 | 0 | fn from(value: u32) -> Self { |
112 | 0 | match value { |
113 | 0 | 0 => ResamplingFunction::Bilinear, |
114 | 0 | 1 => ResamplingFunction::Nearest, |
115 | 0 | 2 => ResamplingFunction::Cubic, |
116 | 0 | 3 => ResamplingFunction::MitchellNetravalli, |
117 | 0 | 4 => ResamplingFunction::CatmullRom, |
118 | 0 | 5 => ResamplingFunction::Hermite, |
119 | 0 | 6 => ResamplingFunction::BSpline, |
120 | 0 | 7 => ResamplingFunction::Hann, |
121 | 0 | 8 => ResamplingFunction::Bicubic, |
122 | 0 | 9 => ResamplingFunction::Hamming, |
123 | 0 | 10 => ResamplingFunction::Hanning, |
124 | 0 | 11 => ResamplingFunction::Blackman, |
125 | 0 | 12 => ResamplingFunction::Welch, |
126 | 0 | 13 => ResamplingFunction::Quadric, |
127 | 0 | 14 => ResamplingFunction::Gaussian, |
128 | 0 | 15 => ResamplingFunction::Sphinx, |
129 | 0 | 16 => ResamplingFunction::Bartlett, |
130 | 0 | 17 => ResamplingFunction::Robidoux, |
131 | 0 | 18 => ResamplingFunction::RobidouxSharp, |
132 | 0 | 19 => ResamplingFunction::Spline16, |
133 | 0 | 20 => ResamplingFunction::Spline36, |
134 | 0 | 21 => ResamplingFunction::Spline64, |
135 | 0 | 22 => ResamplingFunction::Kaiser, |
136 | 0 | 23 => ResamplingFunction::BartlettHann, |
137 | 0 | 24 => ResamplingFunction::Box, |
138 | 0 | 25 => ResamplingFunction::Bohman, |
139 | 0 | 26 => ResamplingFunction::Lanczos2, |
140 | 0 | 27 => ResamplingFunction::Lanczos3, |
141 | 0 | 28 => ResamplingFunction::Lanczos4, |
142 | 0 | 29 => ResamplingFunction::Lanczos2Jinc, |
143 | 0 | 30 => ResamplingFunction::Lanczos3Jinc, |
144 | 0 | 31 => ResamplingFunction::Lanczos4Jinc, |
145 | 0 | 32 => ResamplingFunction::Ginseng, |
146 | 0 | 33 => ResamplingFunction::HaasnSoft, |
147 | 0 | 34 => ResamplingFunction::Lagrange2, |
148 | 0 | 35 => ResamplingFunction::Lagrange3, |
149 | 0 | 36 => ResamplingFunction::Lanczos6, |
150 | 0 | 37 => ResamplingFunction::Lanczos6Jinc, |
151 | 0 | 38 => ResamplingFunction::Area, |
152 | 0 | _ => ResamplingFunction::Bilinear, |
153 | | } |
154 | 0 | } |
155 | | } |
156 | | |
157 | | #[derive(Debug, Copy, Clone)] |
158 | | pub(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 | | |
165 | | impl<T> ResamplingWindow<T> { |
166 | 0 | fn new(window: fn(T) -> T, window_size: f32, blur: f32, taper: f32) -> ResamplingWindow<T> { |
167 | 0 | ResamplingWindow { |
168 | 0 | window, |
169 | 0 | window_size, |
170 | 0 | blur, |
171 | 0 | taper, |
172 | 0 | } |
173 | 0 | } |
174 | | } |
175 | | |
176 | | #[derive(Debug, Copy, Clone)] |
177 | | pub(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 | | |
185 | | impl<T> ResamplingFilter<T> { |
186 | 0 | fn new(kernel: fn(T) -> T, min_kernel_size: f32) -> ResamplingFilter<T> { |
187 | 0 | ResamplingFilter { |
188 | 0 | kernel, |
189 | 0 | window: None, |
190 | 0 | min_kernel_size, |
191 | 0 | is_resizable_kernel: true, |
192 | 0 | is_area_filter: false, |
193 | 0 | } |
194 | 0 | } |
195 | | |
196 | 0 | fn new_area(kernel: fn(T) -> T, min_kernel_size: f32) -> ResamplingFilter<T> { |
197 | 0 | ResamplingFilter { |
198 | 0 | kernel, |
199 | 0 | window: None, |
200 | 0 | min_kernel_size, |
201 | 0 | is_resizable_kernel: true, |
202 | 0 | is_area_filter: true, |
203 | 0 | } |
204 | 0 | } |
205 | | |
206 | 0 | fn new_with_window( |
207 | 0 | kernel: fn(T) -> T, |
208 | 0 | window: ResamplingWindow<T>, |
209 | 0 | min_kernel_size: f32, |
210 | 0 | ) -> ResamplingFilter<T> { |
211 | 0 | ResamplingFilter::<T> { |
212 | 0 | kernel, |
213 | 0 | window: Some(window), |
214 | 0 | min_kernel_size, |
215 | 0 | is_resizable_kernel: true, |
216 | 0 | is_area_filter: false, |
217 | 0 | } |
218 | 0 | } |
219 | | |
220 | 0 | fn new_with_fixed_kernel(kernel: fn(T) -> T, min_kernel_size: f32) -> ResamplingFilter<T> { |
221 | 0 | ResamplingFilter::<T> { |
222 | 0 | kernel, |
223 | 0 | window: None, |
224 | 0 | min_kernel_size, |
225 | 0 | is_resizable_kernel: false, |
226 | 0 | is_area_filter: false, |
227 | 0 | } |
228 | 0 | } |
229 | | } |
230 | | |
231 | | impl ResamplingFunction { |
232 | 0 | pub(crate) fn get_resampling_filter<T>(&self) -> ResamplingFilter<T> |
233 | 0 | where |
234 | 0 | T: Copy |
235 | 0 | + Neg |
236 | 0 | + Signed |
237 | 0 | + Float |
238 | 0 | + 'static |
239 | 0 | + ConstPI |
240 | 0 | + MulAssign<T> |
241 | 0 | + AddAssign<T> |
242 | 0 | + AsPrimitive<f64> |
243 | 0 | + AsPrimitive<usize> |
244 | 0 | + Jinc<T> |
245 | 0 | + ConstSqrt2, |
246 | 0 | f32: AsPrimitive<T>, |
247 | 0 | f64: AsPrimitive<T>, |
248 | 0 | usize: AsPrimitive<T>, |
249 | | { |
250 | 0 | match self { |
251 | 0 | ResamplingFunction::Bilinear => ResamplingFilter::new(bilinear, 1f32), |
252 | 0 | ResamplingFunction::Area => ResamplingFilter::new_area(box_weight, 0.5f32), |
253 | | ResamplingFunction::Nearest => { |
254 | | // Just a stab for nearest |
255 | 0 | ResamplingFilter::new(bilinear, 2f32) |
256 | | } |
257 | 0 | ResamplingFunction::Cubic => ResamplingFilter::new(cubic_spline, 2f32), |
258 | | ResamplingFunction::MitchellNetravalli => { |
259 | 0 | ResamplingFilter::new(mitchell_netravalli, 2f32) |
260 | | } |
261 | 0 | ResamplingFunction::Lanczos3 => ResamplingFilter::new(lanczos3, 3f32), |
262 | 0 | ResamplingFunction::CatmullRom => ResamplingFilter::new(catmull_rom, 2f32), |
263 | 0 | ResamplingFunction::Hermite => ResamplingFilter::new(hermite_spline, 2f32), |
264 | 0 | ResamplingFunction::BSpline => ResamplingFilter::new(b_spline, 2f32), |
265 | 0 | ResamplingFunction::Hann => ResamplingFilter::new(hann, 3f32), |
266 | 0 | ResamplingFunction::Bicubic => ResamplingFilter::new(bicubic_spline, 2f32), |
267 | 0 | ResamplingFunction::Lanczos4 => ResamplingFilter::new(lanczos4, 4f32), |
268 | 0 | ResamplingFunction::Lanczos2 => ResamplingFilter::new(lanczos2, 2f32), |
269 | 0 | ResamplingFunction::Hamming => ResamplingFilter::new(hamming, 1f32), |
270 | 0 | ResamplingFunction::Hanning => ResamplingFilter::new(hanning, 2f32), |
271 | 0 | ResamplingFunction::Welch => ResamplingFilter::new(welch, 2f32), |
272 | 0 | ResamplingFunction::Quadric => ResamplingFilter::new(quadric, 2f32), |
273 | 0 | ResamplingFunction::Gaussian => ResamplingFilter::new(gaussian, 2f32), |
274 | 0 | ResamplingFunction::Sphinx => ResamplingFilter::new(sphinx, 2f32), |
275 | 0 | ResamplingFunction::Bartlett => ResamplingFilter::new(bartlett, 2f32), |
276 | 0 | ResamplingFunction::Robidoux => ResamplingFilter::new(robidoux, 2f32), |
277 | 0 | ResamplingFunction::RobidouxSharp => ResamplingFilter::new(robidoux_sharp, 2f32), |
278 | 0 | ResamplingFunction::Spline16 => ResamplingFilter::new_with_fixed_kernel(spline16, 2f32), |
279 | 0 | ResamplingFunction::Spline36 => ResamplingFilter::new_with_fixed_kernel(spline36, 4f32), |
280 | 0 | ResamplingFunction::Spline64 => ResamplingFilter::new_with_fixed_kernel(spline64, 6f32), |
281 | 0 | ResamplingFunction::Kaiser => ResamplingFilter::new(kaiser, 2f32), |
282 | 0 | ResamplingFunction::BartlettHann => ResamplingFilter::new(bartlett_hann, 2f32), |
283 | 0 | ResamplingFunction::Box => ResamplingFilter::new(box_weight, 2f32), |
284 | 0 | ResamplingFunction::Bohman => ResamplingFilter::new(bohman, 2f32), |
285 | 0 | ResamplingFunction::Lanczos2Jinc => ResamplingFilter::new(lanczos2_jinc, 2f32), |
286 | 0 | ResamplingFunction::Lanczos3Jinc => ResamplingFilter::new(lanczos3_jinc, 3f32), |
287 | 0 | ResamplingFunction::Lanczos4Jinc => ResamplingFilter::new(lanczos4_jinc, 4f32), |
288 | 0 | ResamplingFunction::Blackman => ResamplingFilter::new(blackman, 2f32), |
289 | 0 | ResamplingFunction::Ginseng => ResamplingFilter::new_with_window( |
290 | 0 | sinc, |
291 | 0 | ResamplingWindow::new(T::jinc(), 3f32, 1f32, 0f32), |
292 | | 3f32, |
293 | | ), |
294 | 0 | ResamplingFunction::HaasnSoft => ResamplingFilter::new_with_window( |
295 | 0 | T::jinc(), |
296 | 0 | ResamplingWindow::new(hanning, 3f32, 1.11f32, 0f32), |
297 | | 3f32, |
298 | | ), |
299 | 0 | ResamplingFunction::Lagrange2 => ResamplingFilter::new(lagrange2, 2f32), |
300 | 0 | ResamplingFunction::Lagrange3 => ResamplingFilter::new(lagrange3, 3f32), |
301 | 0 | ResamplingFunction::Lanczos6Jinc => ResamplingFilter::new(lanczos6_jinc, 6f32), |
302 | 0 | ResamplingFunction::Lanczos6 => ResamplingFilter::new(lanczos6, 6f32), |
303 | | } |
304 | 0 | } |
305 | | } |