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