/src/libvips/libvips/resample/templates.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* various interpolation templates |
2 | | */ |
3 | | |
4 | | /* |
5 | | |
6 | | This file is part of VIPS. |
7 | | |
8 | | VIPS is free software; you can redistribute it and/or modify |
9 | | it under the terms of the GNU Lesser General Public License as published by |
10 | | the Free Software Foundation; either version 2 of the License, or |
11 | | (at your option) any later version. |
12 | | |
13 | | This program is distributed in the hope that it will be useful, |
14 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | GNU Lesser General Public License for more details. |
17 | | |
18 | | You should have received a copy of the GNU Lesser General Public License |
19 | | along with this program; if not, write to the Free Software |
20 | | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
21 | | 02110-1301 USA |
22 | | |
23 | | */ |
24 | | |
25 | | /* |
26 | | |
27 | | These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk |
28 | | |
29 | | */ |
30 | | |
31 | | #include <cstdint> |
32 | | |
33 | | /* |
34 | | * Various casts which assume that the data is already in range. (That |
35 | | * is, they are to be used with monotone samplers.) |
36 | | */ |
37 | | template <typename T> |
38 | | static T inline to_fptypes(const double val) |
39 | 0 | { |
40 | 0 | const T newval = val; |
41 | |
|
42 | 0 | return newval; |
43 | 0 | } Unexecuted instantiation: lbb.cpp:float to_fptypes<float>(double) Unexecuted instantiation: lbb.cpp:double to_fptypes<double>(double) Unexecuted instantiation: nohalo.cpp:float to_fptypes<float>(double) Unexecuted instantiation: nohalo.cpp:double to_fptypes<double>(double) Unexecuted instantiation: vsqbs.cpp:float to_fptypes<float>(double) Unexecuted instantiation: vsqbs.cpp:double to_fptypes<double>(double) |
44 | | |
45 | | template <typename T> |
46 | | static T inline to_withsign(const double val) |
47 | 0 | { |
48 | 0 | const int sign_of_val = 2 * (val >= 0.) - 1; |
49 | 0 | const int rounded_abs_val = .5 + sign_of_val * val; |
50 | 0 | const T newval = sign_of_val * rounded_abs_val; |
51 | |
|
52 | 0 | return newval; |
53 | 0 | } Unexecuted instantiation: lbb.cpp:signed char to_withsign<signed char>(double) Unexecuted instantiation: lbb.cpp:short to_withsign<short>(double) Unexecuted instantiation: lbb.cpp:int to_withsign<int>(double) Unexecuted instantiation: nohalo.cpp:signed char to_withsign<signed char>(double) Unexecuted instantiation: nohalo.cpp:short to_withsign<short>(double) Unexecuted instantiation: nohalo.cpp:int to_withsign<int>(double) Unexecuted instantiation: vsqbs.cpp:signed char to_withsign<signed char>(double) Unexecuted instantiation: vsqbs.cpp:short to_withsign<short>(double) Unexecuted instantiation: vsqbs.cpp:int to_withsign<int>(double) |
54 | | |
55 | | template <typename T> |
56 | | static T inline to_nosign(const double val) |
57 | 0 | { |
58 | 0 | const T newval = .5 + val; |
59 | |
|
60 | 0 | return newval; |
61 | 0 | } Unexecuted instantiation: lbb.cpp:unsigned char to_nosign<unsigned char>(double) Unexecuted instantiation: lbb.cpp:unsigned short to_nosign<unsigned short>(double) Unexecuted instantiation: lbb.cpp:unsigned int to_nosign<unsigned int>(double) Unexecuted instantiation: nohalo.cpp:unsigned char to_nosign<unsigned char>(double) Unexecuted instantiation: nohalo.cpp:unsigned short to_nosign<unsigned short>(double) Unexecuted instantiation: nohalo.cpp:unsigned int to_nosign<unsigned int>(double) Unexecuted instantiation: vsqbs.cpp:unsigned char to_nosign<unsigned char>(double) Unexecuted instantiation: vsqbs.cpp:unsigned short to_nosign<unsigned short>(double) Unexecuted instantiation: vsqbs.cpp:unsigned int to_nosign<unsigned int>(double) |
62 | | |
63 | | /* |
64 | | * Various bilinear implementation templates. Note that no clampling |
65 | | * is used: There is an assumption that the data is such that |
66 | | * over/underflow is not an issue: |
67 | | */ |
68 | | |
69 | | /* |
70 | | * Bilinear interpolation for float and double types. The first four |
71 | | * inputs are weights, the last four are the corresponding pixel |
72 | | * values: |
73 | | */ |
74 | | template <typename T> |
75 | | static T inline bilinear_fptypes( |
76 | | const double w_times_z, |
77 | | const double x_times_z, |
78 | | const double w_times_y, |
79 | | const double x_times_y, |
80 | | const double tre_thr, |
81 | | const double tre_thrfou, |
82 | | const double trequa_thr, |
83 | | const double trequa_thrfou) |
84 | | { |
85 | | const T newval = |
86 | | w_times_z * tre_thr + |
87 | | x_times_z * tre_thrfou + |
88 | | w_times_y * trequa_thr + |
89 | | x_times_y * trequa_thrfou; |
90 | | |
91 | | return newval; |
92 | | } |
93 | | |
94 | | /* |
95 | | * Bilinear interpolation for signed integer types: |
96 | | */ |
97 | | template <typename T> |
98 | | static T inline bilinear_withsign( |
99 | | const double w_times_z, |
100 | | const double x_times_z, |
101 | | const double w_times_y, |
102 | | const double x_times_y, |
103 | | const double tre_thr, |
104 | | const double tre_thrfou, |
105 | | const double trequa_thr, |
106 | | const double trequa_thrfou) |
107 | | { |
108 | | const double val = |
109 | | w_times_z * tre_thr + |
110 | | x_times_z * tre_thrfou + |
111 | | w_times_y * trequa_thr + |
112 | | x_times_y * trequa_thrfou; |
113 | | |
114 | | const int sign_of_val = 2 * (val >= 0.) - 1; |
115 | | |
116 | | const int rounded_abs_val = .5 + sign_of_val * val; |
117 | | |
118 | | const T newval = sign_of_val * rounded_abs_val; |
119 | | |
120 | | return newval; |
121 | | } |
122 | | |
123 | | /* |
124 | | * Bilinear Interpolation for unsigned integer types: |
125 | | */ |
126 | | template <typename T> |
127 | | static T inline bilinear_nosign( |
128 | | const double w_times_z, |
129 | | const double x_times_z, |
130 | | const double w_times_y, |
131 | | const double x_times_y, |
132 | | const double tre_thr, |
133 | | const double tre_thrfou, |
134 | | const double trequa_thr, |
135 | | const double trequa_thrfou) |
136 | | { |
137 | | const T newval = |
138 | | w_times_z * tre_thr + |
139 | | x_times_z * tre_thrfou + |
140 | | w_times_y * trequa_thr + |
141 | | x_times_y * trequa_thrfou + |
142 | | 0.5; |
143 | | |
144 | | return newval; |
145 | | } |
146 | | |
147 | | /* |
148 | | * Bicubic (Catmull-Rom) interpolation templates: |
149 | | */ |
150 | | |
151 | | template <typename T> |
152 | | static T inline unsigned_fixed_round(T v) |
153 | 0 | { |
154 | 0 | const int round_by = VIPS_INTERPOLATE_SCALE >> 1; |
155 | |
|
156 | 0 | return (v + round_by) >> VIPS_INTERPOLATE_SHIFT; |
157 | 0 | } Unexecuted instantiation: reduceh.cpp:int unsigned_fixed_round<int>(int) Unexecuted instantiation: reduceh.cpp:long unsigned_fixed_round<long>(long) Unexecuted instantiation: reducev.cpp:int unsigned_fixed_round<int>(int) Unexecuted instantiation: reducev.cpp:long unsigned_fixed_round<long>(long) Unexecuted instantiation: bicubic.cpp:int unsigned_fixed_round<int>(int) |
158 | | |
159 | | /* Fixed-point integer bicubic, used for 8-bit types. |
160 | | */ |
161 | | template <typename T> |
162 | | static int inline bicubic_unsigned_int( |
163 | | const T uno_one, const T uno_two, const T uno_thr, const T uno_fou, |
164 | | const T dos_one, const T dos_two, const T dos_thr, const T dos_fou, |
165 | | const T tre_one, const T tre_two, const T tre_thr, const T tre_fou, |
166 | | const T qua_one, const T qua_two, const T qua_thr, const T qua_fou, |
167 | | const int *restrict cx, const int *restrict cy) |
168 | 0 | { |
169 | 0 | const int c0 = cx[0]; |
170 | 0 | const int c1 = cx[1]; |
171 | 0 | const int c2 = cx[2]; |
172 | 0 | const int c3 = cx[3]; |
173 | |
|
174 | 0 | const int r0 = unsigned_fixed_round( |
175 | 0 | c0 * uno_one + |
176 | 0 | c1 * uno_two + |
177 | 0 | c2 * uno_thr + |
178 | 0 | c3 * uno_fou); |
179 | 0 | const int r1 = unsigned_fixed_round( |
180 | 0 | c0 * dos_one + |
181 | 0 | c1 * dos_two + |
182 | 0 | c2 * dos_thr + |
183 | 0 | c3 * dos_fou); |
184 | 0 | const int r2 = unsigned_fixed_round( |
185 | 0 | c0 * tre_one + |
186 | 0 | c1 * tre_two + |
187 | 0 | c2 * tre_thr + |
188 | 0 | c3 * tre_fou); |
189 | 0 | const int r3 = unsigned_fixed_round( |
190 | 0 | c0 * qua_one + |
191 | 0 | c1 * qua_two + |
192 | 0 | c2 * qua_thr + |
193 | 0 | c3 * qua_fou); |
194 | |
|
195 | 0 | return unsigned_fixed_round( |
196 | 0 | cy[0] * r0 + |
197 | 0 | cy[1] * r1 + |
198 | 0 | cy[2] * r2 + |
199 | 0 | cy[3] * r3); |
200 | 0 | } |
201 | | |
202 | | template <typename T> |
203 | | static T inline signed_fixed_round(T v) |
204 | 0 | { |
205 | 0 | const int sign_of_v = 2 * (v >= 0) - 1; |
206 | 0 | const int round_by = sign_of_v * (VIPS_INTERPOLATE_SCALE >> 1); |
207 | |
|
208 | 0 | return (v + round_by) >> VIPS_INTERPOLATE_SHIFT; |
209 | 0 | } Unexecuted instantiation: reduceh.cpp:int signed_fixed_round<int>(int) Unexecuted instantiation: reduceh.cpp:long signed_fixed_round<long>(long) Unexecuted instantiation: reducev.cpp:int signed_fixed_round<int>(int) Unexecuted instantiation: reducev.cpp:long signed_fixed_round<long>(long) Unexecuted instantiation: bicubic.cpp:int signed_fixed_round<int>(int) |
210 | | |
211 | | /* Fixed-point integer bicubic, used for 8-bit types. |
212 | | */ |
213 | | template <typename T> |
214 | | static int inline bicubic_signed_int( |
215 | | const T uno_one, const T uno_two, const T uno_thr, const T uno_fou, |
216 | | const T dos_one, const T dos_two, const T dos_thr, const T dos_fou, |
217 | | const T tre_one, const T tre_two, const T tre_thr, const T tre_fou, |
218 | | const T qua_one, const T qua_two, const T qua_thr, const T qua_fou, |
219 | | const int *restrict cx, const int *restrict cy) |
220 | 0 | { |
221 | 0 | const int c0 = cx[0]; |
222 | 0 | const int c1 = cx[1]; |
223 | 0 | const int c2 = cx[2]; |
224 | 0 | const int c3 = cx[3]; |
225 | |
|
226 | 0 | const int r0 = signed_fixed_round( |
227 | 0 | c0 * uno_one + |
228 | 0 | c1 * uno_two + |
229 | 0 | c2 * uno_thr + |
230 | 0 | c3 * uno_fou); |
231 | 0 | const int r1 = signed_fixed_round( |
232 | 0 | c0 * dos_one + |
233 | 0 | c1 * dos_two + |
234 | 0 | c2 * dos_thr + |
235 | 0 | c3 * dos_fou); |
236 | 0 | const int r2 = signed_fixed_round( |
237 | 0 | c0 * tre_one + |
238 | 0 | c1 * tre_two + |
239 | 0 | c2 * tre_thr + |
240 | 0 | c3 * tre_fou); |
241 | 0 | const int r3 = signed_fixed_round( |
242 | 0 | c0 * qua_one + |
243 | 0 | c1 * qua_two + |
244 | 0 | c2 * qua_thr + |
245 | 0 | c3 * qua_fou); |
246 | |
|
247 | 0 | return signed_fixed_round( |
248 | 0 | cy[0] * r0 + |
249 | 0 | cy[1] * r1 + |
250 | 0 | cy[2] * r2 + |
251 | 0 | cy[3] * r3); |
252 | 0 | } |
253 | | |
254 | | template <typename T> |
255 | | static T inline cubic_float( |
256 | | const T one, const T two, const T thr, const T fou, |
257 | | const double *restrict cx) |
258 | 0 | { |
259 | 0 | return cx[0] * one + |
260 | 0 | cx[1] * two + |
261 | 0 | cx[2] * thr + |
262 | 0 | cx[3] * fou; |
263 | 0 | } Unexecuted instantiation: bicubic.cpp:double cubic_float<double>(double, double, double, double, double const*) Unexecuted instantiation: bicubic.cpp:float cubic_float<float>(float, float, float, float, double const*) |
264 | | |
265 | | /* Floating-point bicubic, used for int/float/double types. |
266 | | */ |
267 | | template <typename T> |
268 | | static T inline bicubic_float( |
269 | | const T uno_one, const T uno_two, const T uno_thr, const T uno_fou, |
270 | | const T dos_one, const T dos_two, const T dos_thr, const T dos_fou, |
271 | | const T tre_one, const T tre_two, const T tre_thr, const T tre_fou, |
272 | | const T qua_one, const T qua_two, const T qua_thr, const T qua_fou, |
273 | | const double *restrict cx, const double *restrict cy) |
274 | 0 | { |
275 | 0 | const double r0 = cubic_float<T>( |
276 | 0 | uno_one, uno_two, uno_thr, uno_fou, cx); |
277 | 0 | const double r1 = cubic_float<T>( |
278 | 0 | dos_one, dos_two, dos_thr, dos_fou, cx); |
279 | 0 | const double r2 = cubic_float<T>( |
280 | 0 | tre_one, tre_two, tre_thr, tre_fou, cx); |
281 | 0 | const double r3 = cubic_float<T>( |
282 | 0 | qua_one, qua_two, qua_thr, qua_fou, cx); |
283 | |
|
284 | 0 | return cubic_float<T>(r0, r1, r2, r3, cy); |
285 | 0 | } Unexecuted instantiation: bicubic.cpp:double bicubic_float<double>(double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double, double const*, double const*) Unexecuted instantiation: bicubic.cpp:float bicubic_float<float>(float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, double const*, double const*) |
286 | | |
287 | | /* Given an offset in [0,1] (we can have x == 1 when building tables), |
288 | | * calculate c0, c1, c2, c3, the catmull-rom coefficients. This is called |
289 | | * from the interpolator as well as from the table builder. |
290 | | */ |
291 | | static void inline calculate_coefficients_catmull(double c[4], const double x) |
292 | 65 | { |
293 | | /* Nicolas believes that the following is an hitherto unknown |
294 | | * hyper-efficient method of computing Catmull-Rom coefficients. It |
295 | | * only uses 4* & 1+ & 5- for a total of only 10 flops to compute |
296 | | * four coefficients. |
297 | | */ |
298 | 65 | const double cr1 = 1. - x; |
299 | 65 | const double cr2 = -.5 * x; |
300 | 65 | const double cr3 = cr1 * cr2; |
301 | 65 | const double cone = cr1 * cr3; |
302 | 65 | const double cfou = x * cr3; |
303 | 65 | const double cr4 = cfou - cone; |
304 | 65 | const double ctwo = cr1 - cone + cr4; |
305 | 65 | const double cthr = x - cfou - cr4; |
306 | | |
307 | 65 | g_assert(x >= 0. && x <= 1.); |
308 | | |
309 | 65 | c[0] = cone; |
310 | 65 | c[3] = cfou; |
311 | 65 | c[1] = ctwo; |
312 | 65 | c[2] = cthr; |
313 | 65 | } Unexecuted instantiation: reduceh.cpp:calculate_coefficients_catmull(double*, double) Unexecuted instantiation: reducev.cpp:calculate_coefficients_catmull(double*, double) bicubic.cpp:calculate_coefficients_catmull(double*, double) Line | Count | Source | 292 | 65 | { | 293 | | /* Nicolas believes that the following is an hitherto unknown | 294 | | * hyper-efficient method of computing Catmull-Rom coefficients. It | 295 | | * only uses 4* & 1+ & 5- for a total of only 10 flops to compute | 296 | | * four coefficients. | 297 | | */ | 298 | 65 | const double cr1 = 1. - x; | 299 | 65 | const double cr2 = -.5 * x; | 300 | 65 | const double cr3 = cr1 * cr2; | 301 | 65 | const double cone = cr1 * cr3; | 302 | 65 | const double cfou = x * cr3; | 303 | 65 | const double cr4 = cfou - cone; | 304 | 65 | const double ctwo = cr1 - cone + cr4; | 305 | 65 | const double cthr = x - cfou - cr4; | 306 | | | 307 | 65 | g_assert(x >= 0. && x <= 1.); | 308 | | | 309 | 65 | c[0] = cone; | 310 | 65 | c[3] = cfou; | 311 | 65 | c[1] = ctwo; | 312 | 65 | c[2] = cthr; | 313 | 65 | } |
Unexecuted instantiation: lbb.cpp:calculate_coefficients_catmull(double*, double) Unexecuted instantiation: nohalo.cpp:calculate_coefficients_catmull(double*, double) Unexecuted instantiation: vsqbs.cpp:calculate_coefficients_catmull(double*, double) |
314 | | |
315 | | /* Generate a cubic filter. See: |
316 | | * |
317 | | * Mitchell and Netravali, Reconstruction Filters in Computer Graphics |
318 | | * Computer Graphics, Volume 22, Number 4, August 1988. |
319 | | * |
320 | | * B = 1, C = 0 - cubic B-spline |
321 | | * B = 1/3, C = 1/3 - Mitchell |
322 | | * B = 0, C = 1/2 - Catmull-Rom spline |
323 | | */ |
324 | | static double inline cubic_filter(double x, double B, double C) |
325 | 0 | { |
326 | 0 | const double ax = VIPS_FABS(x); |
327 | 0 | const double ax2 = ax * ax; |
328 | 0 | const double ax3 = ax2 * ax; |
329 | |
|
330 | 0 | if (ax <= 1) |
331 | 0 | return ((12 - 9 * B - 6 * C) * ax3 + |
332 | 0 | (-18 + 12 * B + 6 * C) * ax2 + |
333 | 0 | (6 - 2 * B)) / |
334 | 0 | 6; |
335 | | |
336 | 0 | if (ax <= 2) |
337 | 0 | return ((-B - 6 * C) * ax3 + |
338 | 0 | (6 * B + 30 * C) * ax2 + |
339 | 0 | (-12 * B - 48 * C) * ax + |
340 | 0 | (8 * B + 24 * C)) / |
341 | 0 | 6; |
342 | | |
343 | 0 | return 0.0; |
344 | 0 | } Unexecuted instantiation: reduceh.cpp:cubic_filter(double, double, double) Unexecuted instantiation: reducev.cpp:cubic_filter(double, double, double) Unexecuted instantiation: bicubic.cpp:cubic_filter(double, double, double) Unexecuted instantiation: lbb.cpp:cubic_filter(double, double, double) Unexecuted instantiation: nohalo.cpp:cubic_filter(double, double, double) Unexecuted instantiation: vsqbs.cpp:cubic_filter(double, double, double) |
345 | | |
346 | | static double inline sinc_filter(double x) |
347 | 0 | { |
348 | 0 | if (x == 0.0) |
349 | 0 | return 1.0; |
350 | | |
351 | 0 | x = x * VIPS_PI; |
352 | |
|
353 | 0 | return sin(x) / x; |
354 | 0 | } Unexecuted instantiation: reduceh.cpp:sinc_filter(double) Unexecuted instantiation: reducev.cpp:sinc_filter(double) Unexecuted instantiation: bicubic.cpp:sinc_filter(double) Unexecuted instantiation: lbb.cpp:sinc_filter(double) Unexecuted instantiation: nohalo.cpp:sinc_filter(double) Unexecuted instantiation: vsqbs.cpp:sinc_filter(double) |
355 | | |
356 | | using VipsFilterFn = double (*)(double); |
357 | | |
358 | | template <VipsKernel K> |
359 | | static double inline filter(double x); |
360 | | |
361 | | template <> |
362 | | double inline filter<VIPS_KERNEL_LINEAR>(double x) |
363 | 0 | { |
364 | 0 | x = VIPS_FABS(x); |
365 | |
|
366 | 0 | if (x < 1.0) |
367 | 0 | return 1.0 - x; |
368 | | |
369 | 0 | return 0.0; |
370 | 0 | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)1>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)1>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)1>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)1>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)1>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)1>(double) |
371 | | |
372 | | /* Catmull-Rom. |
373 | | */ |
374 | | template <> |
375 | | double inline filter<VIPS_KERNEL_CUBIC>(double x) |
376 | 0 | { |
377 | 0 | return cubic_filter(x, 0.0, 0.5); |
378 | 0 | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)2>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)2>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)2>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)2>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)2>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)2>(double) |
379 | | |
380 | | template <> |
381 | | double inline filter<VIPS_KERNEL_MITCHELL>(double x) |
382 | 0 | { |
383 | 0 | return cubic_filter(x, 1.0 / 3.0, 1.0 / 3.0); |
384 | 0 | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)3>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)3>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)3>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)3>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)3>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)3>(double) |
385 | | |
386 | | template <> |
387 | | double inline filter<VIPS_KERNEL_LANCZOS2>(double x) |
388 | 0 | { |
389 | 0 | if (x >= -2 && x <= 2) |
390 | 0 | return sinc_filter(x) * sinc_filter(x / 2); |
391 | | |
392 | 0 | return 0.0; |
393 | 0 | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)4>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)4>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)4>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)4>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)4>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)4>(double) |
394 | | |
395 | | template <> |
396 | | double inline filter<VIPS_KERNEL_LANCZOS3>(double x) |
397 | 0 | { |
398 | 0 | if (x >= -3 && x <= 3) |
399 | 0 | return sinc_filter(x) * sinc_filter(x / 3); |
400 | | |
401 | 0 | return 0.0; |
402 | 0 | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)5>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)5>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)5>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)5>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)5>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)5>(double) |
403 | | |
404 | | template <> |
405 | | double inline filter<VIPS_KERNEL_MKS2013>(double x) |
406 | 0 | { |
407 | 0 | x = VIPS_FABS(x); |
408 | |
|
409 | 0 | if (x >= 2.5) |
410 | 0 | return 0.0; |
411 | | |
412 | 0 | if (x >= 1.5) |
413 | 0 | return (x - 5.0 / 2.0) * (x - 5.0 / 2.0) / -8.0; |
414 | | |
415 | 0 | if (x >= 0.5) |
416 | 0 | return (4.0 * x * x - 11.0 * x + 7.0) / 4.0; |
417 | | |
418 | 0 | return 17.0 / 16.0 - 7.0 * x * x / 4.0; |
419 | 0 | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)6>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)6>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)6>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)6>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)6>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)6>(double) |
420 | | |
421 | | template <> |
422 | | double inline filter<VIPS_KERNEL_MKS2021>(double x) |
423 | 0 | { |
424 | 0 | x = VIPS_FABS(x); |
425 | |
|
426 | 0 | if (x >= 4.5) |
427 | 0 | return 0.0; |
428 | | |
429 | 0 | if (x >= 3.5) |
430 | 0 | return (4.0 * x * x - 36.0 * x + 81.0) / -1152.0; |
431 | | |
432 | 0 | if (x >= 2.5) |
433 | 0 | return (4.0 * x * x - 27.0 * x + 45.0) / 144.0; |
434 | | |
435 | 0 | if (x >= 1.5) |
436 | 0 | return (24.0 * x * x - 113.0 * x + 130.0) / -144.0; |
437 | | |
438 | 0 | if (x >= 0.5) |
439 | 0 | return (140.0 * x * x - 379.0 * x + 239.0) / 144.0; |
440 | | |
441 | 0 | return 577.0 / 576.0 - 239.0 * x * x / 144.0; |
442 | 0 | } Unexecuted instantiation: reduceh.cpp:double filter<(VipsKernel)7>(double) Unexecuted instantiation: reducev.cpp:double filter<(VipsKernel)7>(double) Unexecuted instantiation: bicubic.cpp:double filter<(VipsKernel)7>(double) Unexecuted instantiation: lbb.cpp:double filter<(VipsKernel)7>(double) Unexecuted instantiation: nohalo.cpp:double filter<(VipsKernel)7>(double) Unexecuted instantiation: vsqbs.cpp:double filter<(VipsKernel)7>(double) |
443 | | |
444 | | /* Given an x in [0,1] (we can have x == 1 when building tables), |
445 | | * calculate c0 .. c(@n_points), the coefficients. This is called |
446 | | * from the interpolator as well as from the table builder. |
447 | | * |
448 | | * @shrink is the reduction factor, so 1 for interpolation, 2 for a |
449 | | * x2 reduction, etc. |
450 | | */ |
451 | | template <typename T> |
452 | | static void |
453 | | calculate_coefficients(T *c, const int n_points, |
454 | | VipsFilterFn filter_fn, const double shrink, const double x) |
455 | 0 | { |
456 | 0 | const double half = x + n_points / 2.0 - 1; |
457 | |
|
458 | 0 | int i; |
459 | 0 | T sum; |
460 | |
|
461 | 0 | sum = 0.0; |
462 | 0 | for (i = 0; i < n_points; i++) { |
463 | 0 | const double xp = (i - half) / shrink; |
464 | 0 | double l = filter_fn(xp); |
465 | |
|
466 | 0 | c[i] = l; |
467 | 0 | sum += l; |
468 | 0 | } |
469 | |
|
470 | 0 | for (i = 0; i < n_points; i++) |
471 | 0 | c[i] /= sum; |
472 | 0 | } Unexecuted instantiation: reduceh.cpp:void calculate_coefficients<double>(double*, int, double (*)(double), double, double) Unexecuted instantiation: reduceh.cpp:void calculate_coefficients<long double>(long double*, int, double (*)(double), double, double) Unexecuted instantiation: reducev.cpp:void calculate_coefficients<double>(double*, int, double (*)(double), double, double) Unexecuted instantiation: reducev.cpp:void calculate_coefficients<long double>(long double*, int, double (*)(double), double, double) |
473 | | |
474 | | /* Calculate a mask element. |
475 | | */ |
476 | | template <typename T> |
477 | | static void |
478 | | vips_reduce_make_mask(T *c, VipsKernel kernel, const int n_points, |
479 | | const double shrink, const double x) |
480 | 0 | { |
481 | 0 | switch (kernel) { |
482 | 0 | case VIPS_KERNEL_NEAREST: |
483 | 0 | c[0] = 1.0; |
484 | 0 | break; |
485 | | |
486 | 0 | case VIPS_KERNEL_LINEAR: |
487 | 0 | calculate_coefficients(c, n_points, |
488 | 0 | filter<VIPS_KERNEL_LINEAR>, shrink, x); |
489 | 0 | break; |
490 | | |
491 | 0 | case VIPS_KERNEL_CUBIC: |
492 | 0 | calculate_coefficients(c, n_points, |
493 | 0 | filter<VIPS_KERNEL_CUBIC>, shrink, x); |
494 | 0 | break; |
495 | | |
496 | 0 | case VIPS_KERNEL_MITCHELL: |
497 | 0 | calculate_coefficients(c, n_points, |
498 | 0 | filter<VIPS_KERNEL_MITCHELL>, shrink, x); |
499 | 0 | break; |
500 | | |
501 | 0 | case VIPS_KERNEL_LANCZOS2: |
502 | 0 | calculate_coefficients(c, n_points, |
503 | 0 | filter<VIPS_KERNEL_LANCZOS2>, shrink, x); |
504 | 0 | break; |
505 | | |
506 | 0 | case VIPS_KERNEL_LANCZOS3: |
507 | 0 | calculate_coefficients(c, n_points, |
508 | 0 | filter<VIPS_KERNEL_LANCZOS3>, shrink, x); |
509 | 0 | break; |
510 | | |
511 | 0 | case VIPS_KERNEL_MKS2013: |
512 | 0 | calculate_coefficients(c, n_points, |
513 | 0 | filter<VIPS_KERNEL_MKS2013>, shrink, x); |
514 | 0 | break; |
515 | | |
516 | 0 | case VIPS_KERNEL_MKS2021: |
517 | 0 | calculate_coefficients(c, n_points, |
518 | 0 | filter<VIPS_KERNEL_MKS2021>, shrink, x); |
519 | 0 | break; |
520 | | |
521 | 0 | default: |
522 | 0 | g_assert_not_reached(); |
523 | 0 | break; |
524 | 0 | } |
525 | 0 | } Unexecuted instantiation: reduceh.cpp:void vips_reduce_make_mask<double>(double*, VipsKernel, int, double, double) Unexecuted instantiation: reduceh.cpp:void vips_reduce_make_mask<long double>(long double*, VipsKernel, int, double, double) Unexecuted instantiation: reducev.cpp:void vips_reduce_make_mask<double>(double*, VipsKernel, int, double, double) Unexecuted instantiation: reducev.cpp:void vips_reduce_make_mask<long double>(long double*, VipsKernel, int, double, double) |
526 | | |
527 | | /* Machinery to promote type T to a larger data type, prevents an |
528 | | * overflow in reduce_sum(). Defaults to a 32-bit integral type. |
529 | | */ |
530 | | template <typename T> |
531 | | struct LongT { |
532 | | typedef int32_t type; |
533 | | }; |
534 | | |
535 | | /* 32-bit integral types needs a 64-bits intermediate. |
536 | | */ |
537 | | template <> |
538 | | struct LongT<int32_t> { |
539 | | typedef int64_t type; |
540 | | }; |
541 | | |
542 | | template <> |
543 | | struct LongT<uint32_t> { |
544 | | typedef int64_t type; |
545 | | }; |
546 | | |
547 | | /* 32-bit floating-point types needs a 64-bits intermediate. |
548 | | */ |
549 | | template <> |
550 | | struct LongT<float> { |
551 | | typedef double type; |
552 | | }; |
553 | | |
554 | | /* 64-bit floating-point types needs a 128-bits intermediate. |
555 | | */ |
556 | | template <> |
557 | | struct LongT<double> { |
558 | | typedef long double type; |
559 | | }; |
560 | | |
561 | | /* Our inner loop for resampling with a convolution of type CT. Operate on |
562 | | * elements of type T, gather results in an intermediate of type IT. |
563 | | */ |
564 | | template <typename T, typename CT, typename IT = typename LongT<T>::type> |
565 | | static IT inline reduce_sum(const T *restrict in, int stride, |
566 | | const CT *restrict c, int n) |
567 | 0 | { |
568 | 0 | IT sum; |
569 | |
|
570 | 0 | sum = 0; |
571 | 0 | for (int i = 0; i < n; i++) { |
572 | 0 | sum += (IT) c[i] * in[0]; |
573 | 0 | in += stride; |
574 | 0 | } |
575 | |
|
576 | 0 | return sum; |
577 | 0 | } Unexecuted instantiation: reduceh.cpp:int reduce_sum<unsigned char, short, int>(unsigned char const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:int reduce_sum<signed char, short, int>(signed char const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:int reduce_sum<unsigned short, short, int>(unsigned short const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:int reduce_sum<short, short, int>(short const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:long reduce_sum<unsigned int, short, long>(unsigned int const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:long reduce_sum<int, short, long>(int const*, int, short const*, int) Unexecuted instantiation: reduceh.cpp:double reduce_sum<float, double, double>(float const*, int, double const*, int) Unexecuted instantiation: reduceh.cpp:long double reduce_sum<double, long double, long double>(double const*, int, long double const*, int) Unexecuted instantiation: reducev.cpp:int reduce_sum<unsigned char, short, int>(unsigned char const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:int reduce_sum<signed char, short, int>(signed char const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:int reduce_sum<unsigned short, short, int>(unsigned short const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:int reduce_sum<short, short, int>(short const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:long reduce_sum<unsigned int, short, long>(unsigned int const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:long reduce_sum<int, short, long>(int const*, int, short const*, int) Unexecuted instantiation: reducev.cpp:double reduce_sum<float, double, double>(float const*, int, double const*, int) Unexecuted instantiation: reducev.cpp:long double reduce_sum<double, long double, long double>(double const*, int, long double const*, int) |