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

transformimage.hxx VIGRA

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

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