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