vigra - vigra/resizeimage.hxx Source File

[ 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: \ref resamplingConvolveImage(), \ref resampleImage(), \ref resizeMultiArraySplineInterpolation()
152
153 <b>\#include</b> <vigra/stdimagefunctions.hxx><br>
154 <b>or</b><br>
155 <b>\#include</b> <vigra/resizeimage.hxx><br>
156 */
157 //@{
158
159 /********************************************************/
160 /* */
161 /* resizeLineNoInterpolation */
162 /* */
163 /********************************************************/
164
165 template <class SrcIterator, class SrcAccessor,
166 class DestIterator, class DestAccessor>
167 void
168 resizeLineNoInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
169 DestIterator id, DestIterator idend, DestAccessor ad)
170 {
171 int wold = iend - i1;
172 int wnew = idend - id;
173
174 if(wnew == 1)
175 {
176 ad.set(as(i1), id);
177 return;
178 }
179
180 double dx = (double)(wold - 1) / (wnew - 1);
181 double x = 0.5;
182 for(; id != idend; ++id, x += dx)
183 {
184 int ix = (int)x;
185 ad.set(as(i1, ix), id);
186 }
187 }
188
189 /********************************************************/
190 /* */
191 /* resizeImageNoInterpolation */
192 /* */
193 /********************************************************/
194
195 /** \brief Resize image by repeating the nearest pixel values.
196
197 This algorithm is very fast and does not require any arithmetic on
198 the pixel types.
199
200 The range of both the input and output images (resp. regions) must
201 be given. Both images must have a size of at least 2x2 pixels. The
202 scaling factors are then calculated accordingly. Destination
203 pixels are directly copied from the appropriate source pixels.
204
205 <b> Declarations:</b>
206
207 pass 2D array views:
208 \code
209 namespace vigra {
210 template <class T1, class S1,
211 class T2, class S2>
212 void
213 resizeImageNoInterpolation(MultiArrayView<2, T1, S1> const & src,
214 MultiArrayView<2, T2, S2> dest);
215 }
216 \endcode
217
218 \deprecatedAPI{resizeImageNoInterpolation}
219 pass \ref ImageIterators and \ref DataAccessors :
220 \code
221 namespace vigra {
222 template <class SrcImageIterator, class SrcAccessor,
223 class DestImageIterator, class DestAccessor>
224 void
225 resizeImageNoInterpolation(
226 SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
227 DestImageIterator id, DestImageIterator idend, DestAccessor da)
228 }
229 \endcode
230 use argument objects in conjunction with \ref ArgumentObjectFactories :
231 \code
232 namespace vigra {
233 template <class SrcImageIterator, class SrcAccessor,
234 class DestImageIterator, class DestAccessor>
235 void
236 resizeImageNoInterpolation(
237 triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
238 triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
239 }
240 \endcode
241 \deprecatedEnd
242
243 <b> Usage:</b>
244
245 <b>\#include</b> <vigra/resizeimage.hxx><br>
246 Namespace: vigra
247
248 \code
249 MultiArray<2, unsigned char> src(w, h);
250 MultiArray<2, float> dest(w_new, h_new);
251
252 resizeImageNoInterpolation(src, dest);
253 \endcode
254
255 \deprecatedUsage{resizeImageNoInterpolation}
256 \code
257 vigra::resizeImageNoInterpolation(
258 src.upperLeft(), src.lowerRight(), src.accessor(),
259 dest.upperLeft(), dest.lowerRight(), dest.accessor());
260
261 \endcode
262 <b> Required Interface:</b>
263 \code
264 SrcImageIterator src_upperleft, src_lowerright;
265 DestImageIterator dest_upperleft, src_lowerright;
266
267 SrcAccessor src_accessor;
268 DestAccessor dest_accessor;
269
270 dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
271
272 \endcode
273 \deprecatedEnd
274
275 <b> Preconditions:</b>
276
277 Source and destination must have at least 2 pixels along each axis.
278 */
279 doxygen_overloaded_function(template <...> void resizeImageNoInterpolation)
280
281 template <class SrcIterator, class SrcAccessor,
282 class DestIterator, class DestAccessor>
283 void
284 resizeImageNoInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
285 DestIterator id, DestIterator idend, DestAccessor da)
286 {
287 int w = iend.x - is.x;
288 int h = iend.y - is.y;
289
290 int wnew = idend.x - id.x;
291 int hnew = idend.y - id.y;
292
293 vigra_precondition((w > 1) && (h > 1),
294 "resizeImageNoInterpolation(): "
295 "Source image too small.\n");
296 vigra_precondition((wnew > 1) && (hnew > 1),
297 "resizeImageNoInterpolation(): "
298 "Destination image too small.\n");
299
300 typedef BasicImage<typename SrcAccessor::value_type> TmpImage;
301 typedef typename TmpImage::traverser TmpImageIterator;
302
303 TmpImage tmp(w, hnew);
304
305 TmpImageIterator yt = tmp.upperLeft();
306
307 for(int x=0; x<w; ++x, ++is.x, ++yt.x)
308 {
309 typename SrcIterator::column_iterator c1 = is.columnIterator();
310 typename TmpImageIterator::column_iterator ct = yt.columnIterator();
311
312 resizeLineNoInterpolation(c1, c1 + h, sa, ct, ct + hnew, tmp.accessor());
313 }
314
315 yt = tmp.upperLeft();
316
317 for(int y=0; y < hnew; ++y, ++yt.y, ++id.y)
318 {
319 typename DestIterator::row_iterator rd = id.rowIterator();
320 typename TmpImageIterator::row_iterator rt = yt.rowIterator();
321
322 resizeLineNoInterpolation(rt, rt + w, tmp.accessor(), rd, rd + wnew, da);
323 }
324 }
325
326 template <class SrcIterator, class SrcAccessor,
327 class DestIterator, class DestAccessor>
328 inline void
329 resizeImageNoInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
330 triple<DestIterator, DestIterator, DestAccessor> dest)
331 {
332 resizeImageNoInterpolation(src.first, src.second, src.third,
333 dest.first, dest.second, dest.third);
334 }
335
336 template <class T1, class S1,
337 class T2, class S2>
338 inline void
339 resizeImageNoInterpolation(MultiArrayView<2, T1, S1> const & src,
340 MultiArrayView<2, T2, S2> dest)
341 {
342 resizeImageNoInterpolation(srcImageRange(src),
343 destImageRange(dest));
344 }
345
346 /********************************************************/
347 /* */
348 /* resizeLineLinearInterpolation */
349 /* */
350 /********************************************************/
351
352 template <class SrcIterator, class SrcAccessor,
353 class DestIterator, class DestAccessor>
354 void
355 resizeLineLinearInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
356 DestIterator id, DestIterator idend, DestAccessor ad)
357 {
358 int wold = iend - i1;
359 int wnew = idend - id;
360
361 if((wold <= 1) || (wnew <= 1)) return; // oder error ?
362
363 typedef
364 NumericTraits<typename DestAccessor::value_type> DestTraits;
365 typedef typename DestTraits::RealPromote RealPromote;
366
367 ad.set(DestTraits::fromRealPromote(as(i1)), id);
368 ++id;
369
370 --iend, --idend;
371 ad.set(DestTraits::fromRealPromote(as(iend)), idend);
372
373 double dx = (double)(wold - 1) / (wnew - 1);
374 double x = dx;
375
376 for(; id != idend; ++id, x += dx)
377 {
378 if(x >= 1.0)
379 {
380 int xx = (int)x;
381 i1 += xx;
382 x -= (double)xx;
383 }
384 double x1 = 1.0 - x;
385
386 ad.set(DestTraits::fromRealPromote(RealPromote(x1 * as(i1) + x * as(i1, 1))), id);
387 }
388 }
389
390 /********************************************************/
391 /* */
392 /* resizeImageLinearInterpolation */
393 /* */
394 /********************************************************/
395
396 /** \brief Resize image using linear interpolation.
397
398 The function uses the standard separable bilinear interpolation algorithm to
399 obtain a good compromise between quality and speed.
400
401 The range must of both the input and output images (resp. regions)
402 must be given. Both images must have a size of at
403 least 2x2. The scaling factors are then calculated
404 accordingly. If the source image is larger than the destination, it
405 is smoothed (band limited) using a recursive
406 exponential filter. The source value_type (SrcAccessor::value_type) must
407 be a linear space, i.e. it must support addition, multiplication
408 with a scalar real number and \ref NumericTraits "NumericTraits".
409
410 <b> Declarations:</b>
411
412 pass 2D array views:
413 \code
414 namespace vigra {
415 template <class T1, class S1,
416 class T2, class S2>
417 void
418 resizeImageLinearInterpolation(MultiArrayView<2, T1, S1> const & src,
419 MultiArrayView<2, T2, S2> dest);
420 }
421 \endcode
422
423 \deprecatedAPI{resizeImageLinearInterpolation}
424 pass \ref ImageIterators and \ref DataAccessors :
425 \code
426 namespace vigra {
427 template <class SrcImageIterator, class SrcAccessor,
428 class DestImageIterator, class DestAccessor>
429 void
430 resizeImageLinearInterpolation(
431 SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
432 DestImageIterator id, DestImageIterator idend, DestAccessor da)
433 }
434 \endcode
435 use argument objects in conjunction with \ref ArgumentObjectFactories :
436 \code
437 namespace vigra {
438 template <class SrcImageIterator, class SrcAccessor,
439 class DestImageIterator, class DestAccessor>
440 void
441 resizeImageLinearInterpolation(
442 triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
443 triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
444 }
445 \endcode
446 \deprecatedEnd
447
448 <b> Usage:</b>
449
450 <b>\#include</b> <vigra/resizeimage.hxx><br>
451 Namespace: vigra
452
453 \code
454 MultiArray<2, unsigned char> src(w, h);
455 MultiArray<2, float> dest(w_new, h_new);
456
457 resizeImageLinearInterpolation(src, dest);
458 \endcode
459
460 \deprecatedUsage{resizeImageLinearInterpolation}
461 \code
462 vigra::resizeImageLinearInterpolation(
463 src.upperLeft(), src.lowerRight(), src.accessor(),
464 dest.upperLeft(), dest.lowerRight(), dest.accessor());
465
466 \endcode
467 <b> Required Interface:</b>
468 \code
469 SrcImageIterator src_upperleft, src_lowerright;
470 DestImageIterator dest_upperleft, src_lowerright;
471
472 SrcAccessor src_accessor;
473 DestAccessor dest_accessor;
474
475 NumericTraits<SrcAccessor::value_type>::RealPromote
476 u = src_accessor(src_upperleft),
477 v = src_accessor(src_upperleft, 1);
478 double d;
479
480 u = d * v;
481 u = u + v;
482
483 dest_accessor.set(
484 NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
485 dest_upperleft);
486
487 \endcode
488 \deprecatedEnd
489
490 <b> Preconditions:</b>
491
492 Source and destination must have at least 2 pixels along each axis.
493 */
494 doxygen_overloaded_function(template <...> void resizeImageLinearInterpolation)
495
496 template <class SrcIterator, class SrcAccessor,
497 class DestIterator, class DestAccessor>
498 void
499 resizeImageLinearInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
500 DestIterator id, DestIterator idend, DestAccessor da)
501 {
502 int w = iend.x - is.x;
503 int h = iend.y - is.y;
504
505 int wnew = idend.x - id.x;
506 int hnew = idend.y - id.y;
507
508 vigra_precondition((w > 1) && (h > 1),
509 "resizeImageLinearInterpolation(): "
510 "Source image too small.\n");
511 vigra_precondition((wnew > 1) && (hnew > 1),
512 "resizeImageLinearInterpolation(): "
513 "Destination image too small.\n");
514
515 double const scale = 2.0;
516
517 typedef typename SrcAccessor::value_type SRCVT;
518 typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
519 typedef BasicImage<TMPTYPE> TmpImage;
520 typedef typename TmpImage::traverser TmpImageIterator;
521
522 BasicImage<TMPTYPE> tmp(w, hnew);
523 BasicImage<TMPTYPE> line((h > w) ? h : w, 1);
524
525 int x,y;
526
527 typename BasicImage<TMPTYPE>::Iterator yt = tmp.upperLeft();
528 typename TmpImageIterator::row_iterator lt = line.upperLeft().rowIterator();
529
530 for(x=0; x<w; ++x, ++is.x, ++yt.x)
531 {
532 typename SrcIterator::column_iterator c1 = is.columnIterator();
533 typename TmpImageIterator::column_iterator ct = yt.columnIterator();
534
535 if(hnew < h)
536 {
537 recursiveSmoothLine(c1, c1 + h, sa,
538 lt, line.accessor(), (double)h/hnew/scale);
539
540 resizeLineLinearInterpolation(lt, lt + h, line.accessor(),
541 ct, ct + hnew, tmp.accessor());
542 }
543 else
544 {
545 resizeLineLinearInterpolation(c1, c1 + h, sa,
546 ct, ct + hnew, tmp.accessor());
547 }
548 }
549
550 yt = tmp.upperLeft();
551
552 for(y=0; y < hnew; ++y, ++yt.y, ++id.y)
553 {
554 typename DestIterator::row_iterator rd = id.rowIterator();
555 typename TmpImageIterator::row_iterator rt = yt.rowIterator();
556
557 if(wnew < w)
558 {
559 recursiveSmoothLine(rt, rt + w, tmp.accessor(),
560 lt, line.accessor(), (double)w/wnew/scale);
561
562 resizeLineLinearInterpolation(lt, lt + w, line.accessor(),
563 rd, rd + wnew, da);
564 }
565 else
566 {
567 resizeLineLinearInterpolation(rt, rt + w, tmp.accessor(),
568 rd, rd + wnew, da);
569 }
570 }
571 }
572
573 template <class SrcIterator, class SrcAccessor,
574 class DestIterator, class DestAccessor>
575 inline void
576 resizeImageLinearInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
577 triple<DestIterator, DestIterator, DestAccessor> dest)
578 {
579 resizeImageLinearInterpolation(src.first, src.second, src.third,
580 dest.first, dest.second, dest.third);
581 }
582
583 template <class T1, class S1,
584 class T2, class S2>
585 inline void
586 resizeImageLinearInterpolation(MultiArrayView<2, T1, S1> const & src,
587 MultiArrayView<2, T2, S2> dest)
588 {
589 resizeImageLinearInterpolation(srcImageRange(src),
590 destImageRange(dest));
591 }
592
593 /***************************************************************/
594 /* */
595 /* resizeImageSplineInterpolation */
596 /* */
597 /***************************************************************/
598
599 /** \brief Resize image using B-spline interpolation.
600
601 The function implements separable spline interpolation algorithm described in
602
603 M. Unser, A. Aldroubi, M. Eden, <i>"B-Spline Signal Processing"</i>
604 IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 821-833 (part I),
605 pp. 834-848 (part II), 1993.
606
607 to obtain optimal interpolation quality and speed. You may pass the function
608 a spline of arbitrary order (e.g. <TT>BSpline<ORDER, double></tt> or
609 <TT>CatmullRomSpline<double></tt>). The default is a third order spline
610 which gives a twice continuously differentiable interpolant.
611 The implementation ensures that image values are interpolated rather
612 than smoothed by first calling a recursive (sharpening) prefilter as
613 described in the above paper. Then the actual interpolation is done
614 using \ref resamplingConvolveLine().
615
616 The range of both the input and output images (resp. regions)
617 must be given. The input image must have a size of at
618 least 4x4, the destination of at least 2x2. The scaling factors are then calculated
619 accordingly. If the source image is larger than the destination, it
620 is smoothed (band limited) using a recursive
621 exponential filter. The source value_type (SrcAccessor::value_type) must
622 be a linear algebra, i.e. it must support addition, subtraction,
623 and multiplication (+, -, *), multiplication with a scalar
624 real number and \ref NumericTraits "NumericTraits".
625 The function uses accessors.
626
627 <b> Declarations:</b>
628
629 pass 2D array views:
630 \code
631 namespace vigra {
632 template <class T1, class S1,
633 class T2, class S2,
634 class SPLINE>
635 void
636 resizeImageSplineInterpolation(MultiArrayView<2, T1, S1> const & src,
637 MultiArrayView<2, T2, S2> dest,
638 SPLINE const & spline = BSpline<3, double>());
639 }
640 \endcode
641
642 \deprecatedAPI{resizeImageSplineInterpolation}
643 pass \ref ImageIterators and \ref DataAccessors :
644 \code
645 namespace vigra {
646 template <class SrcImageIterator, class SrcAccessor,
647 class DestImageIterator, class DestAccessor,
648 class SPLINE>
649 void
650 resizeImageSplineInterpolation(
651 SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
652 DestImageIterator id, DestImageIterator idend, DestAccessor da,
653 SPLINE spline = BSpline<3, double>())
654 }
655 \endcode
656 use argument objects in conjunction with \ref ArgumentObjectFactories :
657 \code
658 namespace vigra {
659 template <class SrcImageIterator, class SrcAccessor,
660 class DestImageIterator, class DestAccessor,
661 class SPLINE>
662 void
663 resizeImageSplineInterpolation(
664 triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
665 triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
666 SPLINE spline = BSpline<3, double>())
667 }
668 \endcode
669 \deprecatedEnd
670
671 <b> Usage:</b>
672
673 <b>\#include</b> <vigra/resizeimage.hxx><br>
674 Namespace: vigra
675
676 \code
677 MultiArray<2, unsigned char> src(w, h);
678 MultiArray<2, float> dest(w_new, h_new);
679
680 // use default cubic spline interpolator
681 resizeImageSplineInterpolation(src, dest);
682
683 // use 5th-order spline interpolator
684 resizeImageSplineInterpolation(src, dest, BSpline<5, double>());
685 \endcode
686
687 \deprecatedUsage{resizeImageSplineInterpolation}
688 \code
689 vigra::resizeImageSplineInterpolation(
690 src.upperLeft(), src.lowerRight(), src.accessor(),
691 dest.upperLeft(), dest.lowerRight(), dest.accessor());
692
693 \endcode
694 <b> Required Interface:</b>
695 \code
696 SrcImageIterator src_upperleft, src_lowerright;
697 DestImageIterator dest_upperleft, src_lowerright;
698
699 SrcAccessor src_accessor;
700 DestAccessor dest_accessor;
701
702 NumericTraits<SrcAccessor::value_type>::RealPromote
703 u = src_accessor(src_upperleft),
704 v = src_accessor(src_upperleft, 1);
705 double d;
706
707 u = d * v;
708 u = u + v;
709 u = u - v;
710 u = u * v;
711 u += v;
712 u -= v;
713
714 dest_accessor.set(
715 NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
716 dest_upperleft);
717
718 \endcode
719 \deprecatedEnd
720
721 <b> Preconditions:</b>
722
723 Source and destination must have at least 2 pixels along each axis.
724 */
725 doxygen_overloaded_function(template <...> void resizeImageSplineInterpolation)
726
727 template <class SrcIterator, class SrcAccessor,
728 class DestIterator, class DestAccessor,
729 class SPLINE>
730 void
731 resizeImageSplineInterpolation(
732 SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
733 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc,
734 SPLINE const & spline)
735 {
736
737 int width_old = src_iter_end.x - src_iter.x;
738 int height_old = src_iter_end.y - src_iter.y;
739
740 int width_new = dest_iter_end.x - dest_iter.x;
741 int height_new = dest_iter_end.y - dest_iter.y;
742
743 vigra_precondition((width_old > 1) && (height_old > 1),
744 "resizeImageSplineInterpolation(): "
745 "Source image too small.\n");
746
747 vigra_precondition((width_new > 1) && (height_new > 1),
748 "resizeImageSplineInterpolation(): "
749 "Destination image too small.\n");
750
751 Rational<int> xratio(width_new - 1, width_old - 1);
752 Rational<int> yratio(height_new - 1, height_old - 1);
753 Rational<int> offset(0);
754 resampling_detail::MapTargetToSourceCoordinate xmapCoordinate(xratio, offset);
755 resampling_detail::MapTargetToSourceCoordinate ymapCoordinate(yratio, offset);
756 int xperiod = lcm(xratio.numerator(), xratio.denominator());
757 int yperiod = lcm(yratio.numerator(), yratio.denominator());
758
759 double const scale = 2.0;
760
761 typedef typename SrcAccessor::value_type SRCVT;
762 typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
763 typedef BasicImage<TMPTYPE> TmpImage;
764 typedef typename TmpImage::traverser TmpImageIterator;
765
766 BasicImage<TMPTYPE> tmp(width_old, height_new);
767
768 BasicImage<TMPTYPE> line((height_old > width_old) ? height_old : width_old, 1);
769 typename BasicImage<TMPTYPE>::Accessor tmp_acc = tmp.accessor();
770 ArrayVector<double> const & prefilterCoeffs = spline.prefilterCoefficients();
771
772 int x,y;
773
774 ArrayVector<Kernel1D<double> > kernels(yperiod);
775 createResamplingKernels(spline, ymapCoordinate, kernels);
776
777 typename BasicImage<TMPTYPE>::Iterator y_tmp = tmp.upperLeft();
778 typename TmpImageIterator::row_iterator line_tmp = line.upperLeft().rowIterator();
779
780 for(x=0; x<width_old; ++x, ++src_iter.x, ++y_tmp.x)
781 {
782
783 typename SrcIterator::column_iterator c_src = src_iter.columnIterator();
784 typename TmpImageIterator::column_iterator c_tmp = y_tmp.columnIterator();
785
786 if(prefilterCoeffs.size() == 0)
787 {
788 if(height_new >= height_old)
789 {
790 resamplingConvolveLine(c_src, c_src + height_old, src_acc,
791 c_tmp, c_tmp + height_new, tmp_acc,
792 kernels, ymapCoordinate);
793 }
794 else
795 {
796 recursiveSmoothLine(c_src, c_src + height_old, src_acc,
797 line_tmp, line.accessor(), (double)height_old/height_new/scale);
798 resamplingConvolveLine(line_tmp, line_tmp + height_old, line.accessor(),
799 c_tmp, c_tmp + height_new, tmp_acc,
800 kernels, ymapCoordinate);
801 }
802 }
803 else
804 {
805 recursiveFilterLine(c_src, c_src + height_old, src_acc,
806 line_tmp, line.accessor(),
807 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
808 for(unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
809 {
810 recursiveFilterLine(line_tmp, line_tmp + height_old, line.accessor(),
811 line_tmp, line.accessor(),
812 prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
813 }
814 if(height_new < height_old)
815 {
816 recursiveSmoothLine(line_tmp, line_tmp + height_old, line.accessor(),
817 line_tmp, line.accessor(), (double)height_old/height_new/scale);
818 }
819 resamplingConvolveLine(line_tmp, line_tmp + height_old, line.accessor(),
820 c_tmp, c_tmp + height_new, tmp_acc,
821 kernels, ymapCoordinate);
822 }
823 }
824
825 y_tmp = tmp.upperLeft();
826
827 kernels.resize(xperiod);
828 createResamplingKernels(spline, xmapCoordinate, kernels);
829
830 for(y=0; y < height_new; ++y, ++y_tmp.y, ++dest_iter.y)
831 {
832 typename DestIterator::row_iterator r_dest = dest_iter.rowIterator();
833 typename TmpImageIterator::row_iterator r_tmp = y_tmp.rowIterator();
834
835 if(prefilterCoeffs.size() == 0)
836 {
837 if(width_new >= width_old)
838 {
839 resamplingConvolveLine(r_tmp, r_tmp + width_old, tmp.accessor(),
840 r_dest, r_dest + width_new, dest_acc,
841 kernels, xmapCoordinate);
842 }
843 else
844 {
845 recursiveSmoothLine(r_tmp, r_tmp + width_old, tmp.accessor(),
846 line_tmp, line.accessor(), (double)width_old/width_new/scale);
847 resamplingConvolveLine(line_tmp, line_tmp + width_old, line.accessor(),
848 r_dest, r_dest + width_new, dest_acc,
849 kernels, xmapCoordinate);
850 }
851 }
852 else
853 {
854 recursiveFilterLine(r_tmp, r_tmp + width_old, tmp.accessor(),
855 line_tmp, line.accessor(),
856 prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
857 for(unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
858 {
859 recursiveFilterLine(line_tmp, line_tmp + width_old, line.accessor(),
860 line_tmp, line.accessor(),
861 prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
862 }
863 if(width_new < width_old)
864 {
865 recursiveSmoothLine(line_tmp, line_tmp + width_old, line.accessor(),
866 line_tmp, line.accessor(), (double)width_old/width_new/scale);
867 }
868 resamplingConvolveLine(line_tmp, line_tmp + width_old, line.accessor(),
869 r_dest, r_dest + width_new, dest_acc,
870 kernels, xmapCoordinate);
871 }
872 }
873 }
874
875 template <class SrcIterator, class SrcAccessor,
876 class DestIterator, class DestAccessor>
877 void
878 resizeImageSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
879 DestIterator id, DestIterator idend, DestAccessor da)
880 {
881 resizeImageSplineInterpolation(is, iend, sa, id, idend, da, BSpline<3, double>());
882 }
883
884 template <class SrcIterator, class SrcAccessor,
885 class DestIterator, class DestAccessor,
886 class SPLINE>
887 inline void
888 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
889 triple<DestIterator, DestIterator, DestAccessor> dest,
890 SPLINE const & spline)
891 {
892 resizeImageSplineInterpolation(src.first, src.second, src.third,
893 dest.first, dest.second, dest.third, spline);
894 }
895
896 template <class SrcIterator, class SrcAccessor,
897 class DestIterator, class DestAccessor>
898 inline void
899 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
900 triple<DestIterator, DestIterator, DestAccessor> dest)
901 {
902 resizeImageSplineInterpolation(src.first, src.second, src.third,
903 dest.first, dest.second, dest.third);
904 }
905
906 template <class T1, class S1,
907 class T2, class S2,
908 class SPLINE>
909 inline void
910 resizeImageSplineInterpolation(MultiArrayView<2, T1, S1> const & src,
911 MultiArrayView<2, T2, S2> dest,
912 SPLINE const & spline)
913 {
914 resizeImageSplineInterpolation(srcImageRange(src),
915 destImageRange(dest), spline);
916 }
917
918 template <class T1, class S1,
919 class T2, class S2>
920 inline void
921 resizeImageSplineInterpolation(MultiArrayView<2, T1, S1> const & src,
922 MultiArrayView<2, T2, S2> dest)
923 {
924 resizeImageSplineInterpolation(srcImageRange(src),
925 destImageRange(dest));
926 }
927
928 /*****************************************************************/
929 /* */
930 /* resizeImageCatmullRomInterpolation */
931 /* */
932 /*****************************************************************/
933
934 /** \brief Resize image using the Catmull/Rom interpolation function.
935
936 The function calls like \ref resizeImageSplineInterpolation() with
937 \ref vigra::CatmullRomSpline as an interpolation kernel.
938 The interpolated function has one continuous derivative.
939 (See \ref resizeImageSplineInterpolation() for more documentation)
940
941 <b> Declarations:</b>
942
943 pass 2D array views:
944 \code
945 namespace vigra {
946 template <class T1, class S1,
947 class T2, class S2>
948 void
949 resizeImageCatmullRomInterpolation(MultiArrayView<2, T1, S1> const & src,
950 MultiArrayView<2, T2, S2> dest);
951 }
952 \endcode
953
954 \deprecatedAPI{resizeImageCatmullRomInterpolation}
955 pass \ref ImageIterators and \ref DataAccessors :
956 \code
957 namespace vigra {
958 template <class SrcIterator, class SrcAccessor,
959 class DestIterator, class DestAccessor>
960 void
961 resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
962 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
963 }
964 \endcode
965 use argument objects in conjunction with \ref ArgumentObjectFactories :
966 \code
967 namespace vigra {
968 template <class SrcIterator, class SrcAccessor,
969 class DestIterator, class DestAccessor>
970 void
971 resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
972 triple<DestIterator, DestIterator, DestAccessor> dest);
973 }
974 \endcode
975 \deprecatedEnd
976
977 <b>\#include</b> <vigra/resizeimage.hxx><br>
978 Namespace: vigra
979
980 \code
981 MultiArray<2, unsigned char> src(w, h);
982 MultiArray<2, float> dest(w_new, h_new);
983
984 resizeImageCatmullRomInterpolation(src, dest);
985 \endcode
986 */
987 doxygen_overloaded_function(template <...> void resizeImageCatmullRomInterpolation)
988
989 template <class SrcIterator, class SrcAccessor,
990 class DestIterator, class DestAccessor>
991 inline void
992 resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
993 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
994 {
995 resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
996 CatmullRomSpline<double>());
997 }
998
999 template <class SrcIterator, class SrcAccessor,
1000 class DestIterator, class DestAccessor>
1001 inline void
1002 resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1003 triple<DestIterator, DestIterator, DestAccessor> dest)
1004 {
1005 resizeImageCatmullRomInterpolation(src.first, src.second, src.third,
1006 dest.first, dest.second, dest.third);
1007 }
1008
1009 template <class T1, class S1,
1010 class T2, class S2>
1011 inline void
1012 resizeImageCatmullRomInterpolation(MultiArrayView<2, T1, S1> const & src,
1013 MultiArrayView<2, T2, S2> dest)
1014 {
1015 resizeImageCatmullRomInterpolation(srcImageRange(src),
1016 destImageRange(dest));
1017 }
1018
1019 /*****************************************************************/
1020 /* */
1021 /* resizeImageCoscotInterpolation */
1022 /* */
1023 /*****************************************************************/
1024
1025 /** \brief Resize image using the Coscot interpolation function.
1026
1027 The function calls \ref resizeImageSplineInterpolation() with
1028 \ref vigra::CoscotFunction as an interpolation kernel.
1029 The interpolated function has one continuous derivative.
1030 (See \ref resizeImageSplineInterpolation() for more documentation)
1031
1032 <b> Declarations:</b>
1033
1034 pass 2D array views:
1035 \code
1036 namespace vigra {
1037 template <class T1, class S1,
1038 class T2, class S2>
1039 void
1040 resizeImageCoscotInterpolation(MultiArrayView<2, T1, S1> const & src,
1041 MultiArrayView<2, T2, S2> dest);
1042 }
1043 \endcode
1044
1045 \deprecatedAPI{resizeImageCoscotInterpolation}
1046 pass \ref ImageIterators and \ref DataAccessors :
1047 \code
1048 namespace vigra {
1049 template <class SrcIterator, class SrcAccessor,
1050 class DestIterator, class DestAccessor>
1051 void
1052 resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
1053 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
1054 }
1055 \endcode
1056 use argument objects in conjunction with \ref ArgumentObjectFactories :
1057 \code
1058 namespace vigra {
1059 template <class SrcIterator, class SrcAccessor,
1060 class DestIterator, class DestAccessor>
1061 void
1062 resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1063 triple<DestIterator, DestIterator, DestAccessor> dest);
1064 }
1065 \endcode
1066 \deprecatedEnd
1067
1068
1069 <b>\#include</b> <vigra/resizeimage.hxx><br>
1070 Namespace: vigra
1071
1072 \code
1073 MultiArray<2, unsigned char> src(w, h);
1074 MultiArray<2, float> dest(w_new, h_new);
1075
1076 resizeImageCoscotInterpolation(src, dest);
1077 \endcode
1078 */
1079 doxygen_overloaded_function(template <...> void resizeImageCoscotInterpolation)
1080
1081 template <class SrcIterator, class SrcAccessor,
1082 class DestIterator, class DestAccessor>
1083 void
1084 resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
1085 DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
1086 {
1087 resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
1088 CoscotFunction<double>());
1089 }
1090
1091 template <class SrcIterator, class SrcAccessor,
1092 class DestIterator, class DestAccessor>
1093 inline void
1094 resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1095 triple<DestIterator, DestIterator, DestAccessor> dest)
1096 {
1097 resizeImageCoscotInterpolation(src.first, src.second, src.third,
1098 dest.first, dest.second, dest.third);
1099 }
1100
1101 template <class T1, class S1,
1102 class T2, class S2>
1103 inline void
1104 resizeImageCoscotInterpolation(MultiArrayView<2, T1, S1> const & src,
1105 MultiArrayView<2, T2, S2> dest)
1106 {
1107 resizeImageCoscotInterpolation(srcImageRange(src),
1108 destImageRange(dest));
1109 }
1110
1111 //@}
1112
1113 } // namespace vigra
1114
1115 #endif // VIGRA_RESIZEIMAGE_HXX

© 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.10.0 (Thu Jan 8 2015)