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

resizeimage.hxx VIGRA

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>
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  */
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  */
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  */
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
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
Definition: resizeimage.hxx:82
result_type operator()(argument_type x) const
Definition: resizeimage.hxx:103
linalg::TemporaryMatrix< T > sin(MultiArrayView< 2, T, C > const &v)
void recursiveSmoothLine(...)
Convolves the image with a 1-dimensional exponential filter.
void resizeImageCoscotInterpolation(...)
Resize image using the Coscot interpolation function.
void resizeImageSplineInterpolation(...)
Resize image using B-spline interpolation.
double radius() const
Definition: resizeimage.hxx:121
unsigned int derivativeOrder() const
Definition: resizeimage.hxx:126
T argument_type
Definition: resizeimage.hxx:91
value_type operator[](value_type x) const
Definition: resizeimage.hxx:115
void resizeImageLinearInterpolation(...)
Resize image using linear interpolation.
void recursiveFilterLine(...)
Performs a 1-dimensional recursive convolution of the source signal.
void resizeImageNoInterpolation(...)
Resize image by repeating the nearest pixel values.
IntType lcm(IntType n, IntType m)
Definition: rational.hxx:122
T result_type
Definition: resizeimage.hxx:94
T value_type
Definition: resizeimage.hxx:88
FFTWComplex< R >::NormType abs(const FFTWComplex< R > &a)
absolute value (= magnitude)
Definition: fftw3.hxx:1002
ArrayVector< double > const & prefilterCoefficients() const
Definition: resizeimage.hxx:132
linalg::TemporaryMatrix< T > tan(MultiArrayView< 2, T, C > const &v)
linalg::TemporaryMatrix< T > cos(MultiArrayView< 2, T, C > const &v)
void resamplingConvolveLine(...)
Performs a 1-dimensional resampling convolution of the source signal using the given set of kernels...
void resizeImageCatmullRomInterpolation(...)
Resize image using the Catmull/Rom interpolation function.

© 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 (Tue Dec 31 2013)