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

transformimage.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 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_TRANSFORMIMAGE_HXX
38 #define VIGRA_TRANSFORMIMAGE_HXX
39 
40 #include "utilities.hxx"
41 #include "numerictraits.hxx"
42 #include "iteratortraits.hxx"
43 #include "rgbvalue.hxx"
44 #include "functortraits.hxx"
45 #include "inspectimage.hxx"
46 
47 namespace vigra {
48 
49 /** \addtogroup TransformAlgo Algorithms to Transform Images
50  Apply functor to calculate a pixelwise transformation of one image
51 
52  @{
53 */
54 
55 /********************************************************/
56 /* */
57 /* transformLine */
58 /* */
59 /********************************************************/
60 
61 template <class SrcIterator, class SrcAccessor,
62  class DestIterator, class DestAccessor, class Functor>
63 void
64 transformLine(SrcIterator s,
65  SrcIterator send, SrcAccessor src,
66  DestIterator d, DestAccessor dest,
67  Functor const & f)
68 {
69  for(; s != send; ++s, ++d)
70  dest.set(f(src(s)), d);
71 }
72 
73 template <class SrcIterator, class SrcAccessor,
74  class MaskIterator, class MaskAccessor,
75  class DestIterator, class DestAccessor,
76  class Functor>
77 void
78 transformLineIf(SrcIterator s,
79  SrcIterator send, SrcAccessor src,
80  MaskIterator m, MaskAccessor mask,
81  DestIterator d, DestAccessor dest,
82  Functor const & f)
83 {
84  for(; s != send; ++s, ++d, ++m)
85  if(mask(m))
86  dest.set(f(src(s)), d);
87 }
88 
89 /********************************************************/
90 /* */
91 /* transformImage */
92 /* */
93 /********************************************************/
94 
95 /** \brief Apply unary point transformation to each pixel.
96 
97  The transformation given by the functor is applied to every source
98  pixel and the result written into the corresponding destination pixel.
99  The function uses accessors to access the pixel data.
100  Note that the unary functors of the STL can be used in addition to
101  the functors specifically defined in \ref TransformFunctor.
102  Creation of new functors is easiest by using \ref FunctorExpressions.
103 
104  <b> Declarations:</b>
105 
106  pass arguments explicitly:
107  \code
108  namespace vigra {
109  template <class SrcImageIterator, class SrcAccessor,
110  class DestImageIterator, class DestAccessor, class Functor>
111  void
112  transformImage(SrcImageIterator src_upperleft,
113  SrcImageIterator src_lowerright, SrcAccessor sa,
114  DestImageIterator dest_upperleft, DestAccessor da,
115  Functor const & f)
116  }
117  \endcode
118 
119 
120  use argument objects in conjunction with \ref ArgumentObjectFactories :
121  \code
122  namespace vigra {
123  template <class SrcImageIterator, class SrcAccessor,
124  class DestImageIterator, class DestAccessor, class Functor>
125  void
126  transformImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
127  pair<DestImageIterator, DestAccessor> dest,
128  Functor const & f)
129  }
130  \endcode
131 
132  <b> Usage:</b>
133 
134  <b>\#include</b> <vigra/transformimage.hxx><br>
135  Namespace: vigra
136 
137  \code
138 
139  #include <cmath> // for sqrt()
140 
141  vigra::transformImage(srcImageRange(src),
142  destImage(dest),
143  (double(*)(double))&std::sqrt );
144 
145  \endcode
146 
147  <b> Required Interface:</b>
148 
149  \code
150  SrcImageIterator src_upperleft, src_lowerright;
151  DestImageIterator dest_upperleft;
152  SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
153  DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
154 
155  SrcAccessor src_accessor;
156  DestAccessor dest_accessor;
157 
158  Functor functor;
159 
160  dest_accessor.set(functor(src_accessor(sx)), dx);
161 
162  \endcode
163 
164 */
165 doxygen_overloaded_function(template <...> void transformImage)
166 
167 template <class SrcImageIterator, class SrcAccessor,
168  class DestImageIterator, class DestAccessor, class Functor>
169 void
170 transformImage(SrcImageIterator src_upperleft,
171  SrcImageIterator src_lowerright, SrcAccessor sa,
172  DestImageIterator dest_upperleft, DestAccessor da,
173  Functor const & f)
174 {
175  int w = src_lowerright.x - src_upperleft.x;
176 
177  for(; src_upperleft.y < src_lowerright.y; ++src_upperleft.y, ++dest_upperleft.y)
178  {
179  transformLine(src_upperleft.rowIterator(),
180  src_upperleft.rowIterator() + w, sa,
181  dest_upperleft.rowIterator(), da, f);
182  }
183 }
184 
185 template <class SrcImageIterator, class SrcAccessor,
186  class DestImageIterator, class DestAccessor, class Functor>
187 inline
188 void
189 transformImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
190  pair<DestImageIterator, DestAccessor> dest,
191  Functor const & f)
192 {
193  transformImage(src.first, src.second, src.third,
194  dest.first, dest.second, f);
195 }
196 
197 /********************************************************/
198 /* */
199 /* transformImageIf */
200 /* */
201 /********************************************************/
202 
203 /** \brief Apply unary point transformation to each pixel within the ROI
204  (i.e., where the mask is non-zero).
205 
206  The transformation given by the functor is applied to every source
207  pixel in the ROI (i.e. when the return value of the mask's accessor
208  is not zero)
209  and the result is written into the corresponding destination pixel.
210  The function uses accessors to access the pixel data.
211  Note that the unary functors of the STL can be used in addition to
212  the functors specifically defined in \ref TransformFunctor.
213  Creation of new functors is easiest by using \ref FunctorExpressions.
214 
215  <b> Declarations:</b>
216 
217  pass arguments explicitly:
218  \code
219  namespace vigra {
220  template <class SrcImageIterator, class SrcAccessor,
221  class MaskImageIterator, class MaskAccessor,
222  class DestImageIterator, clas DestAccessor,
223  class Functor>
224  void
225  transformImageIf(SrcImageIterator src_upperleft,
226  SrcImageIterator src_lowerright, SrcAccessor sa,
227  MaskImageIterator mask_upperleft, MaskAccessor ma,
228  DestImageIterator dest_upperleft, DestAccessor da,
229  Functor const & f)
230  }
231  \endcode
232 
233 
234  use argument objects in conjunction with \ref ArgumentObjectFactories :
235  \code
236  namespace vigra {
237  template <class SrcImageIterator, class SrcAccessor,
238  class MaskImageIterator, class MaskAccessor,
239  class DestImageIterator, clas DestAccessor,
240  class Functor>
241  void
242  transformImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
243  pair<MaskImageIterator, MaskAccessor> mask,
244  pair<DestImageIterator, DestAccessor> dest,
245  Functor const & f)
246  }
247  \endcode
248 
249  <b> Usage:</b>
250 
251  <b>\#include</b> <vigra/transformimage.hxx><br>
252  Namespace: vigra
253 
254  \code
255  #include <cmath> // for sqrt()
256 
257  vigra::transformImageIf(srcImageRange(src),
258  maskImage(mask),
259  destImage(dest),
260  (double(*)(double))&std::sqrt );
261 
262  \endcode
263 
264  <b> Required Interface:</b>
265 
266  \code
267  SrcImageIterator src_upperleft, src_lowerright;
268  DestImageIterator dest_upperleft;
269  MaskImageIterator mask_upperleft;
270  SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
271  MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
272  DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
273 
274  SrcAccessor src_accessor;
275  DestAccessor dest_accessor;
276  MaskAccessor mask_accessor;
277  Functor functor;
278 
279  if(mask_accessor(mx))
280  dest_accessor.set(functor(src_accessor(sx)), dx);
281 
282  \endcode
283 
284 */
285 doxygen_overloaded_function(template <...> void transformImageIf)
286 
287 template <class SrcImageIterator, class SrcAccessor,
288  class MaskImageIterator, class MaskAccessor,
289  class DestImageIterator, class DestAccessor,
290  class Functor>
291 void
292 transformImageIf(SrcImageIterator src_upperleft,
293  SrcImageIterator src_lowerright, SrcAccessor sa,
294  MaskImageIterator mask_upperleft, MaskAccessor ma,
295  DestImageIterator dest_upperleft, DestAccessor da,
296  Functor const & f)
297 {
298  int w = src_lowerright.x - src_upperleft.x;
299 
300  for(; src_upperleft.y < src_lowerright.y;
301  ++src_upperleft.y, ++mask_upperleft.y, ++dest_upperleft.y)
302  {
303  transformLineIf(src_upperleft.rowIterator(),
304  src_upperleft.rowIterator() + w, sa,
305  mask_upperleft.rowIterator(), ma,
306  dest_upperleft.rowIterator(), da, f);
307  }
308 }
309 
310 template <class SrcImageIterator, class SrcAccessor,
311  class MaskImageIterator, class MaskAccessor,
312  class DestImageIterator, class DestAccessor,
313  class Functor>
314 inline
315 void
316 transformImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
317  pair<MaskImageIterator, MaskAccessor> mask,
318  pair<DestImageIterator, DestAccessor> dest,
319  Functor const & f)
320 {
321  transformImageIf(src.first, src.second, src.third,
322  mask.first, mask.second,
323  dest.first, dest.second, f);
324 }
325 
326 /********************************************************/
327 /* */
328 /* gradientBasedTransform */
329 /* */
330 /********************************************************/
331 
332 /** \brief Calculate a function of the image gradient.
333 
334  The gradient and the function represented by <TT>Functor f</TT>
335  are calculated in one go: for each location, the symmetric
336  difference in x- and y-directions (asymmetric difference at the
337  image borders) are passed to the given functor, and the result is
338  written the destination image. Functors to be used with this
339  function include \ref MagnitudeFunctor and \ref
340  RGBGradientMagnitudeFunctor.
341 
342  <b> Declarations:</b>
343 
344  pass arguments explicitly:
345  \code
346  namespace vigra {
347  template <class SrcImageIterator, class SrcAccessor,
348  class DestImageIterator, class DestAccessor, class Functor>
349  void
350  gradientBasedTransform(SrcImageIterator srcul, SrcImageIterator srclr, SrcAccessor sa,
351  DestImageIterator destul, DestAccessor da, Functor const & f)
352  }
353  \endcode
354 
355 
356  use argument objects in conjunction with \ref ArgumentObjectFactories :
357  \code
358  namespace vigra {
359  template <class SrcImageIterator, class SrcAccessor,
360  class DestImageIterator, class DestAccessor, class Functor>
361  void
362  gradientBasedTransform(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
363  pair<DestImageIterator, DestAccessor> dest, Functor const & const & f)
364  }
365  \endcode
366 
367  <b> Usage:</b>
368 
369  <b>\#include</b> <vigra/transformimage.hxx>
370 
371 
372  \code
373  vigra::FImage src(w,h), magnitude(w,h);
374  ...
375 
376  gradientBasedTransform(srcImageRange(src), destImage(magnitude),
377  vigra::MagnitudeFunctor<float>());
378  \endcode
379 
380  <b> Required Interface:</b>
381 
382  \code
383  SrcImageIterator is, isend;
384  DestImageIterator id;
385 
386  SrcAccessor src_accessor;
387  DestAccessor dest_accessor;
388 
389  typename NumericTraits<typename SrcAccessor::value_type>::RealPromote
390  diffx, diffy;
391 
392  diffx = src_accessor(is, Diff2D(-1,0)) - src_accessor(is, Diff2D(1,0));
393  diffy = src_accessor(is, Diff2D(0,-1)) - src_accessor(is, Diff2D(0,1));
394 
395  Functor f;
396 
397  dest_accessor.set(f(diffx, diffy), id);
398 
399  \endcode
400 
401 */
402 doxygen_overloaded_function(template <...> void gradientBasedTransform)
403 
404 template <class SrcImageIterator, class SrcAccessor,
405  class DestImageIterator, class DestAccessor, class Functor>
406 void
407 gradientBasedTransform(SrcImageIterator srcul, SrcImageIterator srclr, SrcAccessor sa,
408  DestImageIterator destul, DestAccessor da, Functor const & grad)
409 {
410  int w = srclr.x - srcul.x;
411  int h = srclr.y - srcul.y;
412  int x,y;
413 
414  SrcImageIterator sy = srcul;
415  DestImageIterator dy = destul;
416 
417  static const Diff2D left(-1,0);
418  static const Diff2D right(1,0);
419  static const Diff2D top(0,-1);
420  static const Diff2D bottom(0,1);
421 
422  typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
423  TmpType diffx, diffy;
424 
425  SrcImageIterator sx = sy;
426  DestImageIterator dx = dy;
427 
428  diffx = sa(sx) - sa(sx, right);
429  diffy = sa(sx) - sa(sx, bottom);
430  da.set(grad(diffx, diffy), dx);
431 
432  for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
433  {
434  diffx = (sa(sx, left) - sa(sx, right)) / TmpType(2.0);
435  diffy = sa(sx) - sa(sx, bottom);
436  da.set(grad(diffx, diffy), dx);
437  }
438 
439  diffx = sa(sx, left) - sa(sx);
440  diffy = sa(sx) - sa(sx, bottom);
441  da.set(grad(diffx, diffy), dx);
442 
443  ++sy.y;
444  ++dy.y;
445 
446  for(y=2; y<h; ++y, ++sy.y, ++dy.y)
447  {
448  sx = sy;
449  dx = dy;
450 
451  diffx = sa(sx) - sa(sx, right);
452  diffy = (sa(sx, top) - sa(sx, bottom)) / TmpType(2.0);
453  da.set(grad(diffx, diffy), dx);
454 
455  for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
456  {
457  diffx = (sa(sx, left) - sa(sx, right)) / TmpType(2.0);
458  diffy = (sa(sx, top) - sa(sx, bottom)) / TmpType(2.0);
459  da.set(grad(diffx, diffy), dx);
460  }
461 
462  diffx = sa(sx, left) - sa(sx);
463  diffy = (sa(sx, top) - sa(sx, bottom)) / TmpType(2.0);
464  da.set(grad(diffx, diffy), dx);
465  }
466 
467  sx = sy;
468  dx = dy;
469 
470  diffx = sa(sx) - sa(sx, right);
471  diffy = sa(sx, top) - sa(sx);
472  da.set(grad(diffx, diffy), dx);
473 
474  for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
475  {
476  diffx = (sa(sx, left) - sa(sx, right)) / TmpType(2.0);
477  diffy = sa(sx, top) - sa(sx);
478  da.set(grad(diffx, diffy), dx);
479  }
480 
481  diffx = sa(sx, left) - sa(sx);
482  diffy = sa(sx, top) - sa(sx);
483  da.set(grad(diffx, diffy), dx);
484 }
485 
486 template <class SrcImageIterator, class SrcAccessor,
487  class DestImageIterator, class DestAccessor, class Functor>
488 inline
489 void
490 gradientBasedTransform(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
491  pair<DestImageIterator, DestAccessor> dest, Functor const & grad)
492 {
493  gradientBasedTransform(src.first, src.second, src.third,
494  dest.first, dest.second, grad);
495 }
496 
497 /** @} */
498 /** \addtogroup TransformFunctor Functors to Transform Images
499 
500  Note that the unary functors of the STL can also be used in
501  connection with \ref transformImage().
502 */
503 //@{
504 
505 template <class DestValueType, class Multiplier = double>
506 class LinearIntensityTransform
507 {
508  public:
509  /* the functors argument type (actually, since
510  <tt>operator()</tt> is a template, much more types are possible)
511  */
512  typedef DestValueType argument_type;
513 
514  /* the functors result type
515  */
516  typedef DestValueType result_type;
517 
518  /* \deprecated use argument_type and result_type
519  */
520  typedef DestValueType value_type;
521 
522  /* type of the offset (used in internal calculations to prevent
523  overflows and minimize round-off errors).
524  */
525  typedef typename
526  NumericTraits<DestValueType>::RealPromote argument_promote;
527 
528  /* type of the scale factor
529  */
530  typedef Multiplier scalar_multiplier_type;
531 
532  /* init scale and offset
533  */
534  LinearIntensityTransform(scalar_multiplier_type scale, argument_promote offset)
535  : scale_(scale), offset_(offset)
536  {}
537 
538  /* calculate transform
539  */
540  template <class SrcValueType>
541  result_type operator()(SrcValueType const & s) const
542  {
543  return NumericTraits<result_type>::fromRealPromote(scale_ * (s + offset_));
544  }
545 
546  private:
547 
548  scalar_multiplier_type scale_;
549  argument_promote offset_;
550 };
551 
552 template <class DestValueType, class Multiplier>
553 class FunctorTraits<LinearIntensityTransform<DestValueType, Multiplier> >
554 : public FunctorTraitsBase<LinearIntensityTransform<DestValueType, Multiplier> >
555 {
556  public:
557  typedef VigraTrueType isUnaryFunctor;
558 };
559 
560 template <class DestValueType, class Multiplier = double>
561 class ScalarIntensityTransform
562 {
563  public:
564  /* the functors argument type (actually, since
565  <tt>operator()</tt> is a template, much more types are possible)
566  */
567  typedef DestValueType argument_type;
568 
569  /* the functors result type
570  */
571  typedef DestValueType result_type;
572 
573  /* \deprecated use argument_type and result_type
574  */
575  typedef DestValueType value_type;
576 
577  /* type of the scale factor
578  */
579  typedef Multiplier scalar_multiplier_type;
580 
581  /* init scale
582  */
583  ScalarIntensityTransform(scalar_multiplier_type scale)
584  : scale_(scale)
585  {}
586 
587  /* calculate transform
588  */
589  template <class SrcValueType>
590  result_type operator()(SrcValueType const & s) const
591  {
592  return NumericTraits<result_type>::fromRealPromote(scale_ * s);
593  }
594 
595  private:
596  scalar_multiplier_type scale_;
597 };
598 
599 template <class DestValueType, class Multiplier>
600 class FunctorTraits<ScalarIntensityTransform<DestValueType, Multiplier> >
601 : public FunctorTraitsBase<ScalarIntensityTransform<DestValueType, Multiplier> >
602 {
603  public:
604  typedef VigraTrueType isUnaryFunctor;
605 };
606 
607 /********************************************************/
608 /* */
609 /* linearIntensityTransform */
610 /* */
611 /********************************************************/
612 
613 /** \brief Apply a linear transform to the source pixel values
614 
615  Factory function for a functor that linearly transforms the
616  source pixel values. The functor applies the transform
617  '<TT>destvalue = scale * (srcvalue + offset)</TT>' to every pixel.
618  This can, for example, be used to transform images into the visible
619  range 0...255 or to invert an image.
620 
621  If you leave out the second parameter / offset, you will get an
622  optimized version of the functor which only scales by the given
623  factor, however you have to make the template parameter (pixel
624  type) explicit then.
625 
626  <b> Traits defined:</b>
627 
628  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
629 
630  <b> Declaration:</b>
631 
632  \code
633  namespace vigra {
634  template <class Multiplier, class DestValueType>
635  LinearIntensityTransform<DestValueType, Multiplier>
636  linearIntensityTransform(Multiplier scale, DestValueType offset);
637 
638  template <class DestValueType, class Multiplier>
639  ScalarIntensityTransform<DestValueType, Multiplier>
640  linearIntensityTransform(Multiplier scale);
641  }
642  \endcode
643 
644  <b> Usage:</b>
645 
646  <b>\#include</b> <vigra/transformimage.hxx><br>
647  Namespace: vigra
648 
649  \code
650  vigra::IImage src(width, height);
651  vigra::BImage dest(width, height);
652  ...
653  vigra::FindMinMax<IImage::PixelType> minmax; // functor to find range
654 
655  vigra::inspectImage(srcImageRange(src), minmax); // find original range
656 
657  // transform to range 0...255
658  vigra::transformImage(srcImageRange(src), destImage(dest),
659  linearIntensityTransform(
660  255.0 / (minmax.max - minmax.min), // scaling
661  - minmax.min)); // offset
662  \endcode
663 
664  The one-parameter version can be used like this:
665 
666  \code
667  // scale from 0..255 to 0..1.0
668  FImage dest(src.size());
669 
670  vigra::transformImage(srcImageRange(src), destImage(dest),
671  linearIntensityTransform<float>(1.0 / 255));
672  \endcode
673 
674  <b> Required Interface:</b>
675 
676  The source and destination value types must be models of \ref LinearSpace in both cases.
677 
678 */
679 template <class Multiplier, class DestValueType>
680 LinearIntensityTransform<DestValueType, Multiplier>
681 linearIntensityTransform(Multiplier scale, DestValueType offset)
682 {
683  return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
684 }
685 
686 template <class DestValueType, class Multiplier>
687 ScalarIntensityTransform<DestValueType, Multiplier>
688 linearIntensityTransform(Multiplier scale)
689 {
690  return ScalarIntensityTransform<DestValueType, Multiplier>(scale);
691 }
692 
693 /********************************************************/
694 /* */
695 /* linearRangeMapping */
696 /* */
697 /********************************************************/
698 
699 /** \brief Map a source intensity range linearly to a destination range.
700 
701  Factory function for a functor that linearly transforms the
702  source pixel values. The functor applies the transform
703  '<TT>destvalue = scale * (srcvalue + offset)</TT>' to every pixel,
704  where <tt>scale = (dest_max - dest_min) / (src_max - src_min)</tt>
705  and <tt>offset = dest_min / scale - src_min</tt>. As a result,
706  the pixel values <tt>src_max</tt>, <tt>src_min</tt> in the source image
707  are mapped onto <tt>dest_max</tt>, <tt>dest_min</tt> respectively.
708  This works for scalar as well as vector pixel types. Instead of
709  <tt>src_min</tt> and <tt>src_max</tt>, you may also pass a functor
710  \ref FindMinMax.
711 
712  <b> Declaration:</b>
713 
714  \code
715  namespace vigra {
716  template <class SrcValueType, class DestValueType>
717  LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
718  linearRangeMapping(SrcValueType src_min, SrcValueType src_max,
719  DestValueType dest_min, DestValueType dest_max );
720 
721  template <class SrcValueType, class DestValueType>
722  LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
723  linearRangeMapping(SrcValueType src_min, SrcValueType src_max,
724  DestValueType dest_min, DestValueType dest_max );
725  }
726  \endcode
727 
728  <b> Usage:</b>
729 
730  <b>\#include</b> <vigra/transformimage.hxx><br>
731  Namespace: vigra
732 
733  \code
734  vigra::IImage src(width, height);
735  vigra::BImage dest(width, height);
736  ...
737  vigra::FindMinMax<IImage::PixelType> minmax; // functor to find range
738 
739  vigra::inspectImage(srcImageRange(src), minmax); // find original range
740 
741  // transform to range 0...255
742  vigra::transformImage(srcImageRange(src), destImage(dest),
743  linearRangeMapping(
744  minmax.min, minmax.max, // src range
745  0, 255) // dest range
746  );
747 
748  // equivalent, but shorter
749  vigra::transformImage(srcImageRange(src), destImage(dest),
750  linearRangeMapping(
751  minmax, // src range
752  0, 255) // dest range
753  );
754  \endcode
755 
756  <b> Required Interface:</b>
757 
758  The source and destination value types must be models of \ref LinearSpace in both cases.
759 
760 */
761 template <class SrcValueType, class DestValueType>
762 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
763 linearRangeMapping(SrcValueType src_min, SrcValueType src_max,
764  DestValueType dest_min, DestValueType dest_max )
765 {
766  return linearRangeMapping(src_min, src_max, dest_min, dest_max,
767  typename NumericTraits<DestValueType>::isScalar());
768 }
769 
770 template <class SrcValueType, class DestValueType>
771 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
772 linearRangeMapping(FindMinMax<SrcValueType> const & src,
773  DestValueType dest_min, DestValueType dest_max )
774 {
775  return linearRangeMapping(src.min, src.max, dest_min, dest_max,
776  typename NumericTraits<DestValueType>::isScalar());
777 }
778 
779 template <class SrcValueType, class DestValueType>
780 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
782  SrcValueType src_min, SrcValueType src_max,
783  DestValueType dest_min, DestValueType dest_max,
784  VigraTrueType /* isScalar */ )
785 {
786  typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
787  Multiplier diff = src_max - src_min;
788  Multiplier scale = diff == NumericTraits<Multiplier>::zero()
789  ? NumericTraits<Multiplier>::one()
790  : (dest_max - dest_min) / diff;
791  return LinearIntensityTransform<DestValueType, Multiplier>(
792  scale, dest_min / scale - src_min );
793 }
794 
795 template <class SrcValueType, class DestValueType>
796 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
798  SrcValueType src_min, SrcValueType src_max,
799  DestValueType dest_min, DestValueType dest_max,
800  VigraFalseType /* isScalar */ )
801 {
802  typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
803  typedef typename Multiplier::value_type MComponent;
804  Multiplier scale(dest_max), offset(dest_max);
805  for(unsigned int i=0; i<src_min.size(); ++i)
806  {
807  MComponent diff = src_max[i] - src_min[i];
808  scale[i] = diff == NumericTraits<MComponent>::zero()
809  ? NumericTraits<MComponent>::one()
810  : (dest_max[i] - dest_min[i]) / diff;
811  offset[i] = dest_min[i] / scale[i] - src_min[i];
812  }
813  return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
814 }
815 
816 /********************************************************/
817 /* */
818 /* Threshold */
819 /* */
820 /********************************************************/
821 
822 /** \brief Threshold an image.
823 
824  If a source pixel is above or equal the lower and below
825  or equal the higher threshold (i.e. within the closed interval
826  [lower, higher]) the destination pixel is set to 'yesresult',
827  otherwise to 'noresult'.
828 
829  <b> Traits defined:</b>
830 
831  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
832 
833  <b> Usage:</b>
834 
835  <b>\#include</b> <vigra/transformimage.hxx><br>
836  Namespace: vigra
837 
838  \code
839  vigra::BImage src(width, height), dest(width, height);
840  ...
841  vigra::transformImage(src.upperLeft(), src.lowerRight(), src.accessor(),
842  dest.upperLeft(), dest.accessor(),
843  vigra::Threshold<
844  vigra::BImage::PixelType, vigra::BImage::PixelType>(10, 100, 0, 255));
845 
846  \endcode
847 
848  <b> Required Interface:</b>
849 
850  \code
851 
852  SrcValueType src;
853  DestValueType dest, yesresult, noresult;
854 
855  dest = ((src < lower) || (higher < src)) ? noresult : yesresult;
856 
857  \endcode
858 
859 */
860 template <class SrcValueType, class DestValueType>
862 {
863  public:
864 
865  /** the functor's argument type
866  */
867  typedef SrcValueType argument_type;
868 
869  /** the functor's result type
870  */
871  typedef DestValueType result_type;
872 
873  /** init thresholds and return values
874  */
876  result_type noresult, result_type yesresult)
877  : lower_(lower), higher_(higher),
878  yesresult_(yesresult), noresult_(noresult)
879  {}
880 
881  /** calculate transform
882  */
884  {
885  return ((s < lower_) || (higher_ < s)) ? noresult_ : yesresult_;
886  }
887 
888  private:
889 
890  argument_type lower_, higher_;
891  result_type yesresult_, noresult_;
892 };
893 
894 template <class SrcValueType, class DestValueType>
895 class FunctorTraits<Threshold<SrcValueType, DestValueType> >
896 : public FunctorTraitsBase<Threshold<SrcValueType, DestValueType> >
897 {
898  public:
899  typedef VigraTrueType isUnaryFunctor;
900 };
901 
902 /********************************************************/
903 /* */
904 /* BrightnessContrastFunctor */
905 /* */
906 /********************************************************/
907 
908 /** \brief Adjust brightness and contrast of an image.
909 
910  This functor applies a gamma correction to each pixel in order to
911  modify the brightness of the image. To the result of the gamma
912  correction, another transform is applied that modifies the
913  contrast. The brightness and contrast parameters must be
914  positive. Values greater than 1 will increase image brightness or
915  contrast respectively, values smaller than 1 decrease them. A
916  value of exactly 1 will have no effect. If contrast is set to 1,
917  the result is equivalent to that of the GammaFunctor with gamma =
918  1./brightness.
919 
920  For \ref RGBValue "RGBValue's", the transforms are applied
921  component-wise. The pixel values are assumed to lie between the
922  given minimum and maximum values (in case of RGB, this is again
923  understood component-wise). In case of <TT>unsigned char</TT>, min
924  and max default to 0 and 255 respectively. Precisely, the
925  following transform is applied to each <em> PixelValue</em>:
926 
927  \f[
928  \begin{array}{rcl}
929  V_1 & = & \frac{PixelValue - min}{max - min} \\
930  V_2 & = & V_1^\frac{1}{brightness} \\
931  V_3 & = & 2 V_2 - 1 \\
932  V_4 & = & \left\lbrace
933  \begin{array}{l}
934  V_3^\frac{1}{contrast} \mbox{\rm \quad if } V_3 \ge 0 \\
935  - (-V_3)^\frac{1}{contrast} \mbox{\rm \quad otherwise}
936  \end{array} \right. \\
937  Result & = & \frac{V_4 + 1}{2} (max - min) + min
938  \end{array}
939  \f]
940 
941  If the <TT>PixelType</TT> is <TT>unsigned char</TT>, a look-up-table is used
942  for faster computation.
943 
944  <b> Traits defined:</b>
945 
946  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
947 
948  <b> Usage:</b>
949 
950  <b>\#include</b> <vigra/transformimage.hxx><br>
951  Namespace: vigra
952 
953  \code
954  vigra::BImage bimage(width, height);
955  double brightness, contrast;
956  ...
957  vigra::transformImage(srcImageRange(bimage), destImage(bimage),
958  vigra::BrightnessContrastFunctor<unsigned char>(brightness, contrast));
959 
960 
961 
962  vigra::FImage fimage(width, height);
963  ...
964 
965  vigra::FindMinMax<float> minmax;
966  vigra::inspectImage(srcImageRange(fimage), minmax);
967 
968  vigra::transformImage(srcImageRange(fimage), destImage(fimage),
969  vigra::BrightnessContrastFunctor<float>(brightness, contrast, minmax.min, minmax.max));
970 
971 
972  \endcode
973 
974  <b> Required Interface:</b>
975 
976  Scalar types: must be a linear algebra (+, - *, NumericTraits),
977  strict weakly ordered (<), and <TT>pow()</TT> must be defined.
978 
979  RGB values: the component type must meet the above requirements.
980 */
981 template <class PixelType>
983 {
984  typedef typename
985  NumericTraits<PixelType>::RealPromote promote_type;
986 
987  public:
988 
989  /** the functor's argument type
990  */
991  typedef PixelType argument_type;
992 
993  /** the functor's result type
994  */
995  typedef PixelType result_type;
996 
997  /** \deprecated use argument_type and result_type
998  */
999  typedef PixelType value_type;
1000 
1001  /** Init functor for argument range <TT>[min, max]</TT>.
1002  <TT>brightness</TT> and <TT>contrast</TT> values > 1 will
1003  increase brightness and contrast, < 1 will decrease them, and == 1 means
1004  no change.
1005  */
1006  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1007  argument_type const & min, argument_type const & max)
1008  : b_(1.0/brightness),
1009  c_(1.0/contrast),
1010  min_(min),
1011  diff_(max - min),
1012  zero_(NumericTraits<promote_type>::zero()),
1013  one_(NumericTraits<promote_type>::one())
1014  {}
1015 
1016  /** Calculate modified gray or color value
1017  */
1019  {
1020  promote_type v1 = (v - min_) / diff_;
1021  promote_type brighter = VIGRA_CSTD::pow(v1, b_);
1022  promote_type v2 = 2.0 * brighter - one_;
1023  promote_type contrasted = (v2 < zero_) ?
1024  -VIGRA_CSTD::pow(-v2, c_) :
1025  VIGRA_CSTD::pow(v2, c_);
1026  return result_type(0.5 * diff_ * (contrasted + one_) + min_);
1027  }
1028 
1029  private:
1030  promote_type b_, c_;
1031  argument_type min_;
1032  promote_type diff_, zero_, one_;
1033 };
1034 
1035 template <>
1036 class BrightnessContrastFunctor<unsigned char>
1037 {
1038  typedef NumericTraits<unsigned char>::RealPromote promote_type;
1039  unsigned char lut[256];
1040 
1041  public:
1042 
1043  typedef unsigned char value_type;
1044 
1045  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1046  value_type const & min = 0, value_type const & max = 255)
1047  {
1048  BrightnessContrastFunctor<promote_type> f(brightness, contrast, min, max);
1049 
1050  for(int i = min; i <= max; ++i)
1051  {
1052  lut[i] = static_cast<unsigned char>(f(i)+0.5);
1053  }
1054  }
1055 
1056  value_type operator()(value_type const & v) const
1057  {
1058 
1059  return lut[v];
1060  }
1061 };
1062 
1063 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1064 
1065 template <class ComponentType>
1066 class BrightnessContrastFunctor<RGBValue<ComponentType> >
1067 {
1068  typedef typename
1069  NumericTraits<ComponentType>::RealPromote promote_type;
1070  BrightnessContrastFunctor<ComponentType> red, green, blue;
1071 
1072  public:
1073 
1074  typedef RGBValue<ComponentType> value_type;
1075 
1076  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1077  value_type const & min, value_type const & max)
1078  : red(brightness, contrast, min.red(), max.red()),
1079  green(brightness, contrast, min.green(), max.green()),
1080  blue(brightness, contrast, min.blue(), max.blue())
1081  {}
1082 
1083  value_type operator()(value_type const & v) const
1084  {
1085 
1086  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1087  }
1088 };
1089 
1090 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1091 
1092 template <>
1093 class BrightnessContrastFunctor<RGBValue<int> >
1094 {
1095  typedef NumericTraits<int>::RealPromote promote_type;
1096  BrightnessContrastFunctor<int> red, green, blue;
1097 
1098  public:
1099 
1100  typedef RGBValue<int> value_type;
1101 
1102  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1103  value_type const & min, value_type const & max)
1104  : red(brightness, contrast, min.red(), max.red()),
1105  green(brightness, contrast, min.green(), max.green()),
1106  blue(brightness, contrast, min.blue(), max.blue())
1107  {}
1108 
1109  value_type operator()(value_type const & v) const
1110  {
1111 
1112  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1113  }
1114 };
1115 
1116 template <>
1117 class BrightnessContrastFunctor<RGBValue<float> >
1118 {
1119  typedef NumericTraits<float>::RealPromote promote_type;
1120  BrightnessContrastFunctor<float> red, green, blue;
1121 
1122  public:
1123 
1124  typedef RGBValue<float> value_type;
1125 
1126  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1127  value_type const & min, value_type const & max)
1128  : red(brightness, contrast, min.red(), max.red()),
1129  green(brightness, contrast, min.green(), max.green()),
1130  blue(brightness, contrast, min.blue(), max.blue())
1131  {}
1132 
1133  value_type operator()(value_type const & v) const
1134  {
1135 
1136  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1137  }
1138 };
1139 
1140 template <class PixelType>
1141 class FunctorTraits<BrightnessContrastFunctor<PixelType> >
1142 : public FunctorTraitsBase<BrightnessContrastFunctor<PixelType> >
1143 {
1144  public:
1145  typedef VigraTrueType isUnaryFunctor;
1146 };
1147 
1148 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1149 
1150 template <>
1151 class BrightnessContrastFunctor<RGBValue<unsigned char> >
1152 {
1153  typedef NumericTraits<unsigned char>::RealPromote promote_type;
1154  BrightnessContrastFunctor<unsigned char> red, green, blue;
1155 
1156  public:
1157 
1158  typedef RGBValue<unsigned char> value_type;
1159 
1160  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1161  value_type const & min = value_type(0,0,0),
1162  value_type const & max = value_type(255, 255, 255))
1163  : red(brightness, contrast, min.red(), max.red()),
1164  green(brightness, contrast, min.green(), max.green()),
1165  blue(brightness, contrast, min.blue(), max.blue())
1166  {}
1167 
1168  value_type operator()(value_type const & v) const
1169  {
1170 
1171  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1172  }
1173 };
1174 
1175 
1176 
1177 /********************************************************/
1178 /* */
1179 /* GammaFunctor */
1180 /* */
1181 /********************************************************/
1182 
1183 /** \brief Perform gamma correction of an image.
1184 
1185  This functor applies a gamma correction to each pixel in order to
1186  modify the brightness of the image. Gamma values smaller than 1
1187  will increase image brightness, whereas values greater than 1
1188  decrease it. A value of gamma = 1 will have no effect. (See also
1189  BrightnessContrastFunctor, which additionally changes the
1190  contrast.)
1191 
1192  For \ref RGBValue "RGBValue's", the transforms are applied
1193  component-wise. For ease of use, the pixel values are assumed to
1194  lie between the given minimum and maximum values (in case of RGB,
1195  this is again understood component-wise). In case of <TT>unsigned
1196  char</TT>, min and max default to 0 and 255 respectively.
1197  Precisely, the following transform is applied to each <em>
1198  PixelValue</em>:
1199 
1200  \f[
1201  \begin{array}{rcl}
1202  V_1 & = & \frac{PixelValue - min}{max - min} \\
1203  V_2 & = & V_1^{gamma} \\
1204  Result & = & V_2 (max - min) + min
1205  \end{array}
1206  \f]
1207 
1208  If the <TT>PixelType</TT> is <TT>unsigned char</TT>, a
1209  look-up-table is used for faster computation.
1210 
1211  <b> Traits defined:</b>
1212 
1213  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
1214 
1215  <b> Usage:</b>
1216 
1217  <b>\#include</b> <vigra/transformimage.hxx><br>
1218  Namespace: vigra
1219 
1220  \code
1221  vigra::BImage bimage(width, height);
1222  double gamma;
1223  ...
1224  vigra::transformImage(srcImageRange(bimage), destImage(bimage),
1225  vigra::GammaFunctor<unsigned char>(gamma));
1226 
1227 
1228 
1229  vigra::FImage fimage(width, height);
1230  ...
1231 
1232  vigra::FindMinMax<float> minmax;
1233  vigra::inspectImage(srcImageRange(fimage), minmax);
1234 
1235  vigra::transformImage(srcImageRange(fimage), destImage(fimage),
1236  vigra::GammaFunctor<float>(gamma, minmax.min, minmax.max));
1237 
1238  \endcode
1239 
1240  <b> Required Interface:</b>
1241 
1242  Scalar types: must be a linear algebra (+, - *, NumericTraits),
1243  strict weakly ordered (<), and <TT>pow()</TT> must be defined.
1244 
1245  RGB values: the component type must meet the above requirements.
1246 */
1247 template <class PixelType>
1249 {
1250  typedef typename
1251  NumericTraits<PixelType>::RealPromote promote_type;
1252 
1253  public:
1254 
1255  /** the functor's argument type
1256  */
1257  typedef PixelType argument_type;
1258 
1259  /** the functor's result type
1260  */
1261  typedef PixelType result_type;
1262 
1263  /** \deprecated use argument_type and result_type
1264  */
1265  typedef PixelType value_type;
1266 
1267  /** Init functor for argument range <TT>[min, max]</TT>.
1268  <TT>gamma</TT> values < 1 will increase brightness, > 1
1269  will decrease it (gamma == 1 means no change).
1270  */
1272  argument_type const & min, argument_type const & max)
1273  : gamma_((promote_type)gamma),
1274  min_(min),
1275  diff_(max - min),
1276  zero_(NumericTraits<promote_type>::zero()),
1277  one_(NumericTraits<promote_type>::one())
1278  {}
1279 
1280  /** Calculate modified gray or color value
1281  */
1283  {
1284  promote_type v1 = (v - min_) / diff_;
1285  promote_type brighter = VIGRA_CSTD::pow(v1, gamma_);
1286  return result_type(diff_ * brighter + min_);
1287  }
1288 
1289  private:
1290  promote_type gamma_;
1291  argument_type min_;
1292  promote_type diff_, zero_, one_;
1293 };
1294 
1295 template <>
1296 class GammaFunctor<unsigned char>
1297 {
1298  typedef NumericTraits<unsigned char>::RealPromote promote_type;
1299  unsigned char lut[256];
1300 
1301  public:
1302 
1303  typedef unsigned char value_type;
1304 
1305  GammaFunctor(promote_type gamma,
1306  value_type const & min = 0, value_type const & max = 255)
1307  {
1308  GammaFunctor<promote_type> f(gamma, min, max);
1309 
1310  for(int i = min; i <= max; ++i)
1311  {
1312  lut[i] = static_cast<unsigned char>(f(i)+0.5);
1313  }
1314  }
1315 
1316  value_type operator()(value_type const & v) const
1317  {
1318 
1319  return lut[v];
1320  }
1321 };
1322 
1323 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1324 
1325 template <class ComponentType>
1326 class GammaFunctor<RGBValue<ComponentType> >
1327 {
1328  typedef typename
1329  NumericTraits<ComponentType>::RealPromote promote_type;
1330  GammaFunctor<ComponentType> red, green, blue;
1331 
1332  public:
1333 
1334  typedef RGBValue<ComponentType> value_type;
1335 
1336  GammaFunctor(promote_type gamma,
1337  value_type const & min, value_type const & max)
1338  : red(gamma, min.red(), max.red()),
1339  green(gamma, min.green(), max.green()),
1340  blue(gamma, min.blue(), max.blue())
1341  {}
1342 
1343  value_type operator()(value_type const & v) const
1344  {
1345  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1346  }
1347 };
1348 
1349 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1350 
1351 template <>
1352 class GammaFunctor<RGBValue<int> >
1353 {
1354  typedef NumericTraits<int>::RealPromote promote_type;
1355  GammaFunctor<int> red, green, blue;
1356 
1357  public:
1358 
1359  typedef RGBValue<int> value_type;
1360 
1361  GammaFunctor(promote_type gamma,
1362  value_type const & min, value_type const & max)
1363  : red(gamma, min.red(), max.red()),
1364  green(gamma, min.green(), max.green()),
1365  blue(gamma, min.blue(), max.blue())
1366  {}
1367 
1368  value_type operator()(value_type const & v) const
1369  {
1370  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1371  }
1372 };
1373 
1374 template <>
1375 class GammaFunctor<RGBValue<float> >
1376 {
1377  typedef NumericTraits<float>::RealPromote promote_type;
1378  GammaFunctor<float> red, green, blue;
1379 
1380  public:
1381 
1382  typedef RGBValue<float> value_type;
1383 
1384  GammaFunctor(promote_type gamma,
1385  value_type const & min, value_type const & max)
1386  : red(gamma, min.red(), max.red()),
1387  green(gamma, min.green(), max.green()),
1388  blue(gamma, min.blue(), max.blue())
1389  {}
1390 
1391  value_type operator()(value_type const & v) const
1392  {
1393  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1394  }
1395 };
1396 
1397 template <class PixelType>
1398 class FunctorTraits<GammaFunctor<PixelType> >
1399 : public FunctorTraitsBase<GammaFunctor<PixelType> >
1400 {
1401  public:
1402  typedef VigraTrueType isUnaryFunctor;
1403 };
1404 
1405 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1406 
1407 template <>
1408 class GammaFunctor<RGBValue<unsigned char> >
1409 {
1410  typedef NumericTraits<unsigned char>::RealPromote promote_type;
1411  GammaFunctor<unsigned char> red, green, blue;
1412 
1413  public:
1414  typedef RGBValue<unsigned char> value_type;
1415 
1416  GammaFunctor(promote_type gamma,
1417  value_type const & min = value_type(0,0,0),
1418  value_type const & max = value_type(255, 255, 255))
1419  : red(gamma, min.red(), max.red()),
1420  green(gamma, min.green(), max.green()),
1421  blue(gamma, min.blue(), max.blue())
1422  {}
1423 
1424  value_type operator()(value_type const & v) const
1425  {
1426  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1427  }
1428 };
1429 
1430 
1431 /********************************************************/
1432 /* */
1433 /* VectorNormFunctor */
1434 /* */
1435 /********************************************************/
1436 
1437 /** \brief A functor for computing the vector norm
1438 
1439  Calculate the magnitude or norm from a given vector-valued
1440  entity. The vector type will typically be some sort of
1441  ref vigra::TinyVector. If the vector is represented by a pair of
1442  scalar-valued images, use \ref vigra::MagnitudeFunctor instead.
1443 
1444  At least, the vector type is required to have a function
1445  '<em>result</em><TT> = dot(v,v)</TT>'.
1446 
1447  <b> Traits defined:</b>
1448 
1449  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
1450 
1451  <b> Usage:</b>
1452 
1453  <b>\#include</b> <vigra/transformimage.hxx><br>
1454  Namespace: vigra
1455 
1456  \code
1457  typedef vigra::TinyVector<float, 2> Vector;
1458  vigra::BasicImage<Vector> grad(width, height);
1459  vigra::FImage magn(width,height);
1460  ...
1461  vigra::transformImage(srcImageRange(grad), destImage(magn),
1462  VectorNormFunctor<float>()
1463  );
1464  \endcode
1465 
1466  \see vigra::TinyVector, dot(), vigra::MagnitudeFunctor
1467 */
1468 template <class ValueType>
1470 {
1471 public:
1472  /** the functor's argument type
1473  */
1474  typedef ValueType argument_type;
1475 
1476  /** the functor's result type
1477  */
1478  typedef typename NumericTraits<typename ValueType::value_type>::RealPromote result_type;
1479 
1480  /** calculate transform '<TT>sqrt(v1*v1 + v2*v2 + ...)</TT>'.
1481  */
1483  {
1484  return VIGRA_CSTD::sqrt( dot(a,a) );
1485  }
1486 }; //-- class VectorNormFunctor
1487 
1488 template <class ValueType>
1489 class FunctorTraits<VectorNormFunctor<ValueType> >
1490 : public FunctorTraitsBase<VectorNormFunctor<ValueType> >
1491 {
1492  public:
1493  typedef VigraTrueType isUnaryFunctor;
1494 };
1495 
1496 /** \brief A functor for computing the squared vector norm
1497 
1498  Calculate the squared magnitude or norm from a given
1499  vector-valued entity. The vector type will typically be some
1500  sort of TinyVector.
1501 
1502  At least, the vector type is required to have a function
1503  '<em>result</em><TT> = dot(v,v)</TT>'.
1504 
1505  For an example of its usage see VectorNormFunctor
1506 
1507  <b> Traits defined:</b>
1508 
1509  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
1510 
1511  \see TinyVector, dot()
1512 */
1513 template <class ValueType>
1515 {
1516 public:
1517  /** the functor's argument type
1518  */
1519  typedef ValueType argument_type;
1520 
1521  /** the functor's result type
1522  */
1523  typedef typename NumericTraits<typename ValueType::value_type>::RealPromote result_type;
1524 
1525  /** calculate transform '<TT>v1*v1 + v2*v2 + ...</TT>'.
1526  */
1528  {
1529  return dot(a,a);
1530  }
1531 }; //-- class VectorNormSqFunctor
1532 
1533 template <class ValueType>
1534 class FunctorTraits<VectorNormSqFunctor<ValueType> >
1535 : public FunctorTraitsBase<VectorNormSqFunctor<ValueType> >
1536 {
1537  public:
1538  typedef VigraTrueType isUnaryFunctor;
1539 };
1540 
1541 //@}
1542 
1543 } // namespace vigra
1544 
1545 #endif // VIGRA_TRANSFORMIMAGE_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.9.0 (Wed Feb 27 2013)