[ 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 
49 namespace vigra {
50 
51 /*****************************************************************/
52 /* */
53 /* CoscotFunction */
54 /* */
55 /*****************************************************************/
56 
57 /*! The Coscot interpolation function.
58 
59  Implements the Coscot interpolation function proposed by Maria Magnusson Seger
60  (maria@isy.liu.se) in the context of tomographic reconstruction. It provides a fast
61  transition between the pass- and stop-bands and minimal ripple outside the transition
62  region. Both properties are important for this application and can be tuned by the parameters
63  <i>m</i> and <i>h</i> (with defaults 3 and 0.5). The function is defined by
64 
65  \f[ f_{m,h}(x) = \left\{ \begin{array}{ll}
66  \frac{1}{2m}\sin(\pi x)\cot(\pi x / (2 m))(h + (1-h)\cos(\pi x/m)) & |x| \leq m \\
67  0 & \mbox{otherwise}
68  \end{array}\right.
69  \f]
70 
71  It can be used as a functor, and as a kernel for
72  \ref resamplingConvolveImage() to create a differentiable interpolant
73  of an image.
74 
75  <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
76  Namespace: vigra
77 
78  \ingroup MathFunctions
79 */
80 template <class T>
82 {
83  public:
84 
85  /** the kernel's value type
86  */
87  typedef T value_type;
88  /** the unary functor's argument type
89  */
90  typedef T argument_type;
91  /** the splines polynomial order
92  */
93  typedef T result_type;
94 
95  CoscotFunction(unsigned int m = 3, double h = 0.5)
96  : m_(m),
97  h_(h)
98  {}
99 
100  /** function (functor) call
101  */
103  {
104  return x == 0.0 ?
105  1.0
106  : abs(x) < m_ ?
107  VIGRA_CSTD::sin(M_PI*x) / VIGRA_CSTD::tan(M_PI * x / 2.0 / m_) *
108  (h_ + (1.0 - h_) * VIGRA_CSTD::cos(M_PI * x / m_)) / 2.0 / m_
109  : 0.0;
110  }
111 
112  /** index operator -- same as operator()
113  */
115  { return operator()(x); }
116 
117  /** Radius of the function's support.
118  Needed for \ref resamplingConvolveImage(), equals m.
119  */
120  double radius() const
121  { return m_; }
122 
123  /** Derivative order of the function: always 0.
124  */
125  unsigned int derivativeOrder() const
126  { return 0; }
127 
128  /** Prefilter coefficients for compatibility with \ref vigra::BSpline.
129  (array has zero length, since prefiltering is not necessary).
130  */
132  {
133  static ArrayVector<double> b;
134  return b;
135  }
136 
137  protected:
138 
139  unsigned int m_;
140  double h_;
141 };
142 
143 /** \addtogroup GeometricTransformations Geometric Transformations
144  Zoom up and down by repeating pixels, or using various interpolation schemes.
145 
146  See also: \ref resamplingConvolveImage(), \ref resampleImage(), \ref resizeMultiArraySplineInterpolation()
147 
148  <b>\#include</b> <<a href="stdimagefunctions_8hxx-source.html">vigra/stdimagefunctions.hxx</a>><br>
149  <b>or</b><br>
150  <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
151 */
152 //@{
153 
154 /********************************************************/
155 /* */
156 /* resizeLineNoInterpolation */
157 /* */
158 /********************************************************/
159 
160 template <class SrcIterator, class SrcAccessor,
161  class DestIterator, class DestAccessor>
162 void
163 resizeLineNoInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
164  DestIterator id, DestIterator idend, DestAccessor ad)
165 {
166  int wold = iend - i1;
167  int wnew = idend - id;
168 
169  if(wnew == 1)
170  {
171  ad.set(as(i1), id);
172  return;
173  }
174 
175  double dx = (double)(wold - 1) / (wnew - 1);
176  double x = 0.5;
177  for(; id != idend; ++id, x += dx)
178  {
179  int ix = (int)x;
180  ad.set(as(i1, ix), id);
181  }
182 }
183 
184 /********************************************************/
185 /* */
186 /* resizeImageNoInterpolation */
187 /* */
188 /********************************************************/
189 
190 /** \brief Resize image by repeating the nearest pixel values.
191 
192  This algorithm is very fast and does not require any arithmetic on
193  the pixel types.
194 
195  The range of both the input and output images (resp. regions) must
196  be given. Both images must have a size of at least 2x2 pixels. The
197  scaling factors are then calculated accordingly. Destination
198  pixels are directly copied from the appropriate source pixels.
199 
200  The function uses accessors.
201 
202  <b> Declarations:</b>
203 
204  pass arguments explicitly:
205  \code
206  namespace vigra {
207  template <class SrcImageIterator, class SrcAccessor,
208  class DestImageIterator, class DestAccessor>
209  void
210  resizeImageNoInterpolation(
211  SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
212  DestImageIterator id, DestImageIterator idend, DestAccessor da)
213  }
214  \endcode
215 
216 
217  use argument objects in conjunction with \ref ArgumentObjectFactories :
218  \code
219  namespace vigra {
220  template <class SrcImageIterator, class SrcAccessor,
221  class DestImageIterator, class DestAccessor>
222  void
223  resizeImageNoInterpolation(
224  triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
225  triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
226  }
227  \endcode
228 
229  <b> Usage:</b>
230 
231  <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
232  Namespace: vigra
233 
234  \code
235  vigra::resizeImageNoInterpolation(
236  src.upperLeft(), src.lowerRight(), src.accessor(),
237  dest.upperLeft(), dest.lowerRight(), dest.accessor());
238 
239  \endcode
240 
241  <b> Required Interface:</b>
242 
243  \code
244  SrcImageIterator src_upperleft, src_lowerright;
245  DestImageIterator dest_upperleft, src_lowerright;
246 
247  SrcAccessor src_accessor;
248  DestAccessor dest_accessor;
249 
250  dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);
251 
252  \endcode
253 
254  <b> Preconditions:</b>
255 
256  \code
257  src_lowerright.x - src_upperleft.x > 1
258  src_lowerright.y - src_upperleft.y > 1
259  dest_lowerright.x - dest_upperleft.x > 1
260  dest_lowerright.y - dest_upperleft.y > 1
261  \endcode
262 
263 */
265 
266 template <class SrcIterator, class SrcAccessor,
267  class DestIterator, class DestAccessor>
268 void
269 resizeImageNoInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
270  DestIterator id, DestIterator idend, DestAccessor da)
271 {
272  int w = iend.x - is.x;
273  int h = iend.y - is.y;
274 
275  int wnew = idend.x - id.x;
276  int hnew = idend.y - id.y;
277 
278  vigra_precondition((w > 1) && (h > 1),
279  "resizeImageNoInterpolation(): "
280  "Source image to small.\n");
281  vigra_precondition((wnew > 1) && (hnew > 1),
282  "resizeImageNoInterpolation(): "
283  "Destination image to small.\n");
284 
285  typedef BasicImage<typename SrcAccessor::value_type> TmpImage;
286  typedef typename TmpImage::traverser TmpImageIterator;
287 
288  TmpImage tmp(w, hnew);
289 
290  TmpImageIterator yt = tmp.upperLeft();
291 
292  for(int x=0; x<w; ++x, ++is.x, ++yt.x)
293  {
294  typename SrcIterator::column_iterator c1 = is.columnIterator();
295  typename TmpImageIterator::column_iterator ct = yt.columnIterator();
296 
297  resizeLineNoInterpolation(c1, c1 + h, sa, ct, ct + hnew, tmp.accessor());
298  }
299 
300  yt = tmp.upperLeft();
301 
302  for(int y=0; y < hnew; ++y, ++yt.y, ++id.y)
303  {
304  typename DestIterator::row_iterator rd = id.rowIterator();
305  typename TmpImageIterator::row_iterator rt = yt.rowIterator();
306 
307  resizeLineNoInterpolation(rt, rt + w, tmp.accessor(), rd, rd + wnew, da);
308  }
309 }
310 
311 template <class SrcIterator, class SrcAccessor,
312  class DestIterator, class DestAccessor>
313 inline
314 void
315 resizeImageNoInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
316  triple<DestIterator, DestIterator, DestAccessor> dest)
317 {
318  resizeImageNoInterpolation(src.first, src.second, src.third,
319  dest.first, dest.second, dest.third);
320 }
321 
322 /********************************************************/
323 /* */
324 /* resizeLineLinearInterpolation */
325 /* */
326 /********************************************************/
327 
328 template <class SrcIterator, class SrcAccessor,
329  class DestIterator, class DestAccessor>
330 void
331 resizeLineLinearInterpolation(SrcIterator i1, SrcIterator iend, SrcAccessor as,
332  DestIterator id, DestIterator idend, DestAccessor ad)
333 {
334  int wold = iend - i1;
335  int wnew = idend - id;
336 
337  if((wold <= 1) || (wnew <= 1)) return; // oder error ?
338 
339  typedef
340  NumericTraits<typename DestAccessor::value_type> DestTraits;
341  typedef typename DestTraits::RealPromote RealPromote;
342 
343  ad.set(DestTraits::fromRealPromote(as(i1)), id);
344  ++id;
345 
346  --iend, --idend;
347  ad.set(DestTraits::fromRealPromote(as(iend)), idend);
348 
349  double dx = (double)(wold - 1) / (wnew - 1);
350  double x = dx;
351 
352  for(; id != idend; ++id, x += dx)
353  {
354  if(x >= 1.0)
355  {
356  int xx = (int)x;
357  i1 += xx;
358  x -= (double)xx;
359  }
360  double x1 = 1.0 - x;
361 
362  ad.set(DestTraits::fromRealPromote(RealPromote(x1 * as(i1) + x * as(i1, 1))), id);
363  }
364 }
365 
366 /********************************************************/
367 /* */
368 /* resizeImageLinearInterpolation */
369 /* */
370 /********************************************************/
371 
372 /** \brief Resize image using linear interpolation.
373 
374  The function uses the standard separable bilinear interpolation algorithm to
375  obtain a good compromize between quality and speed.
376 
377  The range must of both the input and output images (resp. regions)
378  must be given. Both images must have a size of at
379  least 2x2. The scaling factors are then calculated
380  accordingly. If the source image is larger than the destination, it
381  is smoothed (band limited) using a recursive
382  exponential filter. The source value_type (SrcAccessor::value_type) must
383  be a linear space, i.e. it must support addition, multiplication
384  with a scalar real number and \ref NumericTraits "NumericTraits".
385  The function uses accessors.
386 
387  <b> Declarations:</b>
388 
389  pass arguments explicitly:
390  \code
391  namespace vigra {
392  template <class SrcImageIterator, class SrcAccessor,
393  class DestImageIterator, class DestAccessor>
394  void
395  resizeImageLinearInterpolation(
396  SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
397  DestImageIterator id, DestImageIterator idend, DestAccessor da)
398  }
399  \endcode
400 
401 
402  use argument objects in conjunction with \ref ArgumentObjectFactories :
403  \code
404  namespace vigra {
405  template <class SrcImageIterator, class SrcAccessor,
406  class DestImageIterator, class DestAccessor>
407  void
408  resizeImageLinearInterpolation(
409  triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
410  triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
411  }
412  \endcode
413 
414  <b> Usage:</b>
415 
416  <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
417  Namespace: vigra
418 
419  \code
420  vigra::resizeImageLinearInterpolation(
421  src.upperLeft(), src.lowerRight(), src.accessor(),
422  dest.upperLeft(), dest.lowerRight(), dest.accessor());
423 
424  \endcode
425 
426  <b> Required Interface:</b>
427 
428  \code
429  SrcImageIterator src_upperleft, src_lowerright;
430  DestImageIterator dest_upperleft, src_lowerright;
431 
432  SrcAccessor src_accessor;
433  DestAccessor dest_accessor;
434 
435  NumericTraits<SrcAccessor::value_type>::RealPromote
436  u = src_accessor(src_upperleft),
437  v = src_accessor(src_upperleft, 1);
438  double d;
439 
440  u = d * v;
441  u = u + v;
442 
443  dest_accessor.set(
444  NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
445  dest_upperleft);
446 
447  \endcode
448 
449  <b> Preconditions:</b>
450 
451  \code
452  src_lowerright.x - src_upperleft.x > 1
453  src_lowerright.y - src_upperleft.y > 1
454  dest_lowerright.x - dest_upperleft.x > 1
455  dest_lowerright.y - dest_upperleft.y > 1
456  \endcode
457 
458 */
460 
461 template <class SrcIterator, class SrcAccessor,
462  class DestIterator, class DestAccessor>
463 void
464 resizeImageLinearInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
465  DestIterator id, DestIterator idend, DestAccessor da)
466 {
467  int w = iend.x - is.x;
468  int h = iend.y - is.y;
469 
470  int wnew = idend.x - id.x;
471  int hnew = idend.y - id.y;
472 
473  vigra_precondition((w > 1) && (h > 1),
474  "resizeImageLinearInterpolation(): "
475  "Source image to small.\n");
476  vigra_precondition((wnew > 1) && (hnew > 1),
477  "resizeImageLinearInterpolation(): "
478  "Destination image to small.\n");
479 
480  double const scale = 2.0;
481 
482  typedef typename SrcAccessor::value_type SRCVT;
483  typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
484  typedef BasicImage<TMPTYPE> TmpImage;
485  typedef typename TmpImage::traverser TmpImageIterator;
486 
487  BasicImage<TMPTYPE> tmp(w, hnew);
488  BasicImage<TMPTYPE> line((h > w) ? h : w, 1);
489 
490  int x,y;
491 
492  typename BasicImage<TMPTYPE>::Iterator yt = tmp.upperLeft();
493  typename TmpImageIterator::row_iterator lt = line.upperLeft().rowIterator();
494 
495  for(x=0; x<w; ++x, ++is.x, ++yt.x)
496  {
497  typename SrcIterator::column_iterator c1 = is.columnIterator();
498  typename TmpImageIterator::column_iterator ct = yt.columnIterator();
499 
500  if(hnew < h)
501  {
502  recursiveSmoothLine(c1, c1 + h, sa,
503  lt, line.accessor(), (double)h/hnew/scale);
504 
505  resizeLineLinearInterpolation(lt, lt + h, line.accessor(),
506  ct, ct + hnew, tmp.accessor());
507  }
508  else
509  {
510  resizeLineLinearInterpolation(c1, c1 + h, sa,
511  ct, ct + hnew, tmp.accessor());
512  }
513  }
514 
515  yt = tmp.upperLeft();
516 
517  for(y=0; y < hnew; ++y, ++yt.y, ++id.y)
518  {
519  typename DestIterator::row_iterator rd = id.rowIterator();
520  typename TmpImageIterator::row_iterator rt = yt.rowIterator();
521 
522  if(wnew < w)
523  {
524  recursiveSmoothLine(rt, rt + w, tmp.accessor(),
525  lt, line.accessor(), (double)w/wnew/scale);
526 
527  resizeLineLinearInterpolation(lt, lt + w, line.accessor(),
528  rd, rd + wnew, da);
529  }
530  else
531  {
532  resizeLineLinearInterpolation(rt, rt + w, tmp.accessor(),
533  rd, rd + wnew, da);
534  }
535  }
536 }
537 
538 template <class SrcIterator, class SrcAccessor,
539  class DestIterator, class DestAccessor>
540 inline
541 void
542 resizeImageLinearInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
543  triple<DestIterator, DestIterator, DestAccessor> dest)
544 {
545  resizeImageLinearInterpolation(src.first, src.second, src.third,
546  dest.first, dest.second, dest.third);
547 }
548 
549 /***************************************************************/
550 /* */
551 /* resizeImageSplineInterpolation */
552 /* */
553 /***************************************************************/
554 
555 /** \brief Resize image using B-spline interpolation.
556 
557  The function implements separable spline interpolation algorithm described in
558 
559  M. Unser, A. Aldroubi, M. Eden, <i>"B-Spline Signal Processing"</i>
560  IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 821-833 (part I),
561  pp. 834-848 (part II), 1993.
562 
563  to obtain optimal interpolation quality and speed. You may pass the funcion
564  a spline of arbitrary order (e.g. <TT>BSpline<ORDER, double></tt> or
565  <TT>CatmullRomSpline<double></tt>). The default is a third order spline
566  which gives a twice continuously differentiable interpolant.
567  The implementation ensures that image values are interpolated rather
568  than smoothed by first calling a recursive (sharpening) prefilter as
569  described in the above paper. Then the actual interpolation is done
570  using \ref resamplingConvolveLine().
571 
572  The range of both the input and output images (resp. regions)
573  must be given. The input image must have a size of at
574  least 4x4, the destination of at least 2x2. The scaling factors are then calculated
575  accordingly. If the source image is larger than the destination, it
576  is smoothed (band limited) using a recursive
577  exponential filter. The source value_type (SrcAccessor::value_type) must
578  be a linear algebra, i.e. it must support addition, subtraction,
579  and multiplication (+, -, *), multiplication with a scalar
580  real number and \ref NumericTraits "NumericTraits".
581  The function uses accessors.
582 
583  <b> Declarations:</b>
584 
585  pass arguments explicitly:
586  \code
587  namespace vigra {
588  template <class SrcImageIterator, class SrcAccessor,
589  class DestImageIterator, class DestAccessor,
590  class SPLINE>
591  void
592  resizeImageSplineInterpolation(
593  SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
594  DestImageIterator id, DestImageIterator idend, DestAccessor da,
595  SPLINE spline = BSpline<3, double>())
596  }
597  \endcode
598 
599 
600  use argument objects in conjunction with \ref ArgumentObjectFactories :
601  \code
602  namespace vigra {
603  template <class SrcImageIterator, class SrcAccessor,
604  class DestImageIterator, class DestAccessor,
605  class SPLINE>
606  void
607  resizeImageSplineInterpolation(
608  triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
609  triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
610  SPLINE spline = BSpline<3, double>())
611  }
612  \endcode
613 
614  <b> Usage:</b>
615 
616  <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
617  Namespace: vigra
618 
619  \code
620  vigra::resizeImageSplineInterpolation(
621  src.upperLeft(), src.lowerRight(), src.accessor(),
622  dest.upperLeft(), dest.lowerRight(), dest.accessor());
623 
624  \endcode
625 
626  <b> Required Interface:</b>
627 
628  \code
629  SrcImageIterator src_upperleft, src_lowerright;
630  DestImageIterator dest_upperleft, src_lowerright;
631 
632  SrcAccessor src_accessor;
633  DestAccessor dest_accessor;
634 
635  NumericTraits<SrcAccessor::value_type>::RealPromote
636  u = src_accessor(src_upperleft),
637  v = src_accessor(src_upperleft, 1);
638  double d;
639 
640  u = d * v;
641  u = u + v;
642  u = u - v;
643  u = u * v;
644  u += v;
645  u -= v;
646 
647  dest_accessor.set(
648  NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
649  dest_upperleft);
650 
651  \endcode
652 
653  <b> Preconditions:</b>
654 
655  \code
656  src_lowerright.x - src_upperleft.x > 3
657  src_lowerright.y - src_upperleft.y > 3
658  dest_lowerright.x - dest_upperleft.x > 1
659  dest_lowerright.y - dest_upperleft.y > 1
660  \endcode
661 
662 */
664 
665 template <class SrcIterator, class SrcAccessor,
666  class DestIterator, class DestAccessor,
667  class SPLINE>
668 void
670  SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
671  DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc,
672  SPLINE const & spline)
673 {
674 
675  int width_old = src_iter_end.x - src_iter.x;
676  int height_old = src_iter_end.y - src_iter.y;
677 
678  int width_new = dest_iter_end.x - dest_iter.x;
679  int height_new = dest_iter_end.y - dest_iter.y;
680 
681  vigra_precondition((width_old > 1) && (height_old > 1),
682  "resizeImageSplineInterpolation(): "
683  "Source image to small.\n");
684 
685  vigra_precondition((width_new > 1) && (height_new > 1),
686  "resizeImageSplineInterpolation(): "
687  "Destination image to small.\n");
688 
689  Rational<int> xratio(width_new - 1, width_old - 1);
690  Rational<int> yratio(height_new - 1, height_old - 1);
691  Rational<int> offset(0);
692  resampling_detail::MapTargetToSourceCoordinate xmapCoordinate(xratio, offset);
693  resampling_detail::MapTargetToSourceCoordinate ymapCoordinate(yratio, offset);
694  int xperiod = lcm(xratio.numerator(), xratio.denominator());
695  int yperiod = lcm(yratio.numerator(), yratio.denominator());
696 
697  double const scale = 2.0;
698 
699  typedef typename SrcAccessor::value_type SRCVT;
700  typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
701  typedef BasicImage<TMPTYPE> TmpImage;
702  typedef typename TmpImage::traverser TmpImageIterator;
703 
704  BasicImage<TMPTYPE> tmp(width_old, height_new);
705 
706  BasicImage<TMPTYPE> line((height_old > width_old) ? height_old : width_old, 1);
707  typename BasicImage<TMPTYPE>::Accessor tmp_acc = tmp.accessor();
708  ArrayVector<double> const & prefilterCoeffs = spline.prefilterCoefficients();
709 
710  int x,y;
711 
712  ArrayVector<Kernel1D<double> > kernels(yperiod);
713  createResamplingKernels(spline, ymapCoordinate, kernels);
714 
715  typename BasicImage<TMPTYPE>::Iterator y_tmp = tmp.upperLeft();
716  typename TmpImageIterator::row_iterator line_tmp = line.upperLeft().rowIterator();
717 
718  for(x=0; x<width_old; ++x, ++src_iter.x, ++y_tmp.x)
719  {
720 
721  typename SrcIterator::column_iterator c_src = src_iter.columnIterator();
722  typename TmpImageIterator::column_iterator c_tmp = y_tmp.columnIterator();
723 
724  if(prefilterCoeffs.size() == 0)
725  {
726  if(height_new >= height_old)
727  {
728  resamplingConvolveLine(c_src, c_src + height_old, src_acc,
729  c_tmp, c_tmp + height_new, tmp_acc,
730  kernels, ymapCoordinate);
731  }
732  else
733  {
734  recursiveSmoothLine(c_src, c_src + height_old, src_acc,
735  line_tmp, line.accessor(), (double)height_old/height_new/scale);
736  resamplingConvolveLine(line_tmp, line_tmp + height_old, line.accessor(),
737  c_tmp, c_tmp + height_new, tmp_acc,
738  kernels, ymapCoordinate);
739  }
740  }
741  else
742  {
743  recursiveFilterLine(c_src, c_src + height_old, src_acc,
744  line_tmp, line.accessor(),
745  prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
746  for(unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
747  {
748  recursiveFilterLine(line_tmp, line_tmp + height_old, line.accessor(),
749  line_tmp, line.accessor(),
750  prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
751  }
752  if(height_new < height_old)
753  {
754  recursiveSmoothLine(line_tmp, line_tmp + height_old, line.accessor(),
755  line_tmp, line.accessor(), (double)height_old/height_new/scale);
756  }
757  resamplingConvolveLine(line_tmp, line_tmp + height_old, line.accessor(),
758  c_tmp, c_tmp + height_new, tmp_acc,
759  kernels, ymapCoordinate);
760  }
761  }
762 
763  y_tmp = tmp.upperLeft();
764 
765  DestIterator dest = dest_iter;
766 
767  kernels.resize(xperiod);
768  createResamplingKernels(spline, xmapCoordinate, kernels);
769 
770  for(y=0; y < height_new; ++y, ++y_tmp.y, ++dest_iter.y)
771  {
772  typename DestIterator::row_iterator r_dest = dest_iter.rowIterator();
773  typename TmpImageIterator::row_iterator r_tmp = y_tmp.rowIterator();
774 
775  if(prefilterCoeffs.size() == 0)
776  {
777  if(width_new >= width_old)
778  {
779  resamplingConvolveLine(r_tmp, r_tmp + width_old, tmp.accessor(),
780  r_dest, r_dest + width_new, dest_acc,
781  kernels, xmapCoordinate);
782  }
783  else
784  {
785  recursiveSmoothLine(r_tmp, r_tmp + width_old, tmp.accessor(),
786  line_tmp, line.accessor(), (double)width_old/width_new/scale);
787  resamplingConvolveLine(line_tmp, line_tmp + width_old, line.accessor(),
788  r_dest, r_dest + width_new, dest_acc,
789  kernels, xmapCoordinate);
790  }
791  }
792  else
793  {
794  recursiveFilterLine(r_tmp, r_tmp + width_old, tmp.accessor(),
795  line_tmp, line.accessor(),
796  prefilterCoeffs[0], BORDER_TREATMENT_REFLECT);
797  for(unsigned int b = 1; b < prefilterCoeffs.size(); ++b)
798  {
799  recursiveFilterLine(line_tmp, line_tmp + width_old, line.accessor(),
800  line_tmp, line.accessor(),
801  prefilterCoeffs[b], BORDER_TREATMENT_REFLECT);
802  }
803  if(width_new < width_old)
804  {
805  recursiveSmoothLine(line_tmp, line_tmp + width_old, line.accessor(),
806  line_tmp, line.accessor(), (double)width_old/width_new/scale);
807  }
808  resamplingConvolveLine(line_tmp, line_tmp + width_old, line.accessor(),
809  r_dest, r_dest + width_new, dest_acc,
810  kernels, xmapCoordinate);
811  }
812  }
813 }
814 
815 template <class SrcIterator, class SrcAccessor,
816  class DestIterator, class DestAccessor,
817  class SPLINE>
818 inline
819 void
820 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
821  triple<DestIterator, DestIterator, DestAccessor> dest,
822  SPLINE const & spline)
823 {
824  resizeImageSplineInterpolation(src.first, src.second, src.third,
825  dest.first, dest.second, dest.third, spline);
826 }
827 
828 template <class SrcIterator, class SrcAccessor,
829  class DestIterator, class DestAccessor>
830 void
831 resizeImageSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
832  DestIterator id, DestIterator idend, DestAccessor da)
833 {
834  resizeImageSplineInterpolation(is, iend, sa, id, idend, da, BSpline<3, double>());
835 }
836 
837 template <class SrcIterator, class SrcAccessor,
838  class DestIterator, class DestAccessor>
839 inline
840 void
841 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
842  triple<DestIterator, DestIterator, DestAccessor> dest)
843 {
844  resizeImageSplineInterpolation(src.first, src.second, src.third,
845  dest.first, dest.second, dest.third);
846 }
847 
848 /*****************************************************************/
849 /* */
850 /* resizeImageCatmullRomInterpolation */
851 /* */
852 /*****************************************************************/
853 
854 /** \brief Resize image using the Catmull/Rom interpolation function.
855 
856  The function calls like \ref resizeImageSplineInterpolation() with
857  \ref vigra::CatmullRomSpline as an interpolation kernel.
858  The interpolated function has one continuous derivative.
859  (See \ref resizeImageSplineInterpolation() for more documentation)
860 
861  <b> Declarations:</b>
862 
863  pass arguments explicitly:
864  \code
865  namespace vigra {
866  template <class SrcIterator, class SrcAccessor,
867  class DestIterator, class DestAccessor>
868  void
869  resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
870  DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
871  }
872  \endcode
873 
874 
875  use argument objects in conjunction with \ref ArgumentObjectFactories :
876  \code
877  namespace vigra {
878  template <class SrcIterator, class SrcAccessor,
879  class DestIterator, class DestAccessor>
880  void
881  resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
882  triple<DestIterator, DestIterator, DestAccessor> dest);
883  }
884  \endcode
885 
886 
887  <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
888  Namespace: vigra
889 
890 */
892 
893 template <class SrcIterator, class SrcAccessor,
894  class DestIterator, class DestAccessor>
895 inline void
896 resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
897  DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
898 {
899  resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
900  CatmullRomSpline<double>());
901 }
902 
903 template <class SrcIterator, class SrcAccessor,
904  class DestIterator, class DestAccessor>
905 inline
906 void
907 resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
908  triple<DestIterator, DestIterator, DestAccessor> dest)
909 {
910  resizeImageCatmullRomInterpolation(src.first, src.second, src.third,
911  dest.first, dest.second, dest.third);
912 }
913 
914 #if 0
915 /*****************************************************************/
916 /* */
917 /* resizeImageCubicInterpolation */
918 /* */
919 /*****************************************************************/
920 
921 /** \brief Resize image using the cardinal B-spline interpolation function.
922 
923  The function calls like \ref resizeImageSplineInterpolation() with
924  \ref vigra::BSpline<3, double> and prefiltering as an interpolation kernel.
925  The interpolated function has two continuous derivatives.
926  (See \ref resizeImageSplineInterpolation() for more documentation)
927 
928  <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
929  Namespace: vigra
930 
931 */
932 template <class SrcIterator, class SrcAccessor,
933  class DestIterator, class DestAccessor>
934 void
935 resizeImageCubicInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
936  DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
937 {
938  resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
939  BSpline<3, double>());
940 }
941 
942 template <class SrcIterator, class SrcAccessor,
943  class DestIterator, class DestAccessor>
944 inline
945 void
946 resizeImageCubicInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
947  triple<DestIterator, DestIterator, DestAccessor> dest)
948 {
949  resizeImageCubicInterpolation(src.first, src.second, src.third,
950  dest.first, dest.second, dest.third);
951 }
952 #endif
953 
954 /*****************************************************************/
955 /* */
956 /* resizeImageCoscotInterpolation */
957 /* */
958 /*****************************************************************/
959 
960 /** \brief Resize image using the Coscot interpolation function.
961 
962  The function calls \ref resizeImageSplineInterpolation() with
963  \ref vigra::CoscotFunction as an interpolation kernel.
964  The interpolated function has one continuous derivative.
965  (See \ref resizeImageSplineInterpolation() for more documentation)
966 
967  <b> Declarations:</b>
968 
969  pass arguments explicitly:
970  \code
971  namespace vigra {
972  template <class SrcIterator, class SrcAccessor,
973  class DestIterator, class DestAccessor>
974  void
975  resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
976  DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
977  }
978  \endcode
979 
980 
981  use argument objects in conjunction with \ref ArgumentObjectFactories :
982  \code
983  namespace vigra {
984  template <class SrcIterator, class SrcAccessor,
985  class DestIterator, class DestAccessor>
986  void
987  resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
988  triple<DestIterator, DestIterator, DestAccessor> dest);
989  }
990  \endcode
991 
992 
993  <b>\#include</b> <<a href="resizeimage_8hxx-source.html">vigra/resizeimage.hxx</a>><br>
994  Namespace: vigra
995 
996 */
998 
999 template <class SrcIterator, class SrcAccessor,
1000  class DestIterator, class DestAccessor>
1001 void
1002 resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
1003  DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc)
1004 {
1005  resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_iter, dest_iter_end, dest_acc,
1006  CoscotFunction<double>());
1007 }
1008 
1009 template <class SrcIterator, class SrcAccessor,
1010  class DestIterator, class DestAccessor>
1011 inline
1012 void
1013 resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1014  triple<DestIterator, DestIterator, DestAccessor> dest)
1015 {
1016  resizeImageCoscotInterpolation(src.first, src.second, src.third,
1017  dest.first, dest.second, dest.third);
1018 }
1019 
1020 
1021 #if 0 // old version of the spline interpolation algorithm
1022 
1023 /********************************************************/
1024 /* */
1025 /* resizeCalculateSplineCoefficients */
1026 /* (internally used by resize functions) */
1027 /* */
1028 /********************************************************/
1029 
1030 template <class SrcIterator, class SrcAccessor, class VALUETYPE>
1031 void
1032 resizeCalculateSplineCoefficients(SrcIterator i1, SrcIterator iend,
1033  SrcAccessor a, VALUETYPE * i2)
1034 {
1035  int n = iend - i1;
1036 
1037  if(n <= 0) return;
1038 
1039  VALUETYPE zero = NumericTraits<VALUETYPE>::zero();
1040  VALUETYPE two = 2.0 * NumericTraits<VALUETYPE>::one();
1041  VALUETYPE half = 0.5 * NumericTraits<VALUETYPE>::one();
1042 
1043  *i2 = zero;
1044  if(n == 1) return;
1045 
1046  std::vector<VALUETYPE> vec(n);
1047  typename std::vector<VALUETYPE>::iterator u = vec.begin();
1048 
1049  *u = zero;
1050 
1051  for(++i1, ++i2, ++u, --iend; i1 != iend; ++i1, ++i2, ++u)
1052  {
1053  VALUETYPE p = 0.5 * i2[-1] + two;
1054  *i2 = half / p;
1055  *u = 3.0 *(a(i1,1) - 2.0 * a(i1) + a(i1, -1)) - 0.5 * u[-1] / p;
1056  }
1057 
1058  *i2 = zero;
1059 
1060  for(--i2, --u; u != vec; --u, --i2)
1061  {
1062  *i2 = *i2 * i2[1] + *u;
1063  }
1064 }
1065 
1066 /********************************************************/
1067 /* */
1068 /* resizeImageInternalSplineGradient */
1069 /* */
1070 /********************************************************/
1071 
1072 template <class SrcIterator, class SrcAccessor,
1073  class DoubleIterator, class TempIterator, class DestIterator>
1074 void
1075 resizeImageInternalSplineGradient(SrcIterator in, SrcIterator inend, SrcAccessor sa,
1076  DoubleIterator tmp, TempIterator r, DestIterator id)
1077 {
1078  int w = inend - in;
1079 
1080  int x;
1081 
1082  typedef typename SrcAccessor::value_type SRCVT;
1083  typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
1084 
1085  // calculate border derivatives
1086  SrcIterator xs = in;
1087  TMPTYPE p0 = -11.0/6.0 * sa(xs); ++xs;
1088  p0 += 3.0 * sa(xs); ++xs;
1089  p0 += -1.5 * sa(xs); ++xs;
1090  p0 += 1.0/3.0 * sa(xs);
1091 
1092  xs = in + w-1;
1093  TMPTYPE pw = 11.0/6.0 * sa(xs); --xs;
1094  pw += -3.0 * sa(xs); --xs;
1095  pw += 1.5 * sa(xs); --xs;
1096  pw += -1.0/3.0 * sa(xs);
1097 
1098  xs = in + 2;
1099  SrcIterator xs1 = in;
1100 
1101  for(x=1; x<w-1; ++x, ++xs, ++xs1)
1102  {
1103  r[x] = 3.0 * (sa(xs) - sa(xs1));
1104  }
1105 
1106  r[1] -= p0;
1107  r[w-2] -= pw;
1108 
1109  double q = 0.25;
1110 
1111  id[0] = p0;
1112  id[w-1] = pw;
1113  id[1] = 0.25 * r[1];
1114 
1115  for(x=2; x<w-1; ++x)
1116  {
1117  tmp[x] = q;
1118  q = 1.0 / (4.0 - q);
1119  id[x] = q * (r[x] - id[x-1]);
1120  }
1121 
1122  for(x=w-3; x>=1; --x)
1123  {
1124  id[x] -= tmp[x+1]*id[x+1];
1125  }
1126 }
1127 
1128 /********************************************************/
1129 /* */
1130 /* resizeImageInternalSplineInterpolation */
1131 /* */
1132 /********************************************************/
1133 
1134 template <class SrcIterator, class SrcAccessor,
1135  class DestIterator, class DestAccessor>
1136 void
1137 resizeImageInternalSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
1138  DestIterator id, DestIterator idend, DestAccessor da)
1139 {
1140  int w = iend.x - is.x;
1141  int h = iend.y - is.y;
1142 
1143  int wnew = idend.x - id.x;
1144  int hnew = idend.y - id.y;
1145 
1146  typedef typename SrcAccessor::value_type SRCVT;
1147  typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
1148  typedef typename BasicImage<TMPTYPE>::Iterator TMPITER;
1149  typedef
1150  NumericTraits<typename DestAccessor::value_type> DestTraits;
1151 
1152  BasicImage<TMPTYPE> dx(w,h);
1153  BasicImage<TMPTYPE> dy(w,h);
1154  BasicImage<TMPTYPE> dxy(w,h);
1155  BasicImage<TMPTYPE> W(4,4), W1(4,4);
1156  std::vector<TMPTYPE> R(w > h ? w : h);
1157  std::vector<double> tmp(w > h ? w : h);
1158 
1159  typename BasicImage<TMPTYPE>::Accessor ta;
1160 
1161  SrcIterator in = is;
1162 
1163  TMPITER idx = dx.upperLeft();
1164  TMPITER idy = dy.upperLeft();
1165  TMPITER idxy = dxy.upperLeft();
1166  typename std::vector<TMPTYPE>::iterator r = R.begin();
1167  typename std::vector<double>::iterator it = tmp.begin();
1168 
1169  double ig[] = { 1.0, 0.0, -3.0, 2.0,
1170  0.0, 1.0, -2.0, 1.0,
1171  0.0, 0.0, 3.0, -2.0,
1172  0.0, 0.0, -1.0, 1.0 };
1173 
1174  int x, y, i, j, k;
1175 
1176 
1177  // calculate x derivatives
1178  for(y=0; y<h; ++y, ++in.y, ++idx.y)
1179  {
1180  typename SrcIterator::row_iterator sr = in.rowIterator();
1181  typename TMPITER::row_iterator dr = idx.rowIterator();
1182  resizeImageInternalSplineGradient(sr, sr+w, sa,
1183  it, r, dr);
1184  }
1185 
1186  in = is;
1187 
1188  // calculate y derivatives
1189  for(x=0; x<w; ++x, ++in.x, ++idy.x)
1190  {
1191  typename SrcIterator::column_iterator sc = in.columnIterator();
1192  typename TMPITER::column_iterator dc = idy.columnIterator();
1193  resizeImageInternalSplineGradient(sc, sc+h, sa,
1194  it, r, dc);
1195  }
1196 
1197  in = is;
1198  idy = dy.upperLeft();
1199 
1200  // calculate mixed derivatives
1201  for(y=0; y<h; ++y, ++idy.y, ++idxy.y)
1202  {
1203  typename TMPITER::row_iterator sr = idy.rowIterator();
1204  typename TMPITER::row_iterator dr = idxy.rowIterator();
1205  resizeImageInternalSplineGradient(sr, sr+w, ta,
1206  it, r, dr);
1207  }
1208 
1209  double du = (double)(w-1) / (wnew-1);
1210  double dv = (double)(h-1) / (hnew-1);
1211  double ov = 0.0;
1212  int oy = 0;
1213  int yy = oy;
1214 
1215  DestIterator xxd = id, yyd = id;
1216 
1217  static Diff2D down(0,1), right(1,0), downright(1,1);
1218 
1219  for(y=0; y<h-1; ++y, ++in.y, ov -= 1.0)
1220  {
1221  if(y < h-2 && ov >= 1.0) continue;
1222  int y1 = y+1;
1223  double v = ov;
1224  double ou = 0.0;
1225  int ox = 0;
1226  int xx = ox;
1227 
1228  SrcIterator xs = in;
1229  for(x=0; x<w-1; ++x, ++xs.x, ou -= 1.0)
1230  {
1231  if(x < w-2 && ou >= 1.0) continue;
1232  int x1 = x+1;
1233  double u = ou;
1234 
1235  DestIterator xd = id + Diff2D(ox,oy);
1236  W[0][0] = sa(xs);
1237  W[0][1] = dy(x, y);
1238  W[0][2] = sa(xs, down);
1239  W[0][3] = dy(x, y1);
1240  W[1][0] = dx(x, y);
1241  W[1][1] = dxy(x, y);
1242  W[1][2] = dx(x, y1);
1243  W[1][3] = dxy(x, y1);
1244  W[2][0] = sa(xs, right);
1245  W[2][1] = dy(x1,y);
1246  W[2][2] = sa(xs, downright);
1247  W[2][3] = dy(x1, y1);
1248  W[3][0] = dx(x1, y);
1249  W[3][1] = dxy(x1, y);
1250  W[3][2] = dx(x1, y1);
1251  W[3][3] = dxy(x1, y1);
1252 
1253  for(i=0; i<4; ++i)
1254  {
1255  for(j=0; j<4; ++j)
1256  {
1257  W1[j][i] = ig[j] * W[0][i];
1258  for(k=1; k<4; ++k)
1259  {
1260  W1[j][i] += ig[j+4*k] * W[k][i];
1261  }
1262  }
1263  }
1264  for(i=0; i<4; ++i)
1265  {
1266  for(j=0; j<4; ++j)
1267  {
1268  W[j][i] = ig[i] * W1[j][0];
1269  for(k=1; k<4; ++k)
1270  {
1271  W[j][i] += ig[4*k+i] * W1[j][k];
1272  }
1273  }
1274  }
1275 
1276  TMPTYPE a1,a2,a3,a4;
1277 
1278  yyd = xd;
1279  for(v=ov, yy=oy; v<1.0; v+=dv, ++yyd.y, ++yy)
1280  {
1281  a1 = W[0][0] + v * (W[0][1] +
1282  v * (W[0][2] + v * W[0][3]));
1283  a2 = W[1][0] + v * (W[1][1] +
1284  v * (W[1][2] + v * W[1][3]));
1285  a3 = W[2][0] + v * (W[2][1] +
1286  v * (W[2][2] + v * W[2][3]));
1287  a4 = W[3][0] + v * (W[3][1] +
1288  v * (W[3][2] + v * W[3][3]));
1289 
1290  xxd = yyd;
1291  for(u=ou, xx=ox; u<1.0; u+=du, ++xxd.x, ++xx)
1292  {
1293  da.set(DestTraits::fromRealPromote(a1 + u * (a2 + u * (a3 + u * a4))), xxd);
1294  }
1295 
1296  if(xx == wnew-1)
1297  {
1298  da.set(DestTraits::fromRealPromote(a1 + a2 + a3 + a4), xxd);
1299  }
1300  }
1301 
1302  if(yy == hnew-1)
1303  {
1304  a1 = W[0][0] + W[0][1] + W[0][2] + W[0][3];
1305  a2 = W[1][0] + W[1][1] + W[1][2] + W[1][3];
1306  a3 = W[2][0] + W[2][1] + W[2][2] + W[2][3];
1307  a4 = W[3][0] + W[3][1] + W[3][2] + W[3][3];
1308 
1309  DestIterator xxd = yyd;
1310  for(u=ou, xx=ox; u<1.0; u+=du, ++xxd.x, ++xx)
1311  {
1312  da.set(DestTraits::fromRealPromote(a1 + u * (a2 + u * (a3 + u * a4))), xxd);
1313  }
1314 
1315  if(xx == wnew-1)
1316  {
1317  da.set(DestTraits::fromRealPromote(a1 + a2 + a3 + a4), xxd);
1318  }
1319  }
1320 
1321  ou = u;
1322  ox = xx;
1323  }
1324  ov = v;
1325  oy = yy;
1326  }
1327 }
1328 
1329 template <class SrcIterator, class SrcAccessor,
1330  class DestIterator, class DestAccessor>
1331 void
1332 resizeImageSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa,
1333  DestIterator id, DestIterator idend, DestAccessor da)
1334 {
1335  int w = iend.x - is.x;
1336  int h = iend.y - is.y;
1337 
1338  int wnew = idend.x - id.x;
1339  int hnew = idend.y - id.y;
1340 
1341  vigra_precondition((w > 3) && (h > 3),
1342  "resizeImageSplineInterpolation(): "
1343  "Source image to small.\n");
1344  vigra_precondition((wnew > 1) && (hnew > 1),
1345  "resizeImageSplineInterpolation(): "
1346  "Destination image to small.\n");
1347 
1348  double scale = 2.0;
1349 
1350  if(wnew < w || hnew < h)
1351  {
1352  typedef typename SrcAccessor::value_type SRCVT;
1353  typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE;
1354  typedef typename BasicImage<TMPTYPE>::Iterator TMPITER;
1355 
1356  BasicImage<TMPTYPE> t(w,h);
1357  TMPITER it = t.upperLeft();
1358 
1359  if(wnew < w)
1360  {
1361  recursiveSmoothX(is, iend, sa,
1362  it, t.accessor(), (double)w/wnew/scale);
1363 
1364  if(hnew < h)
1365  {
1366  recursiveSmoothY(it, t.lowerRight(), t.accessor(),
1367  it, t.accessor(), (double)h/hnew/scale);
1368  }
1369  }
1370  else
1371  {
1372  recursiveSmoothY(is, iend, sa,
1373  it, t.accessor(), (double)h/hnew/scale);
1374  }
1375 
1376  resizeImageInternalSplineInterpolation(it, t.lowerRight(), t.accessor(),
1377  id, idend, da);
1378  }
1379  else
1380  {
1381  resizeImageInternalSplineInterpolation(is, iend, sa, id, idend, da);
1382  }
1383 }
1384 
1385 template <class SrcIterator, class SrcAccessor,
1386  class DestIterator, class DestAccessor>
1387 inline
1388 void
1389 resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1390  triple<DestIterator, DestIterator, DestAccessor> dest)
1391 {
1392  resizeImageSplineInterpolation(src.first, src.second, src.third,
1393  dest.first, dest.second, dest.third);
1394 }
1395 #endif // old alghorithm version
1396 
1397 //@}
1398 
1399 } // namespace vigra
1400 
1401 #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.7.1 (Wed Mar 12 2014)