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