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

transformimage.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35
36
37 #ifndef VIGRA_TRANSFORMIMAGE_HXX
38 #define VIGRA_TRANSFORMIMAGE_HXX
39
40 #include "utilities.hxx"
41 #include "numerictraits.hxx"
42 #include "iteratortraits.hxx"
43 #include "rgbvalue.hxx"
44 #include "functortraits.hxx"
45 #include "inspectimage.hxx"
46 #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 experessions",
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 experessions",
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 */
355 doxygen_overloaded_function(template <...> void transformImageIf)
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 */
510 doxygen_overloaded_function(template <...> void gradientBasedTransform)
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>
900 linearRangeMapping(
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>
916 linearRangeMapping(
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>
980 class Threshold
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 */
994 Threshold(argument_type lower, argument_type higher,
995 result_type noresult, result_type yesresult)
996 : lower_(lower), higher_(higher),
997 yesresult_(yesresult), noresult_(noresult)
998 {}
999
1000 /** calculate transform
1001 */
1002 result_type operator()(argument_type s) const
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>
1101 class BrightnessContrastFunctor
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 */
1137 result_type operator()(argument_type const & v) const
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>
1367 class GammaFunctor
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 */
1390 GammaFunctor(double gamma,
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 */
1401 result_type operator()(argument_type const & v) const
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>
1588 class VectorNormFunctor
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 */
1601 result_type operator()( const argument_type &a ) const
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>
1633 class VectorNormSqFunctor
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 */
1646 result_type operator()( const argument_type &a ) const
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

© 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.10.0 (Mon Nov 18 2013)