[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

resizeimage.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2004 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35
36
37 #ifndef VIGRA_RESIZEIMAGE_HXX
38 #define VIGRA_RESIZEIMAGE_HXX
39
40 #include <vector>
41 #include "utilities.hxx"
42 #include "numerictraits.hxx"
43 #include "stdimage.hxx"
44 #include "recursiveconvolution.hxx"
45 #include "separableconvolution.hxx"
46 #include "resampling_convolution.hxx"
47 #include "splines.hxx"
48 #include "multi_shape.hxx"
49
50 namespace vigra {
51
52 /*****************************************************************/
53 /* */
54 /* CoscotFunction */
55 /* */
56 /*****************************************************************/
57
58 /** The Coscot interpolation function.
59
60 Implements the Coscot interpolation function proposed by Maria Magnusson Seger
61 (maria@isy.liu.se) in the context of tomographic reconstruction. It provides a fast
62 transition between the pass- and stop-bands and minimal ripple outside the transition
63 region. Both properties are important for this application and can be tuned by the parameters
64 <i>m</i> and <i>h</i> (with defaults 3 and 0.5). The function is defined by
65
66 \f[ f_{m,h}(x) = \left\{ \begin{array}{ll}
67 \frac{1}{2m}\sin(\pi x)\cot(\pi x / (2 m))(h + (1-h)\cos(\pi x/m)) & |x| \leq m \\
68 0 & \mbox{otherwise}
69 \end{array}\right.
70 \f]
71
72 It can be used as a functor, and as a kernel for
73 \ref resamplingConvolveImage() to create a differentiable interpolant
74 of an image.
75
76 <b>\#include</b> <vigra/resizeimage.hxx><br>
77 Namespace: vigra
78
79 \ingroup MathFunctions
80 */
81 template <class T>
82 class CoscotFunction
83 {
84 public:
85
86 /** the kernel's value type
87 */
88 typedef T value_type;
89 /** the unary functor's argument type
90 */
91 typedef T argument_type;
92 /** the splines polynomial order
93 */
94 typedef T result_type;
95
96 CoscotFunction(unsigned int m = 3, double h = 0.5)
97 : m_(m),
98 h_(h)
99 {}
100
101 /** function (functor) call
102 */
103 result_type operator()(argument_type x) const
104 {
105 return x == 0.0 ?
106 1.0
107 : abs(x) < m_ ?
108 VIGRA_CSTD::sin(M_PI*x) / VIGRA_CSTD::tan(M_PI * x / 2.0 / m_) *
109 (h_ + (1.0 - h_) * VIGRA_CSTD::cos(M_PI * x / m_)) / 2.0 / m_
110 : 0.0;
111 }
112
113 /** index operator -- same as operator()
114 */
115 value_type operator[](value_type x) const
116 { return operator()(x); }
117
118 /** Radius of the function's support.
119 Needed for \ref resamplingConvolveImage(), equals m.
120 */
121 double radius() const
122 { return m_; }
123
124 /** Derivative order of the function: always 0.
125 */
126 unsigned int derivativeOrder() const
127 { return 0; }
128
129 /** Prefilter coefficients for compatibility with \ref vigra::BSpline.
130 (array has zero length, since prefiltering is not necessary).
131 */
132 ArrayVector<double> const & prefilterCoefficients() const
133 {
134 return prefilterCoefficients_;
135 }
136
137 protected:
138 static ArrayVector<double> prefilterCoefficients_;
139 unsigned int m_;
140 double h_;
141 };
142
143 template <class T>
144 ArrayVector<double> CoscotFunction<T>::prefilterCoefficients_;
145
146
147
148 /** \addtogroup GeometricTransformations Geometric Transformations
149 Zoom up and down by repeating pixels, or using various interpolation schemes.
150
151 See also:
152 <ul>
153 <li> \ref ResamplingConvolutionFilters to resize by means of pyramids or smoothing filters</li>
154 <li> \ref resampleImage() to just drop or repeat pixels</li>
155 <li> \ref resizeMultiArraySplineInterpolation() for multi-dimensional interpolation</li>
156 </ul>
157
158 <b>\#include</b> <vigra/stdimagefunctions.hxx><br>
159 <b>or</b><br>
160 <b>\#include</b> <vigra/resizeimage.hxx><br>
161 */
162 //@{
163
164 /********************************************************/
165 /* */
166 /* resizeLineNoInterpolation */
167 /* */
168 /********************************************************/
169
170 template <class SrcIterator, class SrcAccessor,
171 class DestIterator, class DestAccessor>
172 void
173 resizeLineNoInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
174 DestIterator id, DestIterator idend, DestAccessor ad)
175 {
176 int wold = iend - i1;
177 int wnew = idend - id;
178
179 if(wnew == 1)
180 {
181 ad.set(as(i1), id);
182 return;
183 }
184
185 double dx = (double)(wold - 1) / (wnew - 1);
186 double x = 0.5;
187 for(; id != idend; ++id, x += dx)
188 {
189 int ix = (int)x;
190 ad.set(as(i1, ix), id);
191 }
192 }
193
194 /********************************************************/
195 /* */
196 /* resizeImageNoInterpolation */
197 /* */
198 /********************************************************/
199
200 /** \brief Resize image by repeating the nearest pixel values.
201
202 This algorithm is very fast and does not require any arithmetic on
203 the pixel types.
204
205 The range of both the input and output images (resp. regions) must
206 be given. Both images must have a size of at least 2x2 pixels. The
207 scaling factors are then calculated accordingly. Destination
208 pixels are directly copied from the appropriate source pixels.
209
210 <b> Declarations:</b>
211
212 pass 2D array views:
213 \code
214 namespace vigra {
215 template <class T1, class S1,
216 class T2, class S2>
217 void
218 resizeImageNoInterpolation(MultiArrayView<2, T1, S1> const & src,
219 MultiArrayView<2, T2, S2> dest);
220 }
221 \endcode
222
223 \deprecatedAPI{resizeImageNoInterpolation}
224 pass \ref ImageIterators and \ref DataAccessors :
225 \code
226 namespace vigra {
227 template <class SrcImageIterator, class SrcAccessor,
228 class DestImageIterator, class DestAccessor>
229 void
230 resizeImageNoInterpolation(
231 SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
232 DestImageIterator id, DestImageIterator idend, DestAccessor da)
233 }
234 \endcode
235 use argument objects in conjunction with \ref ArgumentObjectFactories :
236 \code
237 namespace vigra {
238 template <class SrcImageIterator, class SrcAccessor,
239 class DestImageIterator, class DestAccessor>
240 void
241 resizeImageNoInterpolation(
242 triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
243 triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
244 }
245 \endcode
246 \deprecatedEnd
247
248 <b> Usage:</b>
249
250 <b>\#include</b> <vigra/resizeimage.hxx><br>
251 Namespace: vigra
252
253 \code
254 MultiArray<2, unsigned char> src(w, h);
255 MultiArray<2, float> dest(w_new, h_new);
256
257 resizeImageNoInterpolation(src, dest);
258 \endcode
259
260 \deprecatedUsage{resizeImageNoInterpolation}
261 \code
262 vigra::resizeImageNoInterpolation(
263 src.upperLeft(), src.lowerRight(), src.accessor(),
264 dest.upperLeft(), dest.lowerRight(), dest.accessor());
265
266 \endcode
267 <b> Required Interface:</b>
268 \code
269 SrcImageIterator src_upperleft, src_lowerright;
270 DestImageIterator dest_upperleft, src_lowerright;
271
272 SrcAccessor src_accessor;
273 DestAccessor dest_accessor;
274
275 dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
276
277 \endcode
278 \deprecatedEnd
279
280 <b> Preconditions:</b>
281
282 Source and destination must have at least 2 pixels along each axis.
283 */
284 doxygen_overloaded_function(template <...> void resizeImageNoInterpolation)
285
286 template <class SrcIterator, class SrcAccessor,
287 class DestIterator, class DestAccessor>
288 void
289 resizeImageNoInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
290 DestIterator id, DestIterator idend, DestAccessor da)
291 {
292 int w = iend.x - is.x;
293 int h = iend.y - is.y;
294
295 int wnew = idend.x - id.x;
296 int hnew = idend.y - id.y;
297
298 vigra_precondition((w > 1) && (h > 1),
299 "resizeImageNoInterpolation(): "
300 "Source image too small.\n");
301 vigra_precondition((wnew > 1) && (hnew > 1),
302 "resizeImageNoInterpolation(): "
303 "Destination image too small.\n");
304
305 typedef BasicImage<typename SrcAccessor::value_type> TmpImage;
306 typedef typename TmpImage::traverser TmpImageIterator;
307
308 TmpImage tmp(w, hnew);
309
310 TmpImageIterator yt = tmp.upperLeft();
311
312 for(int x=0; x<w; ++x, ++is.x, ++yt.x)
313 {
314 typename SrcIterator::column_iterator c1 = is.columnIterator();
315 typename TmpImageIterator::column_iterator ct = yt.columnIterator();
316
317 resizeLineNoInterpolation(c1, c1 + h, sa, ct, ct + hnew, tmp.accessor());
318 }
319
320 yt = tmp.upperLeft();
321
322 for(int y=0; y < hnew; ++y, ++yt.y, ++id.y)
323 {
324 typename DestIterator::row_iterator rd = id.rowIterator();
325 typename TmpImageIterator::row_iterator rt = yt.rowIterator();
326
327 resizeLineNoInterpolation(rt, rt + w, tmp.accessor(), rd, rd + wnew, da);
328 }
329 }
330
331 template <class SrcIterator, class SrcAccessor,
332 class DestIterator, class DestAccessor>
333 inline void
334 resizeImageNoInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
335 triple<DestIterator, DestIterator, DestAccessor> dest)
336 {
337 resizeImageNoInterpolation(src.first, src.second, src.third,
338 dest.first, dest.second, dest.third);
339 }
340
341 template <class T1, class S1,
342 class T2, class S2>
343 inline void
344 resizeImageNoInterpolation(MultiArrayView<2, T1, S1> const & src,
345 MultiArrayView<2, T2, S2> dest)
346 {
347 resizeImageNoInterpolation(srcImageRange(src),
348 destImageRange(dest));
349 }
350
351 /********************************************************/
352 /* */
353 /* resizeLineLinearInterpolation */
354 /* */
355 /********************************************************/
356
357 template <class SrcIterator, class SrcAccessor,
358 class DestIterator, class DestAccessor>
359 void
360 resizeLineLinearInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
361 DestIterator id, DestIterator idend, DestAccessor ad)
362 {
363 int wold = iend - i1;
364 int wnew = idend - id;
365
366 if((wold <= 1) || (wnew <= 1)) return; // oder error ?
367
368 typedef
369 NumericTraits<typename DestAccessor::value_type> DestTraits;
370 typedef typename DestTraits::RealPromote RealPromote;
371
372 ad.set(DestTraits::fromRealPromote(as(i1)), id);
373 ++id;
374
375 --iend, --idend;
376 ad.set(DestTraits::fromRealPromote(as(iend)), idend);
377
378 double dx = (double)(wold - 1) / (wnew - 1);
379 double x = dx;
380
381 for(; id != idend; ++id, x += dx)
382 {
383 if(x >= 1.0)
384 {
385 int xx = (int)x;
386 i1 += xx;
387 x -= (double)xx;
388 }
389 double x1 = 1.0 - x;
390
391 ad.set(DestTraits::fromRealPromote(RealPromote(x1 * as(i1) + x * as(i1, 1))), id);
392 }
393 }
394
395 /********************************************************/
396 /* */
397 /* resizeImageLinearInterpolation */
398 /* */
399 /********************************************************/
400
401 /** \brief Resize image using linear interpolation.
402
403 The function uses the standard separable bilinear interpolation algorithm to
404 obtain a good compromise between quality and speed.
405
406 The range must of both the input and output images (resp. regions)
407 must be given. Both images must have a size of at
408 least 2x2. The scaling factors are then calculated
409 accordingly. If the source image is larger than the destination, it
410 is smoothed (band limited) using a recursive
411 exponential filter. The source value_type (SrcAccessor::value_type) must
412 be a linear space, i.e. it must support addition, multiplication
413 with a scalar real number and \ref NumericTraits "NumericTraits".
414
415 <b> Declarations:</b>
416
417 pass 2D array views:
418 \code
419 namespace vigra {
420 template <class T1, class S1,
421 class T2, class S2>
422 void
423 resizeImageLinearInterpolation(MultiArrayView<2, T1, S1> const & src,
424 MultiArrayView<2, T2, S2> dest);
425 }
426 \endcode
427
428 \deprecatedAPI{resizeImageLinearInterpolation}
429 pass \ref ImageIterators and \ref DataAccessors :
430 \code
431 namespace vigra {
432 template <class SrcImageIterator, class SrcAccessor,
433 class DestImageIterator, class DestAccessor>
434 void
435 resizeImageLinearInterpolation(
436 SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
437 DestImageIterator id, DestImageIterator idend, DestAccessor da)
438 }
439 \endcode
440 use argument objects in conjunction with \ref ArgumentObjectFactories :
441 \code
442 namespace vigra {
443 template <class SrcImageIterator, class SrcAccessor,
444 class DestImageIterator, class DestAccessor>
445 void
446 resizeImageLinearInterpolation(
447 triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
448 triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
449 }
450 \endcode
451 \deprecatedEnd
452
453 <b> Usage:</b>
454
455 <b>\#include</b> <vigra/resizeimage.hxx><br>
456 Namespace: vigra
457
458 \code
459 MultiArray<2, unsigned char> src(w, h);
460 MultiArray<2, float> dest(w_new, h_new);
461
462 resizeImageLinearInterpolation(src, dest);
463 \endcode
464
465 \deprecatedUsage{resizeImageLinearInterpolation}
466 \code
467 vigra::resizeImageLinearInterpolation(
468 src.upperLeft(), src.lowerRight(), src.accessor(),
469 dest.upperLeft(), dest.lowerRight(), dest.accessor());
470
471 \endcode
472 <b> Required Interface:</b>
473 \code
474 SrcImageIterator src_upperleft, src_lowerright;
475 DestImageIterator dest_upperleft, src_lowerright;
476
477 SrcAccessor src_accessor;
478 DestAccessor dest_accessor;
479
480 NumericTraits<SrcAccessor::value_type>::RealPromote
481 u = src_accessor(src_upperleft),
482 v = src_accessor(src_upperleft, 1);
483 double d;
484
485 u = d * v;
486 u = u + v;
487
488 dest_accessor.set(
489 NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
490 dest_upperleft);
491
492 \endcode
493 \deprecatedEnd
494
495 <b> Preconditions:</b>
496
497 Source and destination must have at least 2 pixels along each axis.
498 */
499 doxygen_overloaded_function(template <...> void resizeImageLinearInterpolation)
500
501 template <class SrcIterator, class SrcAccessor,
502 class DestIterator, class DestAccessor>
503 void
504 resizeImageLinearInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
505 DestIterator id, DestIterator idend, DestAccessor da)
506 {
507 int w = iend.x - is.x;
508 int h = iend.y - is.y;
509
510 int wnew = idend.x - id.x;
511 int hnew = idend.y - id.y;
512
513 vigra_precondition((w > 1) && (h > 1),
514 "resizeImageLinearInterpolation(): "
515 "Source image too small.\n");
516 vigra_precondition((wnew > 1) && (hnew > 1),
517 "resizeImageLinearInterpolation(): "
518 "Destination image too small.\n");
519
520 double const scale = 2.0;
521
522 typedef typename SrcAccessor::value_type SRCVT;
523 typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
524 typedef BasicImage<TMPTYPE> TmpImage;
525 typedef typename TmpImage::traverser TmpImageIterator;
526
527 BasicImage<TMPTYPE> tmp(w, hnew);
528 BasicImage<TMPTYPE> line((h > w) ? h : w, 1);
529
530 int x,y;
531
532 typename BasicImage<TMPTYPE>::Iterator yt = tmp.upperLeft();
533 typename TmpImageIterator::row_iterator lt = line.upperLeft().rowIterator();
534
535 for(x=0; x<w; ++x, ++is.x, ++yt.x)
536 {
537 typename SrcIterator::column_iterator c1 = is.columnIterator();
538 typename TmpImageIterator::column_iterator ct = yt.columnIterator();
539
540 if(hnew < h)
541 {
542 recursiveSmoothLine(c1, c1 + h, sa,
543 lt, line.accessor(), (double)h/hnew/scale);
544
545 resizeLineLinearInterpolation(lt, lt + h, line.accessor(),
546 ct, ct + hnew, tmp.accessor());
547 }
548 else
549 {
550 resizeLineLinearInterpolation(c1, c1 + h, sa,
551 ct, ct + hnew, tmp.accessor());
552 }
553 }
554
555 yt = tmp.upperLeft();
556
557 for(y=0; y < hnew; ++y, ++yt.y, ++id.y)
558 {
559 typename DestIterator::row_iterator rd = id.rowIterator();
560 typename TmpImageIterator::row_iterator rt = yt.rowIterator();
561
562 if(wnew < w)
563 {
564 recursiveSmoothLine(rt, rt + w, tmp.accessor(),
565 lt, line.accessor(), (double)w/wnew/scale);
566
567 resizeLineLinearInterpolation(lt, lt + w, line.accessor(),
568 rd, rd + wnew, da);
569 }
570 else
571 {
572 resizeLineLinearInterpolation(rt, rt + w, tmp.accessor(),
573 rd, rd + wnew, da);
574 }
575 }
576 }
577
578 template <class SrcIterator, class SrcAccessor,
579 class DestIterator, class DestAccessor>
580 inline void
581 resizeImageLinearInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
582 triple<DestIterator, DestIterator, DestAccessor> dest)
583 {
584 resizeImageLinearInterpolation(src.first, src.second, src.third,
585 dest.first, dest.second, dest.third);
586 }
587
588 template <class T1, class S1,
589 class T2, class S2>
590 inline void
591 resizeImageLinearInterpolation(MultiArrayView<2, T1, S1> const & src,
592 MultiArrayView<2, T2, S2> dest)
593 {
594 resizeImageLinearInterpolation(srcImageRange(src),
595 destImageRange(dest));
596 }
597
598 /***************************************************************/
599 /* */
600 /* resizeImageSplineInterpolation */
601 /* */
602 /***************************************************************/
603
604 /** \brief Resize image using B-spline interpolation.
605
606 The function implements separable spline interpolation algorithm described in
607
608 M. Unser, A. Aldroubi, M. Eden, <i>"B-Spline Signal Processing"</i>
609 IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 821-833 (part I),
610 pp. 834-848 (part II), 1993.
611
612 to obtain optimal interpolation quality and speed. You may pass the function
613 a spline of arbitrary order (e.g. <TT>BSpline<ORDER, double></tt> or
614 <TT>CatmullRomSpline<double></tt>). The default is a third order spline
615 which gives a twice continuously differentiable interpolant.
616 The implementation ensures that image values are interpolated rather
617 than smoothed by first calling a recursive (sharpening) prefilter as
618 described in the above paper. Then the actual interpolation is done
619 using \ref resamplingConvolveLine().
620
621 The range of both the input and output images (resp. regions)
622 must be given. The input image must have a size of at
623 least 4x4, the destination of at least 2x2. The scaling factors are then calculated
624 accordingly. If the source image is larger than the destination, it
625 is smoothed (band limited) using a recursive
626 exponential filter. The source value_type (SrcAccessor::value_type) must
627 be a linear algebra, i.e. it must support addition, subtraction,
628 and multiplication (+, -, *), multiplication with a scalar
629 real number and \ref NumericTraits "NumericTraits".
630 The function uses accessors.
631
632 <b> Declarations:</b>
633
634 pass 2D array views:
635 \code
636 namespace vigra {
637 template <class T1, class S1,
638 class T2, class S2,
639 class SPLINE>
640 void
641 resizeImageSplineInterpolation(MultiArrayView<2, T1, S1> const & src,
642 MultiArrayView<2, T2, S2> dest,
643 SPLINE const & spline = BSpline<3, double>());
644 }
645 \endcode
646
647 \deprecatedAPI{resizeImageSplineInterpolation}
648 pass \ref ImageIterators and \ref DataAccessors :
649 \code
650 namespace vigra {
651 template <class SrcImageIterator, class SrcAccessor,
652 class DestImageIterator, class DestAccessor,
653 class SPLINE>
654 void
655 resizeImageSplineInterpolation(
656 SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
657 DestImageIterator id, DestImageIterator idend, DestAccessor da,
658 SPLINE spline = BSpline<3, double>())
659 }
660 \endcode
661 use argument objects in conjunction with \ref ArgumentObjectFactories :
662 \code
663 namespace vigra {
664 template <class SrcImageIterator, class SrcAccessor,
665 class DestImageIterator, class DestAccessor,
666 class SPLINE>
667 void
668 resizeImageSplineInterpolation(
669 triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
670 triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
671 SPLINE spline = BSpline<3, double>())
672 }
673 \endcode
674 \deprecatedEnd
675
676 <b> Usage:</b>
677
678 <b>\#include</b> <vigra/resizeimage.hxx><br>
679 Namespace: vigra
680
681 \code
682 MultiArray<2, unsigned char> src(w, h);
683 MultiArray<2, float> dest(w_new, h_new);
684
685 // use default cubic spline interpolator
686 resizeImageSplineInterpolation(src, dest);
687
688 // use 5th-order spline interpolator
689 resizeImageSplineInterpolation(src, dest, BSpline<5, double>());
690 \endcode
691
692 \deprecatedUsage{resizeImageSplineInterpolation}
693 \code
694 vigra::resizeImageSplineInterpolation(
695 src.upperLeft(), src.lowerRight(), src.accessor(),
696 dest.upperLeft(), dest.lowerRight(), dest.accessor());
697
698 \endcode
699 <b> Required Interface:</b>
700 \code
701 SrcImageIterator src_upperleft, src_lowerright;
702 DestImageIterator dest_upperleft, src_lowerright;
703
704 SrcAccessor src_accessor;
705 DestAccessor dest_accessor;
706
707 NumericTraits<SrcAccessor::value_type>::RealPromote
708 u = src_accessor(src_upperleft),
709 v = src_accessor(src_upperleft, 1);
710 double d;
711
712 u = d * v;
713 u = u + v;
714 u = u - v;
715 u = u * v;
716 u += v;
717 u -= v;
718
719 dest_accessor.set(
720 NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
721 dest_upperleft);
722
723 \endcode
724 \deprecatedEnd
725
726 <b> Preconditions:</b>
727
728 Source and destination must have at least 2 pixels along each axis.
729 */
730 doxygen_overloaded_function(template <...> void resizeImageSplineInterpolation)
731
732 template <class SrcIterator, class SrcAccessor,
733 class DestIterator, class DestAccessor,
734 class SPLINE>
735 void
736 resizeImageSplineInterpolation(
737 SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
738 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc,
739 SPLINE const & spline)
740 {
741
742 int width_old = src_iter_end.x - src_iter.x;
743 int height_old = src_iter_end.y - src_iter.y;
744
745 int width_new = dest_iter_end.x - dest_iter.x;
746 int height_new = dest_iter_end.y - dest_iter.y;
747
748 vigra_precondition((width_old > 1) && (height_old > 1),
749 "resizeImageSplineInterpolation(): "
750 "Source image too small.\n");
751
752 vigra_precondition((width_new > 1) && (height_new > 1),
753 "resizeImageSplineInterpolation(): "
754 "Destination image too small.\n");
755
756 Rational<int> xratio(width_new - 1, width_old - 1);
757 Rational<int> yratio(height_new - 1, height_old - 1);
758 Rational<int> offset(0);
759 resampling_detail::MapTargetToSourceCoordinate xmapCoordinate(xratio, offset);
760 resampling_detail::MapTargetToSourceCoordinate ymapCoordinate(yratio, offset);
761 int xperiod = lcm(xratio.numerator(), xratio.denominator());
762 int yperiod = lcm(yratio.numerator(), yratio.denominator());
763
764 double const scale = 2.0;
765
766 typedef typename SrcAccessor::value_type SRCVT;
767 typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
768 typedef BasicImage<TMPTYPE> TmpImage;
769 typedef typename TmpImage::traverser TmpImageIterator;
770
771 BasicImage<TMPTYPE> tmp(width_old, height_new);
772
773 BasicImage<TMPTYPE> line((height_old > width_old) ? height_old : width_old, 1);
774 typename BasicImage<TMPTYPE>::Accessor tmp_acc = tmp.accessor();
775 ArrayVector<double> const & prefilterCoeffs = spline.prefilterCoefficients();
776
777 int x,y;
778
779 ArrayVector<Kernel1D<double> > kernels(yperiod);
780 createResamplingKernels(spline, ymapCoordinate, kernels);
781
782 typename BasicImage<TMPTYPE>::Iterator y_tmp = tmp.upperLeft();
783 typename TmpImageIterator::row_iterator line_tmp = line.upperLeft().rowIterator();
784
785 for(x=0; x<width_old; ++x, ++src_iter.x, ++y_tmp.x)
786 {
787
788 typename SrcIterator::column_iterator c_src = src_iter.columnIterator();
789 typename TmpImageIterator::column_iterator c_tmp = y_tmp.columnIterator();
790
791 if(prefilterCoeffs.size() == 0)
792 {
793 if(height_new >= height_old)
794 {
795 resamplingConvolveLine(c_src, c_src + height_old, src_acc,
796 c_tmp, c_tmp + height_new, tmp_acc,
797 kernels, ymapCoordinate);
798 }
799 else
800 {
801 recursiveSmoothLine(c_src, c_src + height_old, src_acc,
802 line_tmp, line.accessor(), (double)height_old/height_new/scale);
803 resamplingConvolveLine(line_tmp, line_tmp + height_old, line.accessor(),
804 c_tmp, c_tmp + height_new, tmp_acc,
805 kernels, ymapCoordinate);
806 }
807 }
808 else
809 {
810 recursiveFilterLine(c_src, c_src + height_old, src_acc,
811 line_tmp, line.accessor(),
812 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
813 for(unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
814 {
815 recursiveFilterLine(line_tmp, line_tmp + height_old, line.accessor(),
816 line_tmp, line.accessor(),
817 prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
818 }
819 if(height_new < height_old)
820 {
821 recursiveSmoothLine(line_tmp, line_tmp + height_old, line.accessor(),
822 line_tmp, line.accessor(), (double)height_old/height_new/scale);
823 }
824 resamplingConvolveLine(line_tmp, line_tmp + height_old, line.accessor(),
825 c_tmp, c_tmp + height_new, tmp_acc,
826 kernels, ymapCoordinate);
827 }
828 }
829
830 y_tmp = tmp.upperLeft();
831
832 kernels.resize(xperiod);
833 createResamplingKernels(spline, xmapCoordinate, kernels);
834
835 for(y=0; y < height_new; ++y, ++y_tmp.y, ++dest_iter.y)
836 {
837 typename DestIterator::row_iterator r_dest = dest_iter.rowIterator();
838 typename TmpImageIterator::row_iterator r_tmp = y_tmp.rowIterator();
839
840 if(prefilterCoeffs.size() == 0)
841 {
842 if(width_new >= width_old)
843 {
844 resamplingConvolveLine(r_tmp, r_tmp + width_old, tmp.accessor(),
845 r_dest, r_dest + width_new, dest_acc,
846 kernels, xmapCoordinate);
847 }
848 else
849 {
850 recursiveSmoothLine(r_tmp, r_tmp + width_old, tmp.accessor(),
851 line_tmp, line.accessor(), (double)width_old/width_new/scale);
852 resamplingConvolveLine(line_tmp, line_tmp + width_old, line.accessor(),
853 r_dest, r_dest + width_new, dest_acc,
854 kernels, xmapCoordinate);
855 }
856 }
857 else
858 {
859 recursiveFilterLine(r_tmp, r_tmp + width_old, tmp.accessor(),
860 line_tmp, line.accessor(),
861 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
862 for(unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
863 {
864 recursiveFilterLine(line_tmp, line_tmp + width_old, line.accessor(),
865 line_tmp, line.accessor(),
866 prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
867 }
868 if(width_new < width_old)
869 {
870 recursiveSmoothLine(line_tmp, line_tmp + width_old, line.accessor(),
871 line_tmp, line.accessor(), (double)width_old/width_new/scale);
872 }
873 resamplingConvolveLine(line_tmp, line_tmp + width_old, line.accessor(),
874 r_dest, r_dest + width_new, dest_acc,
875 kernels, xmapCoordinate);
876 }
877 }
878 }
879
880 template <class SrcIterator, class SrcAccessor,
881 class DestIterator, class DestAccessor>
882 void
883 resizeImageSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
884 DestIterator id, DestIterator idend, DestAccessor da)
885 {
886 resizeImageSplineInterpolation(is, iend, sa, id, idend, da, BSpline<3, double>());
887 }
888
889 template <class SrcIterator, class SrcAccessor,
890 class DestIterator, class DestAccessor,
891 class SPLINE>
892 inline void
893 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
894 triple<DestIterator, DestIterator, DestAccessor> dest,
895 SPLINE const & spline)
896 {
897 resizeImageSplineInterpolation(src.first, src.second, src.third,
898 dest.first, dest.second, dest.third, spline);
899 }
900
901 template <class SrcIterator, class SrcAccessor,
902 class DestIterator, class DestAccessor>
903 inline void
904 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
905 triple<DestIterator, DestIterator, DestAccessor> dest)
906 {
907 resizeImageSplineInterpolation(src.first, src.second, src.third,
908 dest.first, dest.second, dest.third);
909 }
910
911 template <class T1, class S1,
912 class T2, class S2,
913 class SPLINE>
914 inline void
915 resizeImageSplineInterpolation(MultiArrayView<2, T1, S1> const & src,
916 MultiArrayView<2, T2, S2> dest,
917 SPLINE const & spline)
918 {
919 resizeImageSplineInterpolation(srcImageRange(src),
920 destImageRange(dest), spline);
921 }
922
923 template <class T1, class S1,
924 class T2, class S2>
925 inline void
926 resizeImageSplineInterpolation(MultiArrayView<2, T1, S1> const & src,
927 MultiArrayView<2, T2, S2> dest)
928 {
929 resizeImageSplineInterpolation(srcImageRange(src),
930 destImageRange(dest));
931 }
932
933 /*****************************************************************/
934 /* */
935 /* resizeImageCatmullRomInterpolation */
936 /* */
937 /*****************************************************************/
938
939 /** \brief Resize image using the Catmull/Rom interpolation function.
940
941 The function calls like \ref resizeImageSplineInterpolation() with
942 \ref vigra::CatmullRomSpline as an interpolation kernel.
943 The interpolated function has one continuous derivative.
944 (See \ref resizeImageSplineInterpolation() for more documentation)
945
946 <b> Declarations:</b>
947
948 pass 2D array views:
949 \code
950 namespace vigra {
951 template <class T1, class S1,
952 class T2, class S2>
953 void
954 resizeImageCatmullRomInterpolation(MultiArrayView<2, T1, S1> const & src,
955 MultiArrayView<2, T2, S2> dest);
956 }
957 \endcode
958
959 \deprecatedAPI{resizeImageCatmullRomInterpolation}
960 pass \ref ImageIterators and \ref DataAccessors :
961 \code
962 namespace vigra {
963 template <class SrcIterator, class SrcAccessor,
964 class DestIterator, class DestAccessor>
965 void
966 resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
967 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
968 }
969 \endcode
970 use argument objects in conjunction with \ref ArgumentObjectFactories :
971 \code
972 namespace vigra {
973 template <class SrcIterator, class SrcAccessor,
974 class DestIterator, class DestAccessor>
975 void
976 resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
977 triple<DestIterator, DestIterator, DestAccessor> dest);
978 }
979 \endcode
980 \deprecatedEnd
981
982 <b>\#include</b> <vigra/resizeimage.hxx><br>
983 Namespace: vigra
984
985 \code
986 MultiArray<2, unsigned char> src(w, h);
987 MultiArray<2, float> dest(w_new, h_new);
988
989 resizeImageCatmullRomInterpolation(src, dest);
990 \endcode
991 */
992 doxygen_overloaded_function(template <...> void resizeImageCatmullRomInterpolation)
993
994 template <class SrcIterator, class SrcAccessor,
995 class DestIterator, class DestAccessor>
996 inline void
997 resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
998 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
999 {
1000 resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
1001 CatmullRomSpline<double>());
1002 }
1003
1004 template <class SrcIterator, class SrcAccessor,
1005 class DestIterator, class DestAccessor>
1006 inline void
1007 resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1008 triple<DestIterator, DestIterator, DestAccessor> dest)
1009 {
1010 resizeImageCatmullRomInterpolation(src.first, src.second, src.third,
1011 dest.first, dest.second, dest.third);
1012 }
1013
1014 template <class T1, class S1,
1015 class T2, class S2>
1016 inline void
1017 resizeImageCatmullRomInterpolation(MultiArrayView<2, T1, S1> const & src,
1018 MultiArrayView<2, T2, S2> dest)
1019 {
1020 resizeImageCatmullRomInterpolation(srcImageRange(src),
1021 destImageRange(dest));
1022 }
1023
1024 /*****************************************************************/
1025 /* */
1026 /* resizeImageCoscotInterpolation */
1027 /* */
1028 /*****************************************************************/
1029
1030 /** \brief Resize image using the Coscot interpolation function.
1031
1032 The function calls \ref resizeImageSplineInterpolation() with
1033 \ref vigra::CoscotFunction as an interpolation kernel.
1034 The interpolated function has one continuous derivative.
1035 (See \ref resizeImageSplineInterpolation() for more documentation)
1036
1037 <b> Declarations:</b>
1038
1039 pass 2D array views:
1040 \code
1041 namespace vigra {
1042 template <class T1, class S1,
1043 class T2, class S2>
1044 void
1045 resizeImageCoscotInterpolation(MultiArrayView<2, T1, S1> const & src,
1046 MultiArrayView<2, T2, S2> dest);
1047 }
1048 \endcode
1049
1050 \deprecatedAPI{resizeImageCoscotInterpolation}
1051 pass \ref ImageIterators and \ref DataAccessors :
1052 \code
1053 namespace vigra {
1054 template <class SrcIterator, class SrcAccessor,
1055 class DestIterator, class DestAccessor>
1056 void
1057 resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
1058 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
1059 }
1060 \endcode
1061 use argument objects in conjunction with \ref ArgumentObjectFactories :
1062 \code
1063 namespace vigra {
1064 template <class SrcIterator, class SrcAccessor,
1065 class DestIterator, class DestAccessor>
1066 void
1067 resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1068 triple<DestIterator, DestIterator, DestAccessor> dest);
1069 }
1070 \endcode
1071 \deprecatedEnd
1072
1073
1074 <b>\#include</b> <vigra/resizeimage.hxx><br>
1075 Namespace: vigra
1076
1077 \code
1078 MultiArray<2, unsigned char> src(w, h);
1079 MultiArray<2, float> dest(w_new, h_new);
1080
1081 resizeImageCoscotInterpolation(src, dest);
1082 \endcode
1083 */
1084 doxygen_overloaded_function(template <...> void resizeImageCoscotInterpolation)
1085
1086 template <class SrcIterator, class SrcAccessor,
1087 class DestIterator, class DestAccessor>
1088 void
1089 resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
1090 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
1091 {
1092 resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
1093 CoscotFunction<double>());
1094 }
1095
1096 template <class SrcIterator, class SrcAccessor,
1097 class DestIterator, class DestAccessor>
1098 inline void
1099 resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1100 triple<DestIterator, DestIterator, DestAccessor> dest)
1101 {
1102 resizeImageCoscotInterpolation(src.first, src.second, src.third,
1103 dest.first, dest.second, dest.third);
1104 }
1105
1106 template <class T1, class S1,
1107 class T2, class S2>
1108 inline void
1109 resizeImageCoscotInterpolation(MultiArrayView<2, T1, S1> const & src,
1110 MultiArrayView<2, T2, S2> dest)
1111 {
1112 resizeImageCoscotInterpolation(srcImageRange(src),
1113 destImageRange(dest));
1114 }
1115
1116 //@}
1117
1118 } // namespace vigra
1119
1120 #endif // VIGRA_RESIZEIMAGE_HXX
vigra::CoscotFunction
Definition: resizeimage.hxx:82
vigra::BasicImage::accessor
Accessor accessor()
Definition: basicimage.hxx:1064
vigra::linalg::sin
linalg::TemporaryMatrix< T > sin(MultiArrayView< 2, T, C > const &v)
vigra::recursiveSmoothLine
void recursiveSmoothLine(...)
Convolves the image with a 1-dimensional exponential filter.
vigra::CoscotFunction::radius
double radius() const
Definition: resizeimage.hxx:121
vigra::resizeImageCoscotInterpolation
void resizeImageCoscotInterpolation(...)
Resize image using the Coscot interpolation function.
vigra::resizeImageSplineInterpolation
void resizeImageSplineInterpolation(...)
Resize image using B-spline interpolation.
vigra
Definition: accessor.hxx:43
vigra::CoscotFunction::argument_type
T argument_type
Definition: resizeimage.hxx:91
vigra::BSpline
Definition: splines.hxx:268
vigra::Rational::denominator
param_type denominator() const
Definition: rational.hxx:273
vigra::CoscotFunction::operator[]
value_type operator[](value_type x) const
Definition: resizeimage.hxx:115
vigra::doxygen_overloaded_function
doxygen_overloaded_function(template<... > void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
vigra::CoscotFunction::operator()
result_type operator()(argument_type x) const
Definition: resizeimage.hxx:103
vigra::BasicImageIterator
Definition: basicimage.hxx:262
vigra::ArrayVector< double >
vigra::resizeImageLinearInterpolation
void resizeImageLinearInterpolation(...)
Resize image using linear interpolation.
vigra::recursiveFilterLine
void recursiveFilterLine(...)
Performs a 1-dimensional recursive convolution of the source signal.
vigra::CoscotFunction::prefilterCoefficients
ArrayVector< double > const & prefilterCoefficients() const
Definition: resizeimage.hxx:132
vigra::resizeImageNoInterpolation
void resizeImageNoInterpolation(...)
Resize image by repeating the nearest pixel values.
vigra::lcm
IntType lcm(IntType n, IntType m)
Definition: rational.hxx:122
utilities.hxx
vigra::CoscotFunction::result_type
T result_type
Definition: resizeimage.hxx:94
vigra::BasicImage
Fundamental class template for images.
Definition: basicimage.hxx:473
vigra::CoscotFunction::value_type
T value_type
Definition: resizeimage.hxx:88
vigra::abs
FFTWComplex< R >::NormType abs(const FFTWComplex< R > &a)
absolute value (= magnitude)
Definition: fftw3.hxx:1002
vigra::MultiArrayView
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:652
vigra::linalg::tan
linalg::TemporaryMatrix< T > tan(MultiArrayView< 2, T, C > const &v)
vigra::ArrayVectorView::size
size_type size() const
Definition: array_vector.hxx:358
vigra::StandardAccessor
Encapsulate access to the values an iterator points to.
Definition: accessor.hxx:133
vigra::linalg::cos
linalg::TemporaryMatrix< T > cos(MultiArrayView< 2, T, C > const &v)
vigra::Rational::numerator
param_type numerator() const
Definition: rational.hxx:269
vigra::resamplingConvolveLine
void resamplingConvolveLine(...)
Performs a 1-dimensional resampling convolution of the source signal using the given set of kernels...
vigra::resizeImageCatmullRomInterpolation
void resizeImageCatmullRomInterpolation(...)
Resize image using the Catmull/Rom interpolation function.
vigra::Rational
Definition: rational.hxx:147
vigra::CoscotFunction::derivativeOrder
unsigned int derivativeOrder() const
Definition: resizeimage.hxx:126
vigra::CatmullRomSpline
Definition: splines.hxx:1309
vigra::BasicImage::upperLeft
traverser upperLeft()
Definition: basicimage.hxx:923

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.11.0