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

resampling_convolution.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 #ifndef VIGRA_RESAMPLING_CONVOLUTION_HXX
37 #define VIGRA_RESAMPLING_CONVOLUTION_HXX
38 
39 #include <cmath>
40 #include "stdimage.hxx"
41 #include "array_vector.hxx"
42 #include "rational.hxx"
43 #include "functortraits.hxx"
44 #include "functorexpression.hxx"
45 #include "transformimage.hxx"
46 #include "imagecontainer.hxx"
47 #include "multi_shape.hxx"
48 
49 namespace vigra {
50 
51 namespace resampling_detail
52 {
53 
54 struct MapTargetToSourceCoordinate
55 {
56  MapTargetToSourceCoordinate(Rational<int> const & samplingRatio,
57  Rational<int> const & offset)
58  : a(samplingRatio.denominator()*offset.denominator()),
59  b(samplingRatio.numerator()*offset.numerator()),
60  c(samplingRatio.numerator()*offset.denominator())
61  {}
62 
63 // the following functions are more efficient realizations of:
64 // rational_cast<T>(i / samplingRatio + offset);
65 // we need efficiency because this may be called in the inner loop
66 
67  int operator()(int i) const
68  {
69  return (i * a + b) / c;
70  }
71 
72  double toDouble(int i) const
73  {
74  return double(i * a + b) / c;
75  }
76 
77  Rational<int> toRational(int i) const
78  {
79  return Rational<int>(i * a + b, c);
80  }
81 
82  bool isExpand2() const
83  {
84  return a == 1 && b == 0 && c == 2;
85  }
86 
87  bool isReduce2() const
88  {
89  return a == 2 && b == 0 && c == 1;
90  }
91 
92  int a, b, c;
93 };
94 
95 } // namespace resampling_detail
96 
97 template <>
98 class FunctorTraits<resampling_detail::MapTargetToSourceCoordinate>
99 : public FunctorTraitsBase<resampling_detail::MapTargetToSourceCoordinate>
100 {
101  public:
102  typedef VigraTrueType isUnaryFunctor;
103 };
104 
105 template <class SrcIter, class SrcAcc,
106  class DestIter, class DestAcc,
107  class KernelArray>
108 void
109 resamplingExpandLine2(SrcIter s, SrcIter send, SrcAcc src,
110  DestIter d, DestIter dend, DestAcc dest,
111  KernelArray const & kernels)
112 {
113  typedef typename KernelArray::value_type Kernel;
114  typedef typename KernelArray::const_reference KernelRef;
115  typedef typename Kernel::const_iterator KernelIter;
116 
117  typedef typename
118  PromoteTraits<typename SrcAcc::value_type, typename Kernel::value_type>::Promote
119  TmpType;
120 
121  int wo = send - s;
122  int wn = dend - d;
123  int wo2 = 2*wo - 2;
124 
125  int ileft = std::max(kernels[0].right(), kernels[1].right());
126  int iright = wo + std::min(kernels[0].left(), kernels[1].left()) - 1;
127  for(int i = 0; i < wn; ++i, ++d)
128  {
129  int is = i / 2;
130  KernelRef kernel = kernels[i & 1];
131  KernelIter k = kernel.center() + kernel.right();
132  TmpType sum = NumericTraits<TmpType>::zero();
133  if(is < ileft)
134  {
135  for(int m=is-kernel.right(); m <= is-kernel.left(); ++m, --k)
136  {
137  int mm = (m < 0)
138  ? -m
139  : m;
140  sum += *k * src(s, mm);
141  }
142  }
143  else if(is > iright)
144  {
145  for(int m=is-kernel.right(); m <= is-kernel.left(); ++m, --k)
146  {
147  int mm = (m >= wo)
148  ? wo2 - m
149  : m;
150  sum += *k * src(s, mm);
151  }
152  }
153  else
154  {
155  SrcIter ss = s + is - kernel.right();
156  for(int m = 0; m < kernel.size(); ++m, --k, ++ss)
157  {
158  sum += *k * src(ss);
159  }
160  }
161  dest.set(sum, d);
162  }
163 }
164 
165 template <class SrcIter, class SrcAcc,
166  class DestIter, class DestAcc,
167  class KernelArray>
168 void
169 resamplingReduceLine2(SrcIter s, SrcIter send, SrcAcc src,
170  DestIter d, DestIter dend, DestAcc dest,
171  KernelArray const & kernels)
172 {
173  typedef typename KernelArray::value_type Kernel;
174  typedef typename KernelArray::const_reference KernelRef;
175  typedef typename Kernel::const_iterator KernelIter;
176 
177  KernelRef kernel = kernels[0];
178  KernelIter kbegin = kernel.center() + kernel.right();
179 
180  typedef typename
181  PromoteTraits<typename SrcAcc::value_type, typename Kernel::value_type>::Promote
182  TmpType;
183 
184  int wo = send - s;
185  int wn = dend - d;
186  int wo2 = 2*wo - 2;
187 
188  int ileft = kernel.right();
189  int iright = wo + kernel.left() - 1;
190  for(int i = 0; i < wn; ++i, ++d)
191  {
192  int is = 2 * i;
193  KernelIter k = kbegin;
194  TmpType sum = NumericTraits<TmpType>::zero();
195  if(is < ileft)
196  {
197  for(int m=is-kernel.right(); m <= is-kernel.left(); ++m, --k)
198  {
199  int mm = (m < 0)
200  ? -m
201  : m;
202  sum += *k * src(s, mm);
203  }
204  }
205  else if(is > iright)
206  {
207  for(int m=is-kernel.right(); m <= is-kernel.left(); ++m, --k)
208  {
209  int mm = (m >= wo)
210  ? wo2 - m
211  : m;
212  sum += *k * src(s, mm);
213  }
214  }
215  else
216  {
217  SrcIter ss = s + is - kernel.right();
218  for(int m = 0; m < kernel.size(); ++m, --k, ++ss)
219  {
220  sum += *k * src(ss);
221  }
222  }
223  dest.set(sum, d);
224  }
225 }
226 
227 /** \addtogroup ResamplingConvolutionFilters Resampling Convolution Filters
228 
229  These functions implement the convolution operation when the source and target images
230  have different sizes. This is realized by accessing a continuous kernel at the
231  appropriate non-integer positions. The technique is, for example, described in
232  D. Schumacher: <i>General Filtered Image Rescaling</i>, in: Graphics Gems III,
233  Academic Press, 1992.
234 */
235 //@{
236 
237 /********************************************************/
238 /* */
239 /* resamplingConvolveLine */
240 /* */
241 /********************************************************/
242 
243 /** \brief Performs a 1-dimensional resampling convolution of the source signal using the given
244  set of kernels.
245 
246  This function is mainly used internally: It is called for each dimension of a
247  higher dimensional array in order to perform a separable resize operation.
248 
249  <b> Declaration:</b>
250 
251  <b>\#include</b> <vigra/resampling_convolution.hxx><br/>
252  Namespace: vigra
253 
254  \code
255  namespace vigra {
256  template <class SrcIter, class SrcAcc,
257  class DestIter, class DestAcc,
258  class KernelArray,
259  class Functor>
260  void
261  resamplingConvolveLine(SrcIter s, SrcIter send, SrcAcc src,
262  DestIter d, DestIter dend, DestAcc dest,
263  KernelArray const & kernels,
264  Functor mapTargetToSourceCoordinate)
265  }
266  \endcode
267 
268 */
270 
271 template <class SrcIter, class SrcAcc,
272  class DestIter, class DestAcc,
273  class KernelArray,
274  class Functor>
275 void
276 resamplingConvolveLine(SrcIter s, SrcIter send, SrcAcc src,
277  DestIter d, DestIter dend, DestAcc dest,
278  KernelArray const & kernels,
279  Functor mapTargetToSourceCoordinate)
280 {
281  if(mapTargetToSourceCoordinate.isExpand2())
282  {
283  resamplingExpandLine2(s, send, src, d, dend, dest, kernels);
284  return;
285  }
286  if(mapTargetToSourceCoordinate.isReduce2())
287  {
288  resamplingReduceLine2(s, send, src, d, dend, dest, kernels);
289  return;
290  }
291 
292  typedef typename
293  NumericTraits<typename SrcAcc::value_type>::RealPromote
294  TmpType;
295  typedef typename KernelArray::value_type Kernel;
296  typedef typename Kernel::const_iterator KernelIter;
297 
298  int wo = send - s;
299  int wn = dend - d;
300  int wo2 = 2*wo - 2;
301 
302  int i;
303  typename KernelArray::const_iterator kernel = kernels.begin();
304  for(i=0; i<wn; ++i, ++d, ++kernel)
305  {
306  // use the kernels periodically
307  if(kernel == kernels.end())
308  kernel = kernels.begin();
309 
310  // calculate current target point into source location
311  int is = mapTargetToSourceCoordinate(i);
312 
313  TmpType sum = NumericTraits<TmpType>::zero();
314 
315  int lbound = is - kernel->right(),
316  hbound = is - kernel->left();
317 
318  KernelIter k = kernel->center() + kernel->right();
319  if(lbound < 0 || hbound >= wo)
320  {
321  vigra_precondition(-lbound < wo && wo2 - hbound >= 0,
322  "resamplingConvolveLine(): kernel or offset larger than image.");
323  for(int m=lbound; m <= hbound; ++m, --k)
324  {
325  int mm = (m < 0) ?
326  -m :
327  (m >= wo) ?
328  wo2 - m :
329  m;
330  sum = TmpType(sum + *k * src(s, mm));
331  }
332  }
333  else
334  {
335  SrcIter ss = s + lbound;
336  SrcIter ssend = s + hbound;
337 
338  for(; ss <= ssend; ++ss, --k)
339  {
340  sum = TmpType(sum + *k * src(ss));
341  }
342  }
343 
344  dest.set(sum, d);
345  }
346 }
347 
348 template <class Kernel, class MapCoordinate, class KernelArray>
349 void
350 createResamplingKernels(Kernel const & kernel,
351  MapCoordinate const & mapCoordinate, KernelArray & kernels)
352 {
353  for(unsigned int idest = 0; idest < kernels.size(); ++idest)
354  {
355  int isrc = mapCoordinate(idest);
356  double idsrc = mapCoordinate.toDouble(idest);
357  double offset = idsrc - isrc;
358  double radius = kernel.radius();
359  int left = std::min(0, int(ceil(-radius - offset)));
360  int right = std::max(0, int(floor(radius - offset)));
361  kernels[idest].initExplicitly(left, right);
362 
363  double x = left + offset;
364  for(int i = left; i <= right; ++i, ++x)
365  kernels[idest][i] = kernel(x);
366  kernels[idest].normalize(1.0, kernel.derivativeOrder(), offset);
367  }
368 }
369 
370 /** \brief Apply a resampling filter in the x-direction.
371 
372  This function implements a convolution operation in x-direction
373  (i.e. applies a 1D filter to every row) where the width of the source
374  and destination images differ. This is typically used to avoid aliasing if
375  the image is scaled down, or to interpolate smoothly if the image is scaled up.
376  The target coordinates are transformed into source coordinates by
377 
378  \code
379  xsource = (xtarget - offset) / samplingRatio
380  \endcode
381 
382  The <tt>samplingRatio</tt> and <tt>offset</tt> must be given as \ref vigra::Rational
383  in order to avoid rounding errors in this transformation. It is required that for all
384  pixels of the target image, <tt>xsource</tt> remains within the range of the source
385  image (i.e. <tt>0 <= xsource <= sourceWidth-1</tt>. Since <tt>xsource</tt> is
386  in general not an integer, the <tt>kernel</tt> must be a functor that can be accessed at
387  arbitrary (<tt>double</tt>) coordinates. It must also provide a member function <tt>radius()</tt>
388  which specifies the support (non-zero interval) of the kernel. VIGRA already
389  provides a number of suitable functors, e.g. \ref vigra::Gaussian, \ref vigra::BSpline
390  \ref vigra::CatmullRomSpline, and \ref vigra::CoscotFunction. The function
391  \ref resizeImageSplineInterpolation() is implemented by means of resamplingConvolveX() and
392  resamplingConvolveY().
393 
394  <b> Declarations:</b>
395 
396  pass 2D array views:
397  \code
398  namespace vigra {
399  template <class T1, class S1,
400  class T2, class S2,
401  class Kernel>
402  void
403  resamplingConvolveX(MultiArrayView<2, T1, S1> const & src,
404  MultiArrayView<2, T2, S2> dest,
405  Kernel const & kernel,
406  Rational<int> const & samplingRatio, Rational<int> const & offset);
407  }
408  \endcode
409 
410  \deprecatedAPI{resamplingConvolveX}
411  pass \ref ImageIterators and \ref DataAccessors :
412  \code
413  namespace vigra {
414  template <class SrcIter, class SrcAcc,
415  class DestIter, class DestAcc,
416  class Kernel>
417  void
418  resamplingConvolveX(SrcIter sul, SrcIter slr, SrcAcc src,
419  DestIter dul, DestIter dlr, DestAcc dest,
420  Kernel const & kernel,
421  Rational<int> const & samplingRatio, Rational<int> const & offset);
422  }
423  \endcode
424  use argument objects in conjunction with \ref ArgumentObjectFactories :
425  \code
426  namespace vigra {
427  template <class SrcIter, class SrcAcc,
428  class DestIter, class DestAcc,
429  class Kernel>
430  void
431  resamplingConvolveX(triple<SrcIter, SrcIter, SrcAcc> src,
432  triple<DestIter, DestIter, DestAcc> dest,
433  Kernel const & kernel,
434  Rational<int> const & samplingRatio, Rational<int> const & offset);
435  }
436  \endcode
437  \deprecatedEnd
438 
439  <b> Usage:</b>
440 
441  <b>\#include</b> <vigra/resampling_convolution.hxx><br/>
442  Namespace: vigra
443 
444  \code
445  Rational<int> ratio(2), offset(0);
446 
447  MultiArray<2, float> src(w,h),
448  dest(rational_cast<int>(ratio*w), h);
449 
450  float sigma = 2.0;
451  Gaussian<float> smooth(sigma);
452  ...
453 
454  // simultaneously enlarge and smooth source image
455  resamplingConvolveX(src, dest,
456  smooth, ratio, offset);
457  \endcode
458 
459  \deprecatedUsage{resamplingConvolveX}
460  \code
461  Rational<int> ratio(2), offset(0);
462 
463  FImage src(w,h),
464  dest(rational_cast<int>(ratio*w), h);
465 
466  float sigma = 2.0;
467  Gaussian<float> smooth(sigma);
468  ...
469 
470  // simultaneously enlarge and smooth source image
471  resamplingConvolveX(srcImageRange(src), destImageRange(dest),
472  smooth, ratio, offset);
473  \endcode
474  <b> Required Interface:</b>
475  \code
476  Kernel kernel;
477  int kernelRadius = kernel.radius();
478  double x = ...; // must be <= radius()
479  double value = kernel(x);
480  \endcode
481  \deprecatedEnd
482 */
484 
485 template <class SrcIter, class SrcAcc,
486  class DestIter, class DestAcc,
487  class Kernel>
488 void
489 resamplingConvolveX(SrcIter sul, SrcIter slr, SrcAcc src,
490  DestIter dul, DestIter dlr, DestAcc dest,
491  Kernel const & kernel,
492  Rational<int> const & samplingRatio, Rational<int> const & offset)
493 {
494  int wold = slr.x - sul.x;
495  int wnew = dlr.x - dul.x;
496 
497  vigra_precondition(!samplingRatio.is_inf() && samplingRatio > 0,
498  "resamplingConvolveX(): sampling ratio must be > 0 and < infinity");
499  vigra_precondition(!offset.is_inf(),
500  "resamplingConvolveX(): offset must be < infinity");
501 
502  int period = lcm(samplingRatio.numerator(), samplingRatio.denominator());
503  resampling_detail::MapTargetToSourceCoordinate mapCoordinate(samplingRatio, offset);
504 
505  ArrayVector<Kernel1D<double> > kernels(period);
506 
507  createResamplingKernels(kernel, mapCoordinate, kernels);
508 
509  for(; sul.y < slr.y; ++sul.y, ++dul.y)
510  {
511  typename SrcIter::row_iterator sr = sul.rowIterator();
512  typename DestIter::row_iterator dr = dul.rowIterator();
513  resamplingConvolveLine(sr, sr+wold, src, dr, dr+wnew, dest,
514  kernels, mapCoordinate);
515  }
516 }
517 
518 template <class SrcIter, class SrcAcc,
519  class DestIter, class DestAcc,
520  class Kernel>
521 inline void
522 resamplingConvolveX(triple<SrcIter, SrcIter, SrcAcc> src,
523  triple<DestIter, DestIter, DestAcc> dest,
524  Kernel const & kernel,
525  Rational<int> const & samplingRatio, Rational<int> const & offset)
526 {
527  resamplingConvolveX(src.first, src.second, src.third,
528  dest.first, dest.second, dest.third,
529  kernel, samplingRatio, offset);
530 }
531 
532 template <class T1, class S1,
533  class T2, class S2,
534  class Kernel>
535 inline void
536 resamplingConvolveX(MultiArrayView<2, T1, S1> const & src,
537  MultiArrayView<2, T2, S2> dest,
538  Kernel const & kernel,
539  Rational<int> const & samplingRatio, Rational<int> const & offset)
540 {
541  resamplingConvolveX(srcImageRange(src),
542  destImageRange(dest),
543  kernel, samplingRatio, offset);
544 }
545 
546 /********************************************************/
547 /* */
548 /* resamplingConvolveY */
549 /* */
550 /********************************************************/
551 
552 /** \brief Apply a resampling filter in the y-direction.
553 
554  This function implements a convolution operation in y-direction
555  (i.e. applies a 1D filter to every column) where the height of the source
556  and destination images differ. This is typically used to avoid aliasing if
557  the image is scaled down, or to interpolate smoothly if the image is scaled up.
558  The target coordinates are transformed into source coordinates by
559 
560  \code
561  ysource = (ytarget - offset) / samplingRatio
562  \endcode
563 
564  The <tt>samplingRatio</tt> and <tt>offset</tt> must be given as \ref vigra::Rational
565  in order to avoid rounding errors in this transformation. It is required that for all
566  pixels of the target image, <tt>ysource</tt> remains within the range of the source
567  image (i.e. <tt>0 <= ysource <= sourceHeight-1</tt>. Since <tt>ysource</tt> is
568  in general not an integer, the <tt>kernel</tt> must be a functor that can be accessed at
569  arbitrary (<tt>double</tt>) coordinates. It must also provide a member function <tt>radius()</tt>
570  which specifies the support (non-zero interval) of the kernel. VIGRA already
571  provides a number of suitable functors, e.g. \ref vigra::Gaussian, \ref vigra::BSpline
572  \ref vigra::CatmullRomSpline, and \ref vigra::CoscotFunction. The function
573  \ref resizeImageSplineInterpolation() is implemented by means of resamplingConvolveX() and
574  resamplingConvolveY().
575 
576  <b> Declarations:</b>
577 
578  pass 2D array views:
579  \code
580  namespace vigra {
581  template <class T1, class S1,
582  class T2, class S2,
583  class Kernel>
584  void
585  resamplingConvolveY(MultiArrayView<2, T1, S1> const & src,
586  MultiArrayView<2, T2, S2> dest,
587  Kernel const & kernel,
588  Rational<int> const & samplingRatio, Rational<int> const & offset);
589  }
590  \endcode
591 
592  \deprecatedAPI{resamplingConvolveY}
593  pass \ref ImageIterators and \ref DataAccessors :
594  \code
595  namespace vigra {
596  template <class SrcIter, class SrcAcc,
597  class DestIter, class DestAcc,
598  class Kernel>
599  void
600  resamplingConvolveY(SrcIter sul, SrcIter slr, SrcAcc src,
601  DestIter dul, DestIter dlr, DestAcc dest,
602  Kernel const & kernel,
603  Rational<int> const & samplingRatio, Rational<int> const & offset);
604  }
605  \endcode
606  use argument objects in conjunction with \ref ArgumentObjectFactories :
607  \code
608  namespace vigra {
609  template <class SrcIter, class SrcAcc,
610  class DestIter, class DestAcc,
611  class Kernel>
612  void
613  resamplingConvolveY(triple<SrcIter, SrcIter, SrcAcc> src,
614  triple<DestIter, DestIter, DestAcc> dest,
615  Kernel const & kernel,
616  Rational<int> const & samplingRatio, Rational<int> const & offset);
617  }
618  \endcode
619  \deprecatedEnd
620 
621  <b> Usage:</b>
622 
623  <b>\#include</b> <vigra/resampling_convolution.hxx><br/>
624  Namespace: vigra
625 
626  \code
627  Rational<int> ratio(2), offset(0);
628 
629  MultiArray<2, float> src(w,h),
630  dest(w, rational_cast<int>(ratio*h));
631 
632  float sigma = 2.0;
633  Gaussian<float> smooth(sigma);
634  ...
635 
636  // simultaneously enlarge and smooth source image
637  resamplingConvolveY(src, dest,
638  smooth, ratio, offset);
639  \endcode
640 
641  \deprecatedUsage{resamplingConvolveY}
642  \code
643  Rational<int> ratio(2), offset(0);
644 
645  FImage src(w,h),
646  dest(w, rational_cast<int>(ratio*h));
647 
648  float sigma = 2.0;
649  Gaussian<float> smooth(sigma);
650  ...
651 
652  // simultaneously enlarge and smooth source image
653  resamplingConvolveY(srcImageRange(src), destImageRange(dest),
654  smooth, ratio, offset);
655  \endcode
656  <b> Required Interface:</b>
657  \code
658  Kernel kernel;
659  int kernelRadius = kernel.radius();
660  double y = ...; // must be <= radius()
661  double value = kernel(y);
662  \endcode
663  \deprecatedEnd
664 */
666 
667 template <class SrcIter, class SrcAcc,
668  class DestIter, class DestAcc,
669  class Kernel>
670 void
671 resamplingConvolveY(SrcIter sul, SrcIter slr, SrcAcc src,
672  DestIter dul, DestIter dlr, DestAcc dest,
673  Kernel const & kernel,
674  Rational<int> const & samplingRatio, Rational<int> const & offset)
675 {
676  int hold = slr.y - sul.y;
677  int hnew = dlr.y - dul.y;
678 
679  vigra_precondition(!samplingRatio.is_inf() && samplingRatio > 0,
680  "resamplingConvolveY(): sampling ratio must be > 0 and < infinity");
681  vigra_precondition(!offset.is_inf(),
682  "resamplingConvolveY(): offset must be < infinity");
683 
684  int period = lcm(samplingRatio.numerator(), samplingRatio.denominator());
685 
686  resampling_detail::MapTargetToSourceCoordinate mapCoordinate(samplingRatio, offset);
687 
688  ArrayVector<Kernel1D<double> > kernels(period);
689 
690  createResamplingKernels(kernel, mapCoordinate, kernels);
691 
692  for(; sul.x < slr.x; ++sul.x, ++dul.x)
693  {
694  typename SrcIter::column_iterator sc = sul.columnIterator();
695  typename DestIter::column_iterator dc = dul.columnIterator();
696  resamplingConvolveLine(sc, sc+hold, src, dc, dc+hnew, dest,
697  kernels, mapCoordinate);
698  }
699 }
700 
701 template <class SrcIter, class SrcAccessor,
702  class DestIter, class DestAccessor,
703  class Kernel>
704 inline void
705 resamplingConvolveY(triple<SrcIter, SrcIter, SrcAccessor> src,
706  triple<DestIter, DestIter, DestAccessor> dest,
707  Kernel const & kernel,
708  Rational<int> const & samplingRatio, Rational<int> const & offset)
709 {
710  resamplingConvolveY(src.first, src.second, src.third,
711  dest.first, dest.second, dest.third,
712  kernel, samplingRatio, offset);
713 }
714 
715 template <class T1, class S1,
716  class T2, class S2,
717  class Kernel>
718 inline void
719 resamplingConvolveY(MultiArrayView<2, T1, S1> const & src,
720  MultiArrayView<2, T2, S2> dest,
721  Kernel const & kernel,
722  Rational<int> const & samplingRatio, Rational<int> const & offset)
723 {
724  resamplingConvolveY(srcImageRange(src),
725  destImageRange(dest),
726  kernel, samplingRatio, offset);
727 }
728 
729 /********************************************************/
730 /* */
731 /* resamplingConvolveImage */
732 /* */
733 /********************************************************/
734 
735 /** \brief Apply two separable resampling filters successively, the first in x-direction,
736  the second in y-direction.
737 
738  This function is a shorthand for the concatenation of a call to
739  \ref resamplingConvolveX() and \ref resamplingConvolveY()
740  with the given kernels. See there for detailed documentation.
741 
742  <b> Declarations:</b>
743 
744  pass 2D array views:
745  \code
746  namespace vigra {
747  template <class T1, class S1,
748  class T2, class S2,
749  class KernelX, class KernelY>
750  void
751  resamplingConvolveImage(MultiArrayView<2, T1, S1> const & src,
752  MultiArrayView<2, T2, S2> dest,
753  KernelX const & kx,
754  Rational<int> const & samplingRatioX, Rational<int> const & offsetX,
755  KernelY const & ky,
756  Rational<int> const & samplingRatioY, Rational<int> const & offsetY);
757  }
758  \endcode
759 
760  \deprecatedAPI{resamplingConvolveImage}
761  pass \ref ImageIterators and \ref DataAccessors :
762  \code
763  namespace vigra {
764  template <class SrcIterator, class SrcAccessor,
765  class DestIterator, class DestAccessor,
766  class KernelX, class KernelY>
767  void resamplingConvolveImage(SrcIterator sul,SrcIterator slr, SrcAccessor src,
768  DestIterator dul, DestIterator dlr, DestAccessor dest,
769  KernelX const & kx,
770  Rational<int> const & samplingRatioX, Rational<int> const & offsetX,
771  KernelY const & ky,
772  Rational<int> const & samplingRatioY, Rational<int> const & offsetY);
773  }
774  \endcode
775  use argument objects in conjunction with \ref ArgumentObjectFactories :
776  \code
777  namespace vigra {
778  template <class SrcIterator, class SrcAccessor,
779  class DestIterator, class DestAccessor,
780  class KernelX, class KernelY>
781  void
782  resamplingConvolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
783  triple<DestIterator, DestIterator, DestAccessor> dest,
784  KernelX const & kx,
785  Rational<int> const & samplingRatioX, Rational<int> const & offsetX,
786  KernelY const & ky,
787  Rational<int> const & samplingRatioY, Rational<int> const & offsetY);
788  }
789  \endcode
790  \deprecatedEnd
791 
792  <b> Usage:</b>
793 
794  <b>\#include</b> <vigra/resampling_convolution.hxx><br/>
795  Namespace: vigra
796 
797  \code
798  Rational<int> xratio(2), yratio(3), offset(0);
799 
800  MultiArray<2, float> src(w,h),
801  dest(rational_cast<int>(xratio*w), rational_cast<int>(yratio*h));
802 
803  float sigma = 2.0;
804  Gaussian<float> smooth(sigma);
805  ...
806 
807  // simultaneously enlarge and smooth source image
808  resamplingConvolveImage(src, dest,
809  smooth, xratio, offset,
810  smooth, yratio, offset);
811  \endcode
812 */
814 
815 template <class SrcIterator, class SrcAccessor,
816  class DestIterator, class DestAccessor,
817  class KernelX, class KernelY>
818 void resamplingConvolveImage(SrcIterator sul,SrcIterator slr, SrcAccessor src,
819  DestIterator dul, DestIterator dlr, DestAccessor dest,
820  KernelX const & kx,
821  Rational<int> const & samplingRatioX, Rational<int> const & offsetX,
822  KernelY const & ky,
823  Rational<int> const & samplingRatioY, Rational<int> const & offsetY)
824 {
825  typedef typename
826  NumericTraits<typename SrcAccessor::value_type>::RealPromote
827  TmpType;
828 
829  BasicImage<TmpType> tmp(dlr.x - dul.x, slr.y - sul.y);
830 
831  resamplingConvolveX(srcIterRange(sul, slr, src),
832  destImageRange(tmp),
833  kx, samplingRatioX, offsetX);
834  resamplingConvolveY(srcImageRange(tmp),
835  destIterRange(dul, dlr, dest),
836  ky, samplingRatioY, offsetY);
837 }
838 
839 template <class SrcIterator, class SrcAccessor,
840  class DestIterator, class DestAccessor,
841  class KernelX, class KernelY>
842 inline void
843 resamplingConvolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
844  triple<DestIterator, DestIterator, DestAccessor> dest,
845  KernelX const & kx,
846  Rational<int> const & samplingRatioX, Rational<int> const & offsetX,
847  KernelY const & ky,
848  Rational<int> const & samplingRatioY, Rational<int> const & offsetY)
849 {
850  resamplingConvolveImage(src.first, src.second, src.third,
851  dest.first, dest.second, dest.third,
852  kx, samplingRatioX, offsetX,
853  ky, samplingRatioY, offsetY);
854 }
855 
856 template <class T1, class S1,
857  class T2, class S2,
858  class KernelX, class KernelY>
859 inline void
860 resamplingConvolveImage(MultiArrayView<2, T1, S1> const & src,
861  MultiArrayView<2, T2, S2> dest,
862  KernelX const & kx,
863  Rational<int> const & samplingRatioX, Rational<int> const & offsetX,
864  KernelY const & ky,
865  Rational<int> const & samplingRatioY, Rational<int> const & offsetY)
866 {
867  resamplingConvolveImage(srcImageRange(src),
868  destImageRange(dest),
869  kx, samplingRatioX, offsetX,
870  ky, samplingRatioY, offsetY);
871 }
872 
873 /** \brief Two-fold down-sampling for image pyramid construction.
874 
875  This function implements the reduction by one resolution level (first signature)
876  or across several pyramid levels (last signature) of a Gaussian pyramid as described in
877 
878  P. Burt, E. Adelson: <i>"The Laplacian Pyramid as a Compact Image Code"</i>, IEEE Trans. Communications, 9(4):532-540, 1983
879 
880  That is, it applies the smoothing filter
881  \code
882  [0.25 - centerValue / 2.0, 0.25, centerValue, 0.25, 0.25 - centerValue / 2.0]
883  \endcode
884  to the source image and then copies all pixels with even coordinates to the destination
885  image. The destination image shape must be <tt>dest_shape = ceil(src_shape / 2.0)</tt>.
886  <tt>centerValue</tt> must be between 0.25 and 0.5 and determines the strength of smoothing
887  (bigger values correspond to less smoothing). If <tt>toLevel - fromLevel > 1</tt> in the
888  pyramid variant of the function, this process is repeated until <tt>toLevel</tt> is
889  reached.
890 
891  Typically, this functions is used in connection with a \ref vigra::ImagePyramid
892  (last signature below) to perform several levels of reduction in one go.
893 
894  <b> Declarations:</b>
895 
896  <b>\#include</b> <vigra/resampling_convolution.hxx><br>
897  Namespace: vigra
898 
899  pass 2D array views:
900  \code
901  namespace vigra {
902  template <class SrcIterator, class SrcAccessor,
903  class DestIterator, class DestAccessor>
904  void pyramidReduceBurtFilter(SrcIterator sul, SrcIterator slr, SrcAccessor src,
905  DestIterator dul, DestIterator dlr, DestAccessor dest,
906  double centerValue = 0.4);
907  }
908  \endcode
909 
910  \deprecatedAPI{pyramidReduceBurtFilter}
911  pass \ref ImageIterators and \ref DataAccessors :
912  \code
913  namespace vigra {
914  template <class SrcIterator, class SrcAccessor,
915  class DestIterator, class DestAccessor>
916  void pyramidReduceBurtFilter(SrcIterator sul, SrcIterator slr, SrcAccessor src,
917  DestIterator dul, DestIterator dlr, DestAccessor dest,
918  double centerValue = 0.4);
919  }
920  \endcode
921  use argument objects in conjunction with \ref ArgumentObjectFactories :
922  \code
923  namespace vigra {
924  template <class SrcIterator, class SrcAccessor,
925  class DestIterator, class DestAccessor>
926  void pyramidReduceBurtFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
927  triple<DestIterator, DestIterator, DestAccessor> dest,
928  double centerValue = 0.4);
929  }
930  \endcode
931  \deprecatedEnd
932 
933  use a \ref vigra::ImagePyramid :
934  \code
935  namespace vigra {
936  template <class Image, class Alloc>
937  void pyramidReduceBurtFilter(ImagePyramid<Image, Alloc> & pyramid,
938  int fromLevel, int toLevel,
939  double centerValue = 0.4);
940  }
941  \endcode
942 */
944 
945 template <class SrcIterator, class SrcAccessor,
946  class DestIterator, class DestAccessor>
947 void pyramidReduceBurtFilter(SrcIterator sul, SrcIterator slr, SrcAccessor src,
948  DestIterator dul, DestIterator dlr, DestAccessor dest,
949  double centerValue = 0.4)
950 {
951  vigra_precondition(0.25 <= centerValue && centerValue <= 0.5,
952  "pyramidReduceBurtFilter(): centerValue must be between 0.25 and 0.5.");
953 
954  int wold = slr.x - sul.x;
955  int wnew = dlr.x - dul.x;
956  int hold = slr.y - sul.y;
957  int hnew = dlr.y - dul.y;
958 
959  vigra_precondition(wnew == (wold + 1) / 2 && hnew == (hold + 1) / 2,
960  "pyramidReduceBurtFilter(): destSize = ceil(srcSize / 2) required.");
961 
962  Rational<int> samplingRatio(1,2), offset(0);
963  resampling_detail::MapTargetToSourceCoordinate mapCoordinate(samplingRatio, offset);
964 
965  ArrayVector<Kernel1D<double> > kernels(1);
966  kernels[0].initExplicitly(-2, 2) = 0.25 - centerValue / 2.0, 0.25, centerValue, 0.25, 0.25 - centerValue / 2.0;
967 
968  typedef typename
969  NumericTraits<typename SrcAccessor::value_type>::RealPromote
970  TmpType;
971  typedef BasicImage<TmpType> TmpImage;
972  typedef typename TmpImage::traverser TmpIterator;
973 
974  BasicImage<TmpType> tmp(wnew, hold);
975 
976  TmpIterator tul = tmp.upperLeft();
977 
978  for(; sul.y < slr.y; ++sul.y, ++tul.y)
979  {
980  typename SrcIterator::row_iterator sr = sul.rowIterator();
981  typename TmpIterator::row_iterator tr = tul.rowIterator();
982  // FIXME: replace with reduceLineBurtFilter()
983  resamplingConvolveLine(sr, sr+wold, src, tr, tr+wnew, tmp.accessor(),
984  kernels, mapCoordinate);
985  }
986 
987  tul = tmp.upperLeft();
988 
989  for(; dul.x < dlr.x; ++dul.x, ++tul.x)
990  {
991  typename DestIterator::column_iterator dc = dul.columnIterator();
992  typename TmpIterator::column_iterator tc = tul.columnIterator();
993  resamplingConvolveLine(tc, tc+hold, tmp.accessor(), dc, dc+hnew, dest,
994  kernels, mapCoordinate);
995  }
996 }
997 
998 template <class SrcIterator, class SrcAccessor,
999  class DestIterator, class DestAccessor>
1000 inline
1001 void pyramidReduceBurtFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1002  triple<DestIterator, DestIterator, DestAccessor> dest,
1003  double centerValue = 0.4)
1004 {
1005  pyramidReduceBurtFilter(src.first, src.second, src.third,
1006  dest.first, dest.second, dest.third, centerValue);
1007 }
1008 
1009 template <class Image, class Alloc>
1010 inline
1011 void pyramidReduceBurtFilter(ImagePyramid<Image, Alloc> & pyramid,
1012  int fromLevel, int toLevel,
1013  double centerValue = 0.4)
1014 {
1015  vigra_precondition(fromLevel < toLevel,
1016  "pyramidReduceBurtFilter(): fromLevel must be smaller than toLevel.");
1017  vigra_precondition(pyramid.lowestLevel() <= fromLevel && toLevel <= pyramid.highestLevel(),
1018  "pyramidReduceBurtFilter(): fromLevel and toLevel must be between the lowest and highest pyramid levels (inclusive).");
1019 
1020  for(int i=fromLevel+1; i <= toLevel; ++i)
1021  pyramidReduceBurtFilter(srcImageRange(pyramid[i-1]), destImageRange(pyramid[i]), centerValue);
1022 }
1023 
1024 /** \brief Two-fold up-sampling for image pyramid reconstruction.
1025 
1026  This function implements the expansion by one resolution level (first signature)
1027  or across several pyramid levels (last signature) of a Gaussian pyramid as described in
1028 
1029  P. Burt, E. Adelson: <i>"The Laplacian Pyramid as a Compact Image Code"</i>, IEEE Trans. Communications, 9(4):532-540, 1983
1030 
1031  That is, the function first places the pixel values of the low-resolution
1032  image at the even pixel coordinates of the high-resolution image (pixels with
1033  at least one odd coordinate are zero-initialized) and then applies the
1034  interpolation filter
1035  \code
1036  [0.5 - centerValue, 0.5, 2*centerValue, 0.5, 0.5 - centerValue]
1037  \endcode
1038  to the high-resolution image. The source image shape must be
1039  <tt>src_shape = ceil(dest_shape / 2.0)</tt>.
1040  <tt>centerValue</tt> must be between 0.25 and 0.5 and determines the sharpness
1041  of the interpolation (bigger values correspond to sharper images).
1042  If <tt>fromLevel - toLevel > 1</tt> in the pyramid variant of the function,
1043  this process is repeated until <tt>toLevel</tt> is reached.
1044 
1045  Typically, this functions is used in connection with a \ref vigra::ImagePyramid
1046  (last signature below) to perform several levels of expansion in one go.
1047 
1048  <b> Declarations:</b>
1049 
1050  <b>\#include</b> <vigra/resampling_convolution.hxx><br>
1051  Namespace: vigra
1052 
1053  pass 2D array views:
1054  \code
1055  namespace vigra {
1056  template <class SrcIterator, class SrcAccessor,
1057  class DestIterator, class DestAccessor>
1058  void pyramidExpandBurtFilter(SrcIterator sul, SrcIterator slr, SrcAccessor src,
1059  DestIterator dul, DestIterator dlr, DestAccessor dest,
1060  double centerValue = 0.4);
1061  }
1062  \endcode
1063 
1064  \deprecatedAPI{pyramidExpandBurtFilter}
1065  pass \ref ImageIterators and \ref DataAccessors :
1066  \code
1067  namespace vigra {
1068  template <class SrcIterator, class SrcAccessor,
1069  class DestIterator, class DestAccessor>
1070  void pyramidExpandBurtFilter(SrcIterator sul, SrcIterator slr, SrcAccessor src,
1071  DestIterator dul, DestIterator dlr, DestAccessor dest,
1072  double centerValue = 0.4);
1073  }
1074  \endcode
1075  use argument objects in conjunction with \ref ArgumentObjectFactories :
1076  \code
1077  namespace vigra {
1078  template <class SrcIterator, class SrcAccessor,
1079  class DestIterator, class DestAccessor>
1080  void pyramidExpandBurtFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1081  triple<DestIterator, DestIterator, DestAccessor> dest,
1082  double centerValue = 0.4);
1083  }
1084  \endcode
1085  \deprecatedEnd
1086 
1087  use a \ref vigra::ImagePyramid :
1088  \code
1089  namespace vigra {
1090  template <class Image, class Alloc>
1091  void pyramidExpandBurtFilter(ImagePyramid<Image, Alloc> & pyramid,
1092  int fromLevel, int toLevel,
1093  double centerValue = 0.4);
1094  }
1095  \endcode
1096 */
1098 
1099 template <class SrcIterator, class SrcAccessor,
1100  class DestIterator, class DestAccessor>
1101 void pyramidExpandBurtFilter(SrcIterator sul, SrcIterator slr, SrcAccessor src,
1102  DestIterator dul, DestIterator dlr, DestAccessor dest,
1103  double centerValue = 0.4)
1104 {
1105  vigra_precondition(0.25 <= centerValue && centerValue <= 0.5,
1106  "pyramidExpandBurtFilter(): centerValue must be between 0.25 and 0.5.");
1107 
1108  int wold = slr.x - sul.x;
1109  int wnew = dlr.x - dul.x;
1110  int hold = slr.y - sul.y;
1111  int hnew = dlr.y - dul.y;
1112 
1113  vigra_precondition(wold == (wnew + 1) / 2 && hold == (hnew + 1) / 2,
1114  "pyramidExpandBurtFilter(): oldSize = ceil(newSize / 2) required.");
1115 
1116  Rational<int> samplingRatio(2), offset(0);
1117  resampling_detail::MapTargetToSourceCoordinate mapCoordinate(samplingRatio, offset);
1118 
1119  ArrayVector<Kernel1D<double> > kernels(2);
1120  kernels[0].initExplicitly(-1, 1) = 0.5 - centerValue, 2.0*centerValue, 0.5 - centerValue;
1121  kernels[1].initExplicitly(-1, 0) = 0.5, 0.5;
1122 
1123  typedef typename
1124  NumericTraits<typename SrcAccessor::value_type>::RealPromote
1125  TmpType;
1126  typedef BasicImage<TmpType> TmpImage;
1127  typedef typename TmpImage::traverser TmpIterator;
1128 
1129  BasicImage<TmpType> tmp(wnew, hold);
1130 
1131  TmpIterator tul = tmp.upperLeft();
1132 
1133  for(; sul.y < slr.y; ++sul.y, ++tul.y)
1134  {
1135  typename SrcIterator::row_iterator sr = sul.rowIterator();
1136  typename TmpIterator::row_iterator tr = tul.rowIterator();
1137  // FIXME: replace with expandLineBurtFilter()
1138  resamplingConvolveLine(sr, sr+wold, src, tr, tr+wnew, tmp.accessor(),
1139  kernels, mapCoordinate);
1140  }
1141 
1142  tul = tmp.upperLeft();
1143 
1144  for(; dul.x < dlr.x; ++dul.x, ++tul.x)
1145  {
1146  typename DestIterator::column_iterator dc = dul.columnIterator();
1147  typename TmpIterator::column_iterator tc = tul.columnIterator();
1148  resamplingConvolveLine(tc, tc+hold, tmp.accessor(), dc, dc+hnew, dest,
1149  kernels, mapCoordinate);
1150  }
1151 }
1152 
1153 template <class SrcIterator, class SrcAccessor,
1154  class DestIterator, class DestAccessor>
1155 inline
1156 void pyramidExpandBurtFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1157  triple<DestIterator, DestIterator, DestAccessor> dest,
1158  double centerValue = 0.4)
1159 {
1160  pyramidExpandBurtFilter(src.first, src.second, src.third,
1161  dest.first, dest.second, dest.third, centerValue);
1162 }
1163 
1164 
1165 template <class Image, class Alloc>
1166 inline
1167 void pyramidExpandBurtFilter(ImagePyramid<Image, Alloc> & pyramid, int fromLevel, int toLevel,
1168  double centerValue = 0.4)
1169 {
1170  vigra_precondition(fromLevel > toLevel,
1171  "pyramidExpandBurtFilter(): fromLevel must be larger than toLevel.");
1172  vigra_precondition(pyramid.lowestLevel() <= toLevel && fromLevel <= pyramid.highestLevel(),
1173  "pyramidExpandBurtFilter(): fromLevel and toLevel must be between the lowest and highest pyramid levels (inclusive).");
1174 
1175  for(int i=fromLevel-1; i >= toLevel; --i)
1176  pyramidExpandBurtFilter(srcImageRange(pyramid[i+1]), destImageRange(pyramid[i]), centerValue);
1177 }
1178 
1179 /** \brief Create a Laplacian pyramid.
1180 
1181  This function implements the reduction across several resolution levels of
1182  a Laplacian pyramid as described in
1183 
1184  P. Burt, E. Adelson: <i>"The Laplacian Pyramid as a Compact Image Code"</i>, IEEE Trans. Communications, 9(4):532-540, 1983
1185 
1186  It first creates a Gaussian pyramid using \ref pyramidReduceBurtFilter(), then
1187  upsamples each level once using \ref pyramidExpandBurtFilter(), and finally
1188  stores the difference between the upsampled and original versions of
1189  each level (i.e. the Laplacian of Gaussian is approximated by a difference
1190  of Gaussian).
1191 
1192  <b>\#include</b> <vigra/resampling_convolution.hxx><br>
1193  Namespace: vigra
1194 */
1195 template <class Image, class Alloc>
1196 inline void
1198  int fromLevel, int toLevel,
1199  double centerValue = 0.4)
1200 {
1201  using namespace functor;
1202 
1203  pyramidReduceBurtFilter(pyramid, fromLevel, toLevel, centerValue);
1204  for(int i=fromLevel; i < toLevel; ++i)
1205  {
1206  typename ImagePyramid<Image, Alloc>::value_type tmpImage(pyramid[i].size());
1207  pyramidExpandBurtFilter(srcImageRange(pyramid[i+1]), destImageRange(tmpImage), centerValue);
1208  combineTwoImages(srcImageRange(tmpImage), srcImage(pyramid[i]), destImage(pyramid[i]),
1209  Arg1() - Arg2());
1210  }
1211 }
1212 
1213 /** \brief Reconstruct a Laplacian pyramid.
1214 
1215  This function implements the reconstruction of a Gaussian pyramid
1216  across several resolution levels of a Laplacian pyramid as described in
1217 
1218  P. Burt, E. Adelson: <i>"The Laplacian Pyramid as a Compact Image Code"</i>, IEEE Trans. Communications, 9(4):532-540, 1983
1219 
1220  At each level starting from <tt>fromLevel</tt>, this function calls
1221  \ref pyramidExpandBurtFilter() to interpolate the image to the next highest
1222  resolution, and then adds the interpolated image to the image stored at the
1223  next level.
1224 
1225  <b>\#include</b> <vigra/resampling_convolution.hxx><br>
1226  Namespace: vigra
1227 */
1228 template <class Image, class Alloc>
1229 inline void
1231  int fromLevel, int toLevel,
1232  double centerValue = 0.4)
1233 {
1234  using namespace functor;
1235 
1236  vigra_precondition(fromLevel > toLevel,
1237  "pyramidExpandBurtLaplacian(): fromLevel must be larger than toLevel.");
1238  vigra_precondition(pyramid.lowestLevel() <= toLevel && fromLevel <= pyramid.highestLevel(),
1239  "pyramidExpandBurtLaplacian(): fromLevel and toLevel must be between the lowest and highest pyramid levels (inclusive).");
1240 
1241  for(int i=fromLevel-1; i >= toLevel; --i)
1242  {
1243  typename ImagePyramid<Image, Alloc>::value_type tmpImage(pyramid[i].size());
1244  pyramidExpandBurtFilter(srcImageRange(pyramid[i+1]), destImageRange(tmpImage), centerValue);
1245  combineTwoImages(srcImageRange(tmpImage), srcImage(pyramid[i]), destImage(pyramid[i]),
1246  Arg1() - Arg2());
1247  }
1248 }
1249 
1250 //@}
1251 
1252 } // namespace vigra
1253 
1254 
1255 #endif /* VIGRA_RESAMPLING_CONVOLUTION_HXX */
void resamplingConvolveX(...)
Apply a resampling filter in the x-direction.
void pyramidExpandBurtFilter(...)
Two-fold up-sampling for image pyramid reconstruction.
ImageType value_type
Definition: imagecontainer.hxx:479
void pyramidExpandBurtLaplacian(ImagePyramid< Image, Alloc > &pyramid, int fromLevel, int toLevel, double centerValue=0.4)
Reconstruct a Laplacian pyramid.
Definition: resampling_convolution.hxx:1230
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements
Definition: tinyvector.hxx:2073
void resamplingConvolveImage(...)
Apply two separable resampling filters successively, the first in x-direction, the second in y-direct...
IntType lcm(IntType n, IntType m)
Definition: rational.hxx:122
void combineTwoImages(...)
Combine two source images into destination image.
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
void pyramidReduceBurtFilter(...)
Two-fold down-sampling for image pyramid construction.
int highestLevel() const
Definition: imagecontainer.hxx:576
void resamplingConvolveY(...)
Apply a resampling filter in the y-direction.
int lowestLevel() const
Definition: imagecontainer.hxx:569
void pyramidReduceBurtLaplacian(ImagePyramid< Image, Alloc > &pyramid, int fromLevel, int toLevel, double centerValue=0.4)
Create a Laplacian pyramid.
Definition: resampling_convolution.hxx:1197
int ceil(FixedPoint< IntBits, FracBits > v)
rounding up.
Definition: fixedpoint.hxx:675
void resamplingConvolveLine(...)
Performs a 1-dimensional resampling convolution of the source signal using the given set of kernels...
Class template for logarithmically tapering image pyramids.
Definition: imagecontainer.hxx:468
int floor(FixedPoint< IntBits, FracBits > v)
rounding down.
Definition: fixedpoint.hxx:667

© 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)