[ 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  If a source pixel is above or equal the lower and below
944  or equal the higher threshold (i.e. within the closed interval
945  [lower, higher]) the destination pixel is set to 'yesresult',
946  otherwise to 'noresult'.
947 
948  <b> Traits defined:</b>
949 
950  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
951 
952  <b> Usage:</b>
953 
954  <b>\#include</b> <vigra/transformimage.hxx><br>
955  Namespace: vigra
956 
957  \code
958  vigra::BImage src(width, height), dest(width, height);
959  ...
960  vigra::transformImage(src.upperLeft(), src.lowerRight(), src.accessor(),
961  dest.upperLeft(), dest.accessor(),
962  vigra::Threshold<
963  vigra::BImage::PixelType, vigra::BImage::PixelType>(10, 100, 0, 255));
964 
965  \endcode
966 
967  <b> Required Interface:</b>
968 
969  \code
970 
971  SrcValueType src;
972  DestValueType dest, yesresult, noresult;
973 
974  dest = ((src < lower) || (higher < src)) ? noresult : yesresult;
975 
976  \endcode
977 
978 */
979 template <class SrcValueType, class DestValueType>
981 {
982  public:
983 
984  /** the functor's argument type
985  */
986  typedef SrcValueType argument_type;
987 
988  /** the functor's result type
989  */
990  typedef DestValueType result_type;
991 
992  /** init thresholds and return values
993  */
995  result_type noresult, result_type yesresult)
996  : lower_(lower), higher_(higher),
997  yesresult_(yesresult), noresult_(noresult)
998  {}
999 
1000  /** calculate transform
1001  */
1003  {
1004  return ((s < lower_) || (higher_ < s)) ? noresult_ : yesresult_;
1005  }
1006 
1007  private:
1008 
1009  argument_type lower_, higher_;
1010  result_type yesresult_, noresult_;
1011 };
1012 
1013 template <class SrcValueType, class DestValueType>
1014 class FunctorTraits<Threshold<SrcValueType, DestValueType> >
1015 : public FunctorTraitsBase<Threshold<SrcValueType, DestValueType> >
1016 {
1017  public:
1018  typedef VigraTrueType isUnaryFunctor;
1019 };
1020 
1021 /********************************************************/
1022 /* */
1023 /* BrightnessContrastFunctor */
1024 /* */
1025 /********************************************************/
1026 
1027 /** \brief Adjust brightness and contrast of an image.
1028 
1029  This functor applies a gamma correction to each pixel in order to
1030  modify the brightness of the image. To the result of the gamma
1031  correction, another transform is applied that modifies the
1032  contrast. The brightness and contrast parameters must be
1033  positive. Values greater than 1 will increase image brightness or
1034  contrast respectively, values smaller than 1 decrease them. A
1035  value of exactly 1 will have no effect. If contrast is set to 1,
1036  the result is equivalent to that of the GammaFunctor with gamma =
1037  1./brightness.
1038 
1039  For \ref RGBValue "RGBValue's", the transforms are applied
1040  component-wise. The pixel values are assumed to lie between the
1041  given minimum and maximum values (in case of RGB, this is again
1042  understood component-wise). In case of <TT>unsigned char</TT>, min
1043  and max default to 0 and 255 respectively. Precisely, the
1044  following transform is applied to each <em> PixelValue</em>:
1045 
1046  \f[
1047  \begin{array}{rcl}
1048  V_1 & = & \frac{PixelValue - min}{max - min} \\
1049  V_2 & = & V_1^\frac{1}{brightness} \\
1050  V_3 & = & 2 V_2 - 1 \\
1051  V_4 & = & \left\lbrace
1052  \begin{array}{l}
1053  V_3^\frac{1}{contrast} \mbox{\rm \quad if } V_3 \ge 0 \\
1054  - (-V_3)^\frac{1}{contrast} \mbox{\rm \quad otherwise}
1055  \end{array} \right. \\
1056  Result & = & \frac{V_4 + 1}{2} (max - min) + min
1057  \end{array}
1058  \f]
1059 
1060  If the <TT>PixelType</TT> is <TT>unsigned char</TT>, a look-up-table is used
1061  for faster computation.
1062 
1063  <b> Traits defined:</b>
1064 
1065  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
1066 
1067  <b> Usage:</b>
1068 
1069  <b>\#include</b> <vigra/transformimage.hxx><br>
1070  Namespace: vigra
1071 
1072  \code
1073  vigra::BImage bimage(width, height);
1074  double brightness, contrast;
1075  ...
1076  vigra::transformImage(srcImageRange(bimage), destImage(bimage),
1077  vigra::BrightnessContrastFunctor<unsigned char>(brightness, contrast));
1078 
1079 
1080 
1081  vigra::FImage fimage(width, height);
1082  ...
1083 
1084  vigra::FindMinMax<float> minmax;
1085  vigra::inspectImage(srcImageRange(fimage), minmax);
1086 
1087  vigra::transformImage(srcImageRange(fimage), destImage(fimage),
1088  vigra::BrightnessContrastFunctor<float>(brightness, contrast, minmax.min, minmax.max));
1089 
1090 
1091  \endcode
1092 
1093  <b> Required Interface:</b>
1094 
1095  Scalar types: must be a linear algebra (+, - *, NumericTraits),
1096  strict weakly ordered (<), and <TT>pow()</TT> must be defined.
1097 
1098  RGB values: the component type must meet the above requirements.
1099 */
1100 template <class PixelType>
1102 {
1103  typedef typename
1104  NumericTraits<PixelType>::RealPromote promote_type;
1105 
1106  public:
1107 
1108  /** the functor's argument type
1109  */
1110  typedef PixelType argument_type;
1111 
1112  /** the functor's result type
1113  */
1114  typedef PixelType result_type;
1115 
1116  /** \deprecated use argument_type and result_type
1117  */
1118  typedef PixelType value_type;
1119 
1120  /** Init functor for argument range <TT>[min, max]</TT>.
1121  <TT>brightness</TT> and <TT>contrast</TT> values > 1 will
1122  increase brightness and contrast, < 1 will decrease them, and == 1 means
1123  no change.
1124  */
1125  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1126  argument_type const & min, argument_type const & max)
1127  : b_(1.0/brightness),
1128  c_(1.0/contrast),
1129  min_(min),
1130  diff_(max - min),
1131  zero_(NumericTraits<promote_type>::zero()),
1132  one_(NumericTraits<promote_type>::one())
1133  {}
1134 
1135  /** Calculate modified gray or color value
1136  */
1138  {
1139  promote_type v1 = (v - min_) / diff_;
1140  promote_type brighter = VIGRA_CSTD::pow(v1, b_);
1141  promote_type v2 = 2.0 * brighter - one_;
1142  promote_type contrasted = (v2 < zero_) ?
1143  -VIGRA_CSTD::pow(-v2, c_) :
1144  VIGRA_CSTD::pow(v2, c_);
1145  return result_type(0.5 * diff_ * (contrasted + one_) + min_);
1146  }
1147 
1148  private:
1149  promote_type b_, c_;
1150  argument_type min_;
1151  promote_type diff_, zero_, one_;
1152 };
1153 
1154 template <>
1155 class BrightnessContrastFunctor<unsigned char>
1156 {
1157  typedef NumericTraits<unsigned char>::RealPromote promote_type;
1158  unsigned char lut[256];
1159 
1160  public:
1161 
1162  typedef unsigned char value_type;
1163 
1164  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1165  value_type const & min = 0, value_type const & max = 255)
1166  {
1167  BrightnessContrastFunctor<promote_type> f(brightness, contrast, min, max);
1168 
1169  for(int i = min; i <= max; ++i)
1170  {
1171  lut[i] = static_cast<unsigned char>(f(i)+0.5);
1172  }
1173  }
1174 
1175  value_type operator()(value_type const & v) const
1176  {
1177 
1178  return lut[v];
1179  }
1180 };
1181 
1182 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1183 
1184 template <class ComponentType>
1185 class BrightnessContrastFunctor<RGBValue<ComponentType> >
1186 {
1187  typedef typename
1188  NumericTraits<ComponentType>::RealPromote promote_type;
1189  BrightnessContrastFunctor<ComponentType> red, green, blue;
1190 
1191  public:
1192 
1193  typedef RGBValue<ComponentType> value_type;
1194 
1195  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1196  value_type const & min, value_type const & max)
1197  : red(brightness, contrast, min.red(), max.red()),
1198  green(brightness, contrast, min.green(), max.green()),
1199  blue(brightness, contrast, min.blue(), max.blue())
1200  {}
1201 
1202  value_type operator()(value_type const & v) const
1203  {
1204 
1205  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1206  }
1207 };
1208 
1209 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1210 
1211 template <>
1212 class BrightnessContrastFunctor<RGBValue<int> >
1213 {
1214  typedef NumericTraits<int>::RealPromote promote_type;
1215  BrightnessContrastFunctor<int> red, green, blue;
1216 
1217  public:
1218 
1219  typedef RGBValue<int> value_type;
1220 
1221  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1222  value_type const & min, value_type const & max)
1223  : red(brightness, contrast, min.red(), max.red()),
1224  green(brightness, contrast, min.green(), max.green()),
1225  blue(brightness, contrast, min.blue(), max.blue())
1226  {}
1227 
1228  value_type operator()(value_type const & v) const
1229  {
1230 
1231  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1232  }
1233 };
1234 
1235 template <>
1236 class BrightnessContrastFunctor<RGBValue<float> >
1237 {
1238  typedef NumericTraits<float>::RealPromote promote_type;
1239  BrightnessContrastFunctor<float> red, green, blue;
1240 
1241  public:
1242 
1243  typedef RGBValue<float> value_type;
1244 
1245  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1246  value_type const & min, value_type const & max)
1247  : red(brightness, contrast, min.red(), max.red()),
1248  green(brightness, contrast, min.green(), max.green()),
1249  blue(brightness, contrast, min.blue(), max.blue())
1250  {}
1251 
1252  value_type operator()(value_type const & v) const
1253  {
1254 
1255  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1256  }
1257 };
1258 
1259 template <class PixelType>
1260 class FunctorTraits<BrightnessContrastFunctor<PixelType> >
1261 : public FunctorTraitsBase<BrightnessContrastFunctor<PixelType> >
1262 {
1263  public:
1264  typedef VigraTrueType isUnaryFunctor;
1265 };
1266 
1267 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1268 
1269 template <>
1270 class BrightnessContrastFunctor<RGBValue<unsigned char> >
1271 {
1272  typedef NumericTraits<unsigned char>::RealPromote promote_type;
1273  BrightnessContrastFunctor<unsigned char> red, green, blue;
1274 
1275  public:
1276 
1277  typedef RGBValue<unsigned char> value_type;
1278 
1279  BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
1280  value_type const & min = value_type(0,0,0),
1281  value_type const & max = value_type(255, 255, 255))
1282  : red(brightness, contrast, min.red(), max.red()),
1283  green(brightness, contrast, min.green(), max.green()),
1284  blue(brightness, contrast, min.blue(), max.blue())
1285  {}
1286 
1287  value_type operator()(value_type const & v) const
1288  {
1289 
1290  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1291  }
1292 };
1293 
1294 
1295 
1296 /********************************************************/
1297 /* */
1298 /* GammaFunctor */
1299 /* */
1300 /********************************************************/
1301 
1302 /** \brief Perform gamma correction of an image.
1303 
1304  This functor applies a gamma correction to each pixel in order to
1305  modify the brightness of the image. Gamma values smaller than 1
1306  will increase image brightness, whereas values greater than 1
1307  decrease it. A value of gamma = 1 will have no effect. (See also
1308  BrightnessContrastFunctor, which additionally changes the
1309  contrast.)
1310 
1311  For \ref RGBValue "RGBValue's", the transforms are applied
1312  component-wise. For ease of use, the pixel values are assumed to
1313  lie between the given minimum and maximum values (in case of RGB,
1314  this is again understood component-wise). In case of <TT>unsigned
1315  char</TT>, min and max default to 0 and 255 respectively.
1316  Precisely, the following transform is applied to each <em>
1317  PixelValue</em>:
1318 
1319  \f[
1320  \begin{array}{rcl}
1321  V_1 & = & \frac{PixelValue - min}{max - min} \\
1322  V_2 & = & V_1^{gamma} \\
1323  Result & = & V_2 (max - min) + min
1324  \end{array}
1325  \f]
1326 
1327  If the <TT>PixelType</TT> is <TT>unsigned char</TT>, a
1328  look-up-table is used for faster computation.
1329 
1330  <b> Traits defined:</b>
1331 
1332  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
1333 
1334  <b> Usage:</b>
1335 
1336  <b>\#include</b> <vigra/transformimage.hxx><br>
1337  Namespace: vigra
1338 
1339  \code
1340  vigra::BImage bimage(width, height);
1341  double gamma;
1342  ...
1343  vigra::transformImage(srcImageRange(bimage), destImage(bimage),
1344  vigra::GammaFunctor<unsigned char>(gamma));
1345 
1346 
1347 
1348  vigra::FImage fimage(width, height);
1349  ...
1350 
1351  vigra::FindMinMax<float> minmax;
1352  vigra::inspectImage(srcImageRange(fimage), minmax);
1353 
1354  vigra::transformImage(srcImageRange(fimage), destImage(fimage),
1355  vigra::GammaFunctor<float>(gamma, minmax.min, minmax.max));
1356 
1357  \endcode
1358 
1359  <b> Required Interface:</b>
1360 
1361  Scalar types: must be a linear algebra (+, - *, NumericTraits),
1362  strict weakly ordered (<), and <TT>pow()</TT> must be defined.
1363 
1364  RGB values: the component type must meet the above requirements.
1365 */
1366 template <class PixelType>
1368 {
1369  typedef typename
1370  NumericTraits<PixelType>::RealPromote promote_type;
1371 
1372  public:
1373 
1374  /** the functor's argument type
1375  */
1376  typedef PixelType argument_type;
1377 
1378  /** the functor's result type
1379  */
1380  typedef PixelType result_type;
1381 
1382  /** \deprecated use argument_type and result_type
1383  */
1384  typedef PixelType value_type;
1385 
1386  /** Init functor for argument range <TT>[min, max]</TT>.
1387  <TT>gamma</TT> values < 1 will increase brightness, > 1
1388  will decrease it (gamma == 1 means no change).
1389  */
1391  argument_type const & min, argument_type const & max)
1392  : gamma_((promote_type)gamma),
1393  min_(min),
1394  diff_(max - min),
1395  zero_(NumericTraits<promote_type>::zero()),
1396  one_(NumericTraits<promote_type>::one())
1397  {}
1398 
1399  /** Calculate modified gray or color value
1400  */
1402  {
1403  promote_type v1 = (v - min_) / diff_;
1404  promote_type brighter = VIGRA_CSTD::pow(v1, gamma_);
1405  return result_type(diff_ * brighter + min_);
1406  }
1407 
1408  private:
1409  promote_type gamma_;
1410  argument_type min_;
1411  promote_type diff_, zero_, one_;
1412 };
1413 
1414 template <>
1415 class GammaFunctor<unsigned char>
1416 {
1417  typedef NumericTraits<unsigned char>::RealPromote promote_type;
1418  unsigned char lut[256];
1419 
1420  public:
1421 
1422  typedef unsigned char value_type;
1423 
1424  GammaFunctor(promote_type gamma,
1425  value_type const & min = 0, value_type const & max = 255)
1426  {
1427  GammaFunctor<promote_type> f(gamma, min, max);
1428 
1429  for(int i = min; i <= max; ++i)
1430  {
1431  lut[i] = static_cast<unsigned char>(f(i)+0.5);
1432  }
1433  }
1434 
1435  value_type operator()(value_type const & v) const
1436  {
1437 
1438  return lut[v];
1439  }
1440 };
1441 
1442 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
1443 
1444 template <class ComponentType>
1445 class GammaFunctor<RGBValue<ComponentType> >
1446 {
1447  typedef typename
1448  NumericTraits<ComponentType>::RealPromote promote_type;
1449  GammaFunctor<ComponentType> red, green, blue;
1450 
1451  public:
1452 
1453  typedef RGBValue<ComponentType> value_type;
1454 
1455  GammaFunctor(promote_type gamma,
1456  value_type const & min, value_type const & max)
1457  : red(gamma, min.red(), max.red()),
1458  green(gamma, min.green(), max.green()),
1459  blue(gamma, min.blue(), max.blue())
1460  {}
1461 
1462  value_type operator()(value_type const & v) const
1463  {
1464  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1465  }
1466 };
1467 
1468 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1469 
1470 template <>
1471 class GammaFunctor<RGBValue<int> >
1472 {
1473  typedef NumericTraits<int>::RealPromote promote_type;
1474  GammaFunctor<int> red, green, blue;
1475 
1476  public:
1477 
1478  typedef RGBValue<int> value_type;
1479 
1480  GammaFunctor(promote_type gamma,
1481  value_type const & min, value_type const & max)
1482  : red(gamma, min.red(), max.red()),
1483  green(gamma, min.green(), max.green()),
1484  blue(gamma, min.blue(), max.blue())
1485  {}
1486 
1487  value_type operator()(value_type const & v) const
1488  {
1489  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1490  }
1491 };
1492 
1493 template <>
1494 class GammaFunctor<RGBValue<float> >
1495 {
1496  typedef NumericTraits<float>::RealPromote promote_type;
1497  GammaFunctor<float> red, green, blue;
1498 
1499  public:
1500 
1501  typedef RGBValue<float> value_type;
1502 
1503  GammaFunctor(promote_type gamma,
1504  value_type const & min, value_type const & max)
1505  : red(gamma, min.red(), max.red()),
1506  green(gamma, min.green(), max.green()),
1507  blue(gamma, min.blue(), max.blue())
1508  {}
1509 
1510  value_type operator()(value_type const & v) const
1511  {
1512  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1513  }
1514 };
1515 
1516 template <class PixelType>
1517 class FunctorTraits<GammaFunctor<PixelType> >
1518 : public FunctorTraitsBase<GammaFunctor<PixelType> >
1519 {
1520  public:
1521  typedef VigraTrueType isUnaryFunctor;
1522 };
1523 
1524 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
1525 
1526 template <>
1527 class GammaFunctor<RGBValue<unsigned char> >
1528 {
1529  typedef NumericTraits<unsigned char>::RealPromote promote_type;
1530  GammaFunctor<unsigned char> red, green, blue;
1531 
1532  public:
1533  typedef RGBValue<unsigned char> value_type;
1534 
1535  GammaFunctor(promote_type gamma,
1536  value_type const & min = value_type(0,0,0),
1537  value_type const & max = value_type(255, 255, 255))
1538  : red(gamma, min.red(), max.red()),
1539  green(gamma, min.green(), max.green()),
1540  blue(gamma, min.blue(), max.blue())
1541  {}
1542 
1543  value_type operator()(value_type const & v) const
1544  {
1545  return value_type(red(v.red()), green(v.green()), blue(v.blue()));
1546  }
1547 };
1548 
1549 
1550 /********************************************************/
1551 /* */
1552 /* VectorNormFunctor */
1553 /* */
1554 /********************************************************/
1555 
1556 /** \brief A functor for computing the vector norm
1557 
1558  Calculate the magnitude or norm from a given vector-valued
1559  entity. The vector type will typically be some sort of
1560  ref vigra::TinyVector. If the vector is represented by a pair of
1561  scalar-valued images, use \ref vigra::MagnitudeFunctor instead.
1562 
1563  At least, the vector type is required to have a function
1564  '<em>result</em><TT> = dot(v,v)</TT>'.
1565 
1566  <b> Traits defined:</b>
1567 
1568  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
1569 
1570  <b> Usage:</b>
1571 
1572  <b>\#include</b> <vigra/transformimage.hxx><br>
1573  Namespace: vigra
1574 
1575  \code
1576  typedef vigra::TinyVector<float, 2> Vector;
1577  vigra::BasicImage<Vector> grad(width, height);
1578  vigra::FImage magn(width,height);
1579  ...
1580  vigra::transformImage(srcImageRange(grad), destImage(magn),
1581  VectorNormFunctor<float>()
1582  );
1583  \endcode
1584 
1585  \see vigra::TinyVector, dot(), vigra::MagnitudeFunctor
1586 */
1587 template <class ValueType>
1589 {
1590 public:
1591  /** the functor's argument type
1592  */
1593  typedef ValueType argument_type;
1594 
1595  /** the functor's result type
1596  */
1597  typedef typename NumericTraits<typename ValueType::value_type>::RealPromote result_type;
1598 
1599  /** calculate transform '<TT>sqrt(v1*v1 + v2*v2 + ...)</TT>'.
1600  */
1602  {
1603  return VIGRA_CSTD::sqrt( dot(a,a) );
1604  }
1605 }; //-- class VectorNormFunctor
1606 
1607 template <class ValueType>
1608 class FunctorTraits<VectorNormFunctor<ValueType> >
1609 : public FunctorTraitsBase<VectorNormFunctor<ValueType> >
1610 {
1611  public:
1612  typedef VigraTrueType isUnaryFunctor;
1613 };
1614 
1615 /** \brief A functor for computing the squared vector norm
1616 
1617  Calculate the squared magnitude or norm from a given
1618  vector-valued entity. The vector type will typically be some
1619  sort of TinyVector.
1620 
1621  At least, the vector type is required to have a function
1622  '<em>result</em><TT> = dot(v,v)</TT>'.
1623 
1624  For an example of its usage see VectorNormFunctor
1625 
1626  <b> Traits defined:</b>
1627 
1628  <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
1629 
1630  \see TinyVector, dot()
1631 */
1632 template <class ValueType>
1634 {
1635 public:
1636  /** the functor's argument type
1637  */
1638  typedef ValueType argument_type;
1639 
1640  /** the functor's result type
1641  */
1642  typedef typename NumericTraits<typename ValueType::value_type>::RealPromote result_type;
1643 
1644  /** calculate transform '<TT>v1*v1 + v2*v2 + ...</TT>'.
1645  */
1647  {
1648  return dot(a,a);
1649  }
1650 }; //-- class VectorNormSqFunctor
1651 
1652 template <class ValueType>
1653 class FunctorTraits<VectorNormSqFunctor<ValueType> >
1654 : public FunctorTraitsBase<VectorNormSqFunctor<ValueType> >
1655 {
1656  public:
1657  typedef VigraTrueType isUnaryFunctor;
1658 };
1659 
1660 //@}
1661 
1662 } // namespace vigra
1663 
1664 #endif // VIGRA_TRANSFORMIMAGE_HXX
NumericTraits< typename ValueType::value_type >::RealPromote result_type
Definition: transformimage.hxx:1597
PixelType argument_type
Definition: transformimage.hxx:1376
A functor for computing the squared vector norm.
Definition: transformimage.hxx:1633
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:1110
void transformImage(...)
Apply unary point transformation to each pixel.
NumericTraits< typename ValueType::value_type >::RealPromote result_type
Definition: transformimage.hxx:1642
Adjust brightness and contrast of an image.
Definition: transformimage.hxx:1101
result_type operator()(argument_type s) const
Definition: transformimage.hxx:1002
GammaFunctor(double gamma, argument_type const &min, argument_type const &max)
Definition: transformimage.hxx:1390
SrcValueType argument_type
Definition: transformimage.hxx:986
ValueType argument_type
Definition: transformimage.hxx:1638
PixelType result_type
Definition: transformimage.hxx:1380
A functor for computing the vector norm.
Definition: transformimage.hxx:1588
PixelType result_type
Definition: transformimage.hxx:1114
result_type operator()(const argument_type &a) const
Definition: transformimage.hxx:1601
result_type operator()(argument_type const &v) const
Definition: transformimage.hxx:1401
Threshold(argument_type lower, argument_type higher, result_type noresult, result_type yesresult)
Definition: transformimage.hxx:994
ValueType argument_type
Definition: transformimage.hxx:1593
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:1125
PixelType value_type
Definition: transformimage.hxx:1384
void gradientBasedTransform(...)
Calculate a function of the image gradient.
double gamma(double x)
The gamma function.
Definition: mathutil.hxx:1570
PixelType value_type
Definition: transformimage.hxx:1118
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:1367
result_type operator()(const argument_type &a) const
Definition: transformimage.hxx:1646
Threshold an image.
Definition: transformimage.hxx:980
result_type operator()(argument_type const &v) const
Definition: transformimage.hxx:1137
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:990
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.0