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

# vigra/transformimage.hxx

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
    00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
    00005 /*                                                                      */
    00006 /*    This file is part of the VIGRA computer vision library.           */
    00007 /*    ( Version 1.6.0, Aug 13 2008 )                                    */
    00008 /*    The VIGRA Website is                                              */
    00009 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
    00010 /*    Please direct questions, bug reports, and contributions to        */
    00011 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00012 /*        vigra@informatik.uni-hamburg.de                               */
    00013 /*                                                                      */
    00014 /*    Permission is hereby granted, free of charge, to any person       */
    00015 /*    obtaining a copy of this software and associated documentation    */
    00016 /*    files (the "Software"), to deal in the Software without           */
    00017 /*    restriction, including without limitation the rights to use,      */
    00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00019 /*    sell copies of the Software, and to permit persons to whom the    */
    00020 /*    Software is furnished to do so, subject to the following          */
    00021 /*    conditions:                                                       */
    00022 /*                                                                      */
    00023 /*    The above copyright notice and this permission notice shall be    */
    00024 /*    included in all copies or substantial portions of the             */
    00025 /*    Software.                                                         */
    00026 /*                                                                      */
    00027 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00028 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00029 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00030 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00031 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00032 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00033 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00034 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00035 /*                                                                      */
    00036 /************************************************************************/
    00037
    00038
    00039 #ifndef VIGRA_TRANSFORMIMAGE_HXX
    00040 #define VIGRA_TRANSFORMIMAGE_HXX
    00041
    00042 #include "utilities.hxx"
    00043 #include "numerictraits.hxx"
    00044 #include "iteratortraits.hxx"
    00045 #include "rgbvalue.hxx"
    00046 #include "functortraits.hxx"
    00047
    00048 namespace vigra {
    00049
    00050 /** \addtogroup TransformAlgo Algorithms to Transform Images
    00051     Apply functor to calculate a pixelwise transformation of one image
    00052
    00053     @{
    00054 */
    00055
    00056 /********************************************************/
    00057 /*                                                      */
    00058 /*                      transformLine                   */
    00059 /*                                                      */
    00060 /********************************************************/
    00061
    00062 template <class SrcIterator, class SrcAccessor,
    00063           class DestIterator, class DestAccessor, class Functor>
    00064 void
    00065 transformLine(SrcIterator s,
    00066               SrcIterator send, SrcAccessor src,
    00067               DestIterator d, DestAccessor dest,
    00068               Functor const & f)
    00069 {
    00070     for(; s != send; ++s, ++d)
    00071         dest.set(f(src(s)), d);
    00072 }
    00073
    00074 template <class SrcIterator, class SrcAccessor,
    00075           class MaskIterator, class MaskAccessor,
    00076           class DestIterator, class DestAccessor,
    00077           class Functor>
    00078 void
    00079 transformLineIf(SrcIterator s,
    00080                 SrcIterator send, SrcAccessor src,
    00081                 MaskIterator m, MaskAccessor mask,
    00082                 DestIterator d, DestAccessor dest,
    00083                 Functor const & f)
    00084 {
    00085     for(; s != send; ++s, ++d, ++m)
    00086         if(mask(m))
    00087             dest.set(f(src(s)), d);
    00088 }
    00089
    00090 /********************************************************/
    00091 /*                                                      */
    00092 /*                      transformImage                  */
    00093 /*                                                      */
    00094 /********************************************************/
    00095
    00096 /** \brief Apply unary point transformation to each pixel.
    00097
    00098     The transformation given by the functor is applied to every source
    00099     pixel and the result written into the corresponding destination pixel.
    00100     The function uses accessors to access the pixel data.
    00101     Note that the unary functors of the STL can be used in addition to
    00102     the functors specifically defined in \ref TransformFunctor.
    00103     Creation of new functors is easiest by using \ref FunctorExpressions.
    00104
    00105     <b> Declarations:</b>
    00106
    00107     pass arguments explicitly:
    00108     \code
    00109     namespace vigra {
    00110         template <class SrcImageIterator, class SrcAccessor,
    00111                   class DestImageIterator, class DestAccessor, class Functor>
    00112         void
    00113         transformImage(SrcImageIterator src_upperleft,
    00114                SrcImageIterator src_lowerright, SrcAccessor sa,
    00115                DestImageIterator dest_upperleft, DestAccessor da,
    00116                Functor const & f)
    00117     }
    00118     \endcode
    00119
    00120
    00121     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00122     \code
    00123     namespace vigra {
    00124         template <class SrcImageIterator, class SrcAccessor,
    00125                   class DestImageIterator, class DestAccessor, class Functor>
    00126         void
    00127         transformImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00128                pair<DestImageIterator, DestAccessor> dest,
    00129                Functor const & f)
    00130     }
    00131     \endcode
    00132
    00133     <b> Usage:</b>
    00134
    00135     <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
    00136     Namespace: vigra
    00137
    00138     \code
    00139
    00140     #include <cmath>         // for sqrt()
    00141
    00142     vigra::transformImage(srcImageRange(src),
    00143                           destImage(dest),
    00144                           (double(*)(double))&std::sqrt );
    00145
    00146     \endcode
    00147
    00148     <b> Required Interface:</b>
    00149
    00150     \code
    00151     SrcImageIterator src_upperleft, src_lowerright;
    00152     DestImageIterator      dest_upperleft;
    00153     SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
    00154     DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
    00155
    00156     SrcAccessor src_accessor;
    00157     DestAccessor dest_accessor;
    00158
    00159     Functor functor;
    00160
    00161     dest_accessor.set(functor(src_accessor(sx)), dx);
    00162
    00163     \endcode
    00164
    00165 */
    00166 doxygen_overloaded_function(template <...> void transformImage)
    00167
    00168 template <class SrcImageIterator, class SrcAccessor,
    00169           class DestImageIterator, class DestAccessor, class Functor>
    00170 void
    00171 transformImage(SrcImageIterator src_upperleft,
    00172                SrcImageIterator src_lowerright, SrcAccessor sa,
    00173                DestImageIterator dest_upperleft, DestAccessor da,
    00174                Functor const & f)
    00175 {
    00176     int w = src_lowerright.x - src_upperleft.x;
    00177
    00178     for(; src_upperleft.y < src_lowerright.y; ++src_upperleft.y, ++dest_upperleft.y)
    00179     {
    00180         transformLine(src_upperleft.rowIterator(),
    00181                       src_upperleft.rowIterator() + w, sa,
    00182                       dest_upperleft.rowIterator(), da, f);
    00183     }
    00184 }
    00185
    00186 template <class SrcImageIterator, class SrcAccessor,
    00187       class DestImageIterator, class DestAccessor, class Functor>
    00188 inline
    00189 void
    00190 transformImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00191                pair<DestImageIterator, DestAccessor> dest,
    00192                Functor const & f)
    00193 {
    00194     transformImage(src.first, src.second, src.third,
    00195                    dest.first, dest.second, f);
    00196 }
    00197
    00198 /********************************************************/
    00199 /*                                                      */
    00200 /*                   transformImageIf                   */
    00201 /*                                                      */
    00202 /********************************************************/
    00203
    00204 /** \brief Apply unary point transformation to each pixel within the ROI
    00205     (i.e., where the mask is non-zero).
    00206
    00207     The transformation given by the functor is applied to every source
    00208     pixel in the ROI (i.e. when the return vlaue of the mask's accessor
    00209     is not zero)
    00210     and the result is written into the corresponding destination pixel.
    00211     The function uses accessors to access the pixel data.
    00212     Note that the unary functors of the STL can be used in addition to
    00213     the functors specifically defined in \ref TransformFunctor.
    00214     Creation of new functors is easiest by using \ref FunctorExpressions.
    00215
    00216     <b> Declarations:</b>
    00217
    00218     pass arguments explicitly:
    00219     \code
    00220     namespace vigra {
    00221         template <class SrcImageIterator, class SrcAccessor,
    00222                   class MaskImageIterator, class MaskAccessor,
    00223                   class DestImageIterator, clas DestAccessor,
    00224                   class Functor>
    00225         void
    00226         transformImageIf(SrcImageIterator src_upperleft,
    00227                          SrcImageIterator src_lowerright, SrcAccessor sa,
    00228                          MaskImageIterator mask_upperleft, MaskAccessor ma,
    00229                          DestImageIterator dest_upperleft, DestAccessor da,
    00230                          Functor const & f)
    00231     }
    00232     \endcode
    00233
    00234
    00235     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00236     \code
    00237     namespace vigra {
    00238         template <class SrcImageIterator, class SrcAccessor,
    00239                   class MaskImageIterator, class MaskAccessor,
    00240                   class DestImageIterator, clas DestAccessor,
    00241                   class Functor>
    00242         void
    00243         transformImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00244                          pair<MaskImageIterator, MaskAccessor> mask,
    00245                          pair<DestImageIterator, DestAccessor> dest,
    00246                          Functor const & f)
    00247     }
    00248     \endcode
    00249
    00250     <b> Usage:</b>
    00251
    00252         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
    00253         Namespace: vigra
    00254
    00255     \code
    00256     #include <cmath>         // for sqrt()
    00257
    00258     vigra::transformImageIf(srcImageRange(src),
    00259                             maskImage(mask),
    00260                             destImage(dest),
    00261                             (double(*)(double))&std::sqrt );
    00262
    00263     \endcode
    00264
    00265     <b> Required Interface:</b>
    00266
    00267     \code
    00268     SrcImageIterator src_upperleft, src_lowerright;
    00269     DestImageIterator  dest_upperleft;
    00270     MaskImageIterator mask_upperleft;
    00271     SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
    00272     MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
    00273     DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
    00274
    00275     SrcAccessor src_accessor;
    00276     DestAccessor dest_accessor;
    00277     MaskAccessor mask_accessor;
    00278     Functor functor;
    00279
    00280     if(mask_accessor(mx))
    00281        dest_accessor.set(functor(src_accessor(sx)), dx);
    00282
    00283     \endcode
    00284
    00285 */
    00286 doxygen_overloaded_function(template <...> void transformImageIf)
    00287
    00288 template <class SrcImageIterator, class SrcAccessor,
    00289           class MaskImageIterator, class MaskAccessor,
    00290           class DestImageIterator, class DestAccessor,
    00291           class Functor>
    00292 void
    00293 transformImageIf(SrcImageIterator src_upperleft,
    00294                  SrcImageIterator src_lowerright, SrcAccessor sa,
    00295                  MaskImageIterator mask_upperleft, MaskAccessor ma,
    00296                  DestImageIterator dest_upperleft, DestAccessor da,
    00297                  Functor const & f)
    00298 {
    00299     int w = src_lowerright.x - src_upperleft.x;
    00300
    00301     for(; src_upperleft.y < src_lowerright.y;
    00302              ++src_upperleft.y, ++mask_upperleft.y, ++dest_upperleft.y)
    00303     {
    00304         transformLineIf(src_upperleft.rowIterator(),
    00305                         src_upperleft.rowIterator() + w, sa,
    00306                         mask_upperleft.rowIterator(), ma,
    00307                         dest_upperleft.rowIterator(), da, f);
    00308     }
    00309 }
    00310
    00311 template <class SrcImageIterator, class SrcAccessor,
    00312           class MaskImageIterator, class MaskAccessor,
    00313           class DestImageIterator, class DestAccessor,
    00314           class Functor>
    00315 inline
    00316 void
    00317 transformImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00318                  pair<MaskImageIterator, MaskAccessor> mask,
    00319                  pair<DestImageIterator, DestAccessor> dest,
    00320                  Functor const & f)
    00321 {
    00322     transformImageIf(src.first, src.second, src.third,
    00323                      mask.first, mask.second,
    00324                      dest.first, dest.second, f);
    00325 }
    00326
    00327 /********************************************************/
    00328 /*                                                      */
    00329 /*               gradientBasedTransform                 */
    00330 /*                                                      */
    00331 /********************************************************/
    00332
    00333 /** \brief Calculate a function of the image gradient.
    00334
    00335     The gradient and the function represented by <TT>Functor f</TT>
    00336     are calculated in one go: for each location, the symmetric
    00337     difference in x- and y-directions (asymmetric difference at the
    00338     image borders) are passed to the given functor, and the result is
    00339     written the destination image. Functors to be used with this
    00340     function include \ref MagnitudeFunctor and \ref
    00341     RGBGradientMagnitudeFunctor.
    00342
    00343     <b> Declarations:</b>
    00344
    00345     pass arguments explicitly:
    00346     \code
    00347     namespace vigra {
    00348         template <class SrcImageIterator, class SrcAccessor,
    00349                   class DestImageIterator, class DestAccessor, class Functor>
    00350         void
    00351         gradientBasedTransform(SrcImageIterator srcul, SrcImageIterator srclr, SrcAccessor sa,
    00352                                DestImageIterator destul, DestAccessor da, Functor const & f)
    00353     }
    00354     \endcode
    00355
    00356
    00357     use argument objects in conjunction with \ref ArgumentObjectFactories :
    00358     \code
    00359     namespace vigra {
    00360         template <class SrcImageIterator, class SrcAccessor,
    00361                   class DestImageIterator, class DestAccessor, class Functor>
    00362         void
    00363         gradientBasedTransform(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00364                                pair<DestImageIterator, DestAccessor> dest, Functor const & const & f)
    00365     }
    00366     \endcode
    00367
    00368     <b> Usage:</b>
    00369
    00370     <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>>
    00371
    00372
    00373     \code
    00374     vigra::FImage src(w,h), magnitude(w,h);
    00375     ...
    00376
    00377     gradientBasedTransform(srcImageRange(src), destImage(magnitude),
    00378                                 vigra::MagnitudeFunctor<float>());
    00379     \endcode
    00380
    00381     <b> Required Interface:</b>
    00382
    00383     \code
    00384     SrcImageIterator is, isend;
    00385     DestImageIterator id;
    00386
    00387     SrcAccessor src_accessor;
    00388     DestAccessor dest_accessor;
    00389
    00390     typename NumericTraits<typename SrcAccessor::value_type>::RealPromote
    00391         diffx, diffy;
    00392
    00393     diffx = src_accessor(is, Diff2D(-1,0)) - src_accessor(is, Diff2D(1,0));
    00394     diffy = src_accessor(is, Diff2D(0,-1)) - src_accessor(is, Diff2D(0,1));
    00395
    00396     Functor f;
    00397
    00398     dest_accessor.set(f(diffx, diffy), id);
    00399
    00400     \endcode
    00401
    00402 */
    00403 doxygen_overloaded_function(template <...> void gradientBasedTransform)
    00404
    00405 template <class SrcImageIterator, class SrcAccessor,
    00406           class DestImageIterator, class DestAccessor, class Functor>
    00407 void
    00408 gradientBasedTransform(SrcImageIterator srcul, SrcImageIterator srclr, SrcAccessor sa,
    00409                        DestImageIterator destul, DestAccessor da, Functor const & grad)
    00410 {
    00411     int w = srclr.x - srcul.x;
    00412     int h = srclr.y - srcul.y;
    00413     int x,y;
    00414
    00415     SrcImageIterator sy = srcul;
    00416     DestImageIterator dy = destul;
    00417
    00418     static const Diff2D left(-1,0);
    00419     static const Diff2D right(1,0);
    00420     static const Diff2D top(0,-1);
    00421     static const Diff2D bottom(0,1);
    00422
    00423     typename NumericTraits<typename SrcAccessor::value_type>::RealPromote
    00424              diffx, diffy;
    00425
    00426     SrcImageIterator sx = sy;
    00427     DestImageIterator dx = dy;
    00428
    00429     diffx = sa(sx) - sa(sx, right);
    00430     diffy = sa(sx) - sa(sx, bottom);
    00431     da.set(grad(diffx, diffy), dx);
    00432
    00433     for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
    00434     {
    00435         diffx = (sa(sx, left) - sa(sx, right)) / 2.0;
    00436         diffy = sa(sx) - sa(sx, bottom);
    00437         da.set(grad(diffx, diffy), dx);
    00438     }
    00439
    00440     diffx = sa(sx, left) - sa(sx);
    00441     diffy = sa(sx) - sa(sx, bottom);
    00442     da.set(grad(diffx, diffy), dx);
    00443
    00444     ++sy.y;
    00445     ++dy.y;
    00446
    00447     for(y=2; y<h; ++y, ++sy.y, ++dy.y)
    00448     {
    00449         sx = sy;
    00450         dx = dy;
    00451
    00452         diffx = sa(sx) - sa(sx, right);
    00453         diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0;
    00454         da.set(grad(diffx, diffy), dx);
    00455
    00456         for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
    00457         {
    00458             diffx = (sa(sx, left) - sa(sx, right)) / 2.0;
    00459             diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0;
    00460             da.set(grad(diffx, diffy), dx);
    00461         }
    00462
    00463         diffx = sa(sx, left) - sa(sx);
    00464         diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0;
    00465         da.set(grad(diffx, diffy), dx);
    00466     }
    00467
    00468     sx = sy;
    00469     dx = dy;
    00470
    00471     diffx = sa(sx) - sa(sx, right);
    00472     diffy = sa(sx, top) - sa(sx);
    00473     da.set(grad(diffx, diffy), dx);
    00474
    00475     for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
    00476     {
    00477         diffx = (sa(sx, left) - sa(sx, right)) / 2.0;
    00478         diffy = sa(sx, top) - sa(sx);
    00479         da.set(grad(diffx, diffy), dx);
    00480     }
    00481
    00482     diffx = sa(sx, left) - sa(sx);
    00483     diffy = sa(sx, top) - sa(sx);
    00484     da.set(grad(diffx, diffy), dx);
    00485 }
    00486
    00487 template <class SrcImageIterator, class SrcAccessor,
    00488           class DestImageIterator, class DestAccessor, class Functor>
    00489 inline
    00490 void
    00491 gradientBasedTransform(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00492                        pair<DestImageIterator, DestAccessor> dest, Functor const & grad)
    00493 {
    00494     gradientBasedTransform(src.first, src.second, src.third,
    00495                            dest.first, dest.second, grad);
    00496 }
    00497
    00498 /** @} */
    00499 /** \addtogroup TransformFunctor Functors to Transform Images
    00500
    00501     Note that the unary functors of the STL can also be used in
    00502     connection with \ref transformImage().
    00503 */
    00504 //@{
    00505
    00506 template <class DestValueType, class Multiplier = double>
    00507 class LinearIntensityTransform
    00508 {
    00509   public:
    00510         /* the functors argument type (actually, since
    00511            <tt>operator()</tt> is a template, much more types are possible)
    00512         */
    00513     typedef DestValueType argument_type;
    00514
    00515         /* the functors result type
    00516         */
    00517     typedef DestValueType result_type;
    00518
    00519         /* \deprecated use argument_type and result_type
    00520         */
    00521     typedef DestValueType value_type;
    00522
    00523         /* type of the offset (used in internal calculations to prevent
    00524             overflows and minimize round-off errors).
    00525         */
    00526     typedef typename
    00527             NumericTraits<DestValueType>::RealPromote argument_promote;
    00528
    00529         /* type of the scale factor
    00530         */
    00531     typedef Multiplier scalar_multiplier_type;
    00532
    00533         /* init scale and offset
    00534         */
    00535     LinearIntensityTransform(scalar_multiplier_type scale, argument_promote offset)
    00536     : scale_(scale), offset_(offset)
    00537     {}
    00538
    00539         /* calculate transform
    00540         */
    00541     template <class SrcValueType>
    00542     result_type operator()(SrcValueType const & s) const
    00543     {
    00544         return NumericTraits<result_type>::fromRealPromote(scale_ * (s + offset_));
    00545     }
    00546
    00547   private:
    00548
    00549     scalar_multiplier_type scale_;
    00550     argument_promote offset_;
    00551 };
    00552
    00553 template <class DestValueType, class Multiplier>
    00554 class FunctorTraits<LinearIntensityTransform<DestValueType, Multiplier> >
    00555 : public FunctorTraitsBase<LinearIntensityTransform<DestValueType, Multiplier> >
    00556 {
    00557   public:
    00558     typedef VigraTrueType isUnaryFunctor;
    00559 };
    00560
    00561 template <class DestValueType, class Multiplier = double>
    00562 class ScalarIntensityTransform
    00563 {
    00564   public:
    00565         /* the functors argument type (actually, since
    00566            <tt>operator()</tt> is a template, much more types are possible)
    00567         */
    00568     typedef DestValueType argument_type;
    00569
    00570         /* the functors result type
    00571         */
    00572     typedef DestValueType result_type;
    00573
    00574         /* \deprecated use argument_type and result_type
    00575         */
    00576     typedef DestValueType value_type;
    00577
    00578         /* type of the scale factor
    00579         */
    00580     typedef Multiplier scalar_multiplier_type;
    00581
    00582         /* init scale
    00583         */
    00584     ScalarIntensityTransform(scalar_multiplier_type scale)
    00585     : scale_(scale)
    00586     {}
    00587
    00588         /* calculate transform
    00589         */
    00590     template <class SrcValueType>
    00591     result_type operator()(SrcValueType const & s) const
    00592     {
    00593         return NumericTraits<result_type>::fromRealPromote(scale_ * s);
    00594     }
    00595
    00596   private:
    00597     scalar_multiplier_type scale_;
    00598 };
    00599
    00600 template <class DestValueType, class Multiplier>
    00601 class FunctorTraits<ScalarIntensityTransform<DestValueType, Multiplier> >
    00602 : public FunctorTraitsBase<ScalarIntensityTransform<DestValueType, Multiplier> >
    00603 {
    00604   public:
    00605     typedef VigraTrueType isUnaryFunctor;
    00606 };
    00607
    00608 /********************************************************/
    00609 /*                                                      */
    00610 /*              linearIntensityTransform                */
    00611 /*                                                      */
    00612 /********************************************************/
    00613
    00614 /** \brief Apply a linear transform to the source pixel values
    00615
    00616     Factory function for a functor that linearly transforms the
    00617     source pixel values. The functor applies the transform
    00618     '<TT>destvalue = scale * (srcvalue + offset)</TT>' to every pixel.
    00619     This can, for example, be used to transform images into the visible
    00620     range 0...255 or to invert an image.
    00621
    00622     If you leave out the second parameter / offset, you will get an
    00623     optimized version of the functor which only scales by the given
    00624     factor, however you have to make the template parameter (pixel
    00625     type) explicit then.
    00626
    00627     <b> Traits defined:</b>
    00628
    00629     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
    00630
    00631     <b> Declaration:</b>
    00632
    00633     \code
    00634     namespace vigra {
    00635         template <class Multiplier, class DestValueType>
    00636         LinearIntensityTransform<DestValueType, Multiplier>
    00637         linearIntensityTransform(Multiplier scale, DestValueType offset);
    00638
    00639         template <class DestValueType, class Multiplier>
    00640         ScalarIntensityTransform<DestValueType, Multiplier>
    00641         linearIntensityTransform(Multiplier scale);
    00642     }
    00643     \endcode
    00644
    00645     <b> Usage:</b>
    00646
    00647         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
    00648         Namespace: vigra
    00649
    00650     \code
    00651     vigra::IImage src(width, height);
    00652     vigra::BImage dest(width, height);
    00653     ...
    00654     vigra::FindMinMax<IImage::PixelType> minmax;   // functor to find range
    00655
    00656     vigra::inspectImage(srcImageRange(src), minmax); // find original range
    00657
    00658     // transform to range 0...255
    00659     vigra::transformImage(srcImageRange(src), destImage(dest),
    00660                           linearIntensityTransform(
    00661                             255.0 / (minmax.max - minmax.min), // scaling
    00662                           - minmax.min));                    // offset
    00663     \endcode
    00664
    00665     The one-parameter version can be used like this:
    00666
    00667     \code
    00668     // scale from 0..255 to 0..1.0
    00669     FImage dest(src.size());
    00670
    00671     vigra::transformImage(srcImageRange(src), destImage(dest),
    00672                           linearIntensityTransform<float>(1.0 / 255));
    00673     \endcode
    00674
    00675     <b> Required Interface:</b>
    00676
    00677     The source and destination value types must be models of \ref LinearSpace in both cases.
    00678
    00679 */
    00680 template <class Multiplier, class DestValueType>
    00681 LinearIntensityTransform<DestValueType, Multiplier>
    00682 linearIntensityTransform(Multiplier scale, DestValueType offset)
    00683 {
    00684     return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
    00685 }
    00686
    00687 template <class DestValueType, class Multiplier>
    00688 ScalarIntensityTransform<DestValueType, Multiplier>
    00689 linearIntensityTransform(Multiplier scale)
    00690 {
    00691     return ScalarIntensityTransform<DestValueType, Multiplier>(scale);
    00692 }
    00693
    00694 /********************************************************/
    00695 /*                                                      */
    00696 /*                   linearRangeMapping                 */
    00697 /*                                                      */
    00698 /********************************************************/
    00699
    00700 /** \brief Map a source intensity range linearly to a destination range.
    00701
    00702     Factory function for a functor that linearly transforms the
    00703     source pixel values. The functor applies the transform
    00704     '<TT>destvalue = scale * (srcvalue + offset)</TT>' to every pixel,
    00705     where <tt>scale = (dest_max - dest_min) / (src_max - src_min)</tt>
    00706     and <tt>offset = dest_min / scale - src_min</tt>. As a result,
    00707     the pixel values <tt>src_max</tt>, <tt>src_min</tt> in the source image
    00708     are mapped onto <tt>dest_max</tt>, <tt>dest_min</tt> respectively.
    00709     This works for scalar as well as vector pixel types.
    00710
    00711     <b> Declaration:</b>
    00712
    00713     \code
    00714     namespace vigra {
    00715         template <class SrcValueType, class DestValueType>
    00716         LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
    00717         linearRangeMapping(SrcValueType src_min, SrcValueType src_max,
    00718                            DestValueType dest_min, DestValueType dest_max );
    00719     }
    00720     \endcode
    00721
    00722     <b> Usage:</b>
    00723
    00724         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
    00725         Namespace: vigra
    00726
    00727     \code
    00728     vigra::IImage src(width, height);
    00729     vigra::BImage dest(width, height);
    00730     ...
    00731     vigra::FindMinMax<IImage::PixelType> minmax;   // functor to find range
    00732
    00733     vigra::inspectImage(srcImageRange(src), minmax); // find original range
    00734
    00735     // transform to range 0...255
    00736     vigra::transformImage(srcImageRange(src), destImage(dest),
    00737                           linearRangeTransform(
    00738                             minmax.min, minmax.max,               // src range
    00739                             (unsigned char)0, (unsigned char)255) // dest range
    00740                           );
    00741     \endcode
    00742
    00743     <b> Required Interface:</b>
    00744
    00745     The source and destination value types must be models of \ref LinearSpace in both cases.
    00746
    00747 */
    00748 template <class SrcValueType, class DestValueType>
    00749 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
    00750 linearRangeMapping(SrcValueType src_min, SrcValueType src_max,
    00751                    DestValueType dest_min, DestValueType dest_max )
    00752 {
    00753     return linearRangeMapping(src_min, src_max, dest_min, dest_max,
    00754             typename NumericTraits<DestValueType>::isScalar());
    00755 }
    00756
    00757 template <class SrcValueType, class DestValueType>
    00758 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
    00759 linearRangeMapping(
    00760     SrcValueType src_min, SrcValueType src_max,
    00761     DestValueType dest_min, DestValueType dest_max,
    00762     VigraTrueType /* isScalar */ )
    00763 {
    00764     typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
    00765     Multiplier diff = src_max - src_min;
    00766     Multiplier scale = diff == NumericTraits<Multiplier>::zero()
    00767                      ? NumericTraits<Multiplier>::one()
    00768                      : (dest_max - dest_min) / diff;
    00769     return LinearIntensityTransform<DestValueType, Multiplier>(
    00770                                    scale, dest_min / scale - src_min );
    00771 }
    00772
    00773 template <class SrcValueType, class DestValueType>
    00774 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
    00775 linearRangeMapping(
    00776     SrcValueType src_min, SrcValueType src_max,
    00777     DestValueType dest_min, DestValueType dest_max,
    00778     VigraFalseType /* isScalar */ )
    00779 {
    00780     typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
    00781     typedef typename Multiplier::value_type MComponent;
    00782     Multiplier scale(dest_max), offset(dest_max);
    00783     for(unsigned int i=0; i<src_min.size(); ++i)
    00784     {
    00785         MComponent diff = src_max[i] - src_min[i];
    00786         scale[i] = diff == NumericTraits<MComponent>::zero()
    00787                      ? NumericTraits<MComponent>::one()
    00788                      : (dest_max[i] - dest_min[i]) / diff;
    00789         offset[i] = dest_min[i] / scale[i] - src_min[i];
    00790     }
    00791     return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
    00792 }
    00793
    00794 /********************************************************/
    00795 /*                                                      */
    00796 /*                      Threshold                       */
    00797 /*                                                      */
    00798 /********************************************************/
    00799
    00800 /** \brief Threshold an image.
    00801
    00802     If a source pixel is above or equal the lower and below
    00803     or equal the higher threshold (i.e. within the closed interval
    00804     [lower, heigher]) the destination pixel is set to 'yesresult',
    00805     otherwise to 'noresult'.
    00806
    00807     <b> Traits defined:</b>
    00808
    00809     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
    00810
    00811     <b> Usage:</b>
    00812
    00813         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
    00814         Namespace: vigra
    00815
    00816     \code
    00817     vigra::BImage src(width, height), dest(width, height);
    00818     ...
    00819     vigra::transformImage(src.upperLeft(), src.lowerRight(), src.accessor(),
    00820        dest.upperLeft(), dest.accessor(),
    00821        vigra::Threshold<
    00822           vigra::BImage::PixelType, vigra::BImage::PixelType>(10, 100, 0, 255));
    00823
    00824     \endcode
    00825
    00826     <b> Required Interface:</b>
    00827
    00828     \code
    00829
    00830     SrcValueType   src;
    00831     DestValueType  dest, yesresult, noresult;
    00832
    00833     dest = ((src < lower) || (higher < src)) ? noresult : yesresult;
    00834
    00835     \endcode
    00836
    00837 */
    00838 template <class SrcValueType, class DestValueType>
    00839 class Threshold
    00840 {
    00841    public:
    00842
    00843         /** the functor's argument type
    00844         */
    00845     typedef SrcValueType argument_type;
    00846
    00847         /** the functor's result type
    00848         */
    00849     typedef DestValueType result_type;
    00850
    00851         /** init thresholds and return values
    00852         */
    00853     Threshold(argument_type lower, argument_type higher,
    00854               result_type noresult, result_type yesresult)
    00855     : lower_(lower), higher_(higher),
    00856       yesresult_(yesresult), noresult_(noresult)
    00857     {}
    00858
    00859         /** calculate transform
    00860         */
    00861     result_type operator()(argument_type s) const
    00862     {
    00863         return ((s < lower_) || (higher_ < s)) ? noresult_ : yesresult_;
    00864     }
    00865
    00866   private:
    00867
    00868     argument_type lower_, higher_;
    00869     result_type yesresult_, noresult_;
    00870 };
    00871
    00872 template <class SrcValueType, class DestValueType>
    00873 class FunctorTraits<Threshold<SrcValueType, DestValueType> >
    00874 : public FunctorTraitsBase<Threshold<SrcValueType, DestValueType> >
    00875 {
    00876   public:
    00877     typedef VigraTrueType isUnaryFunctor;
    00878 };
    00879
    00880 /********************************************************/
    00881 /*                                                      */
    00882 /*                BrightnessContrastFunctor             */
    00883 /*                                                      */
    00884 /********************************************************/
    00885
    00886 /** \brief Adjust brightness and contrast of an image.
    00887
    00888     This functor applies a gamma correction to each pixel in order to
    00889     modify the brightness of the image. To the result of the gamma
    00890     correction, another transform is applied that modifies the
    00891     contrast. The brightness and contrast parameters must be
    00892     positive. Values greater than 1 will increase image brightness or
    00893     contrast respectively, values smaller than 1 decrease them.  A
    00894     value of exactly 1 will have no effect.  If contrast is set to 1,
    00895     the result is equivalent to that of the GammaFunctor with gamma =
    00896     1./brightness.
    00897
    00898     For \ref RGBValue "RGBValue's", the transforms are applied
    00899     component-wise. The pixel values are assumed to lie between the
    00900     given minimum and maximum values (in case of RGB, this is again
    00901     understood component-wise). In case of <TT>unsigned char</TT>, min
    00902     and max default to 0 and 255 respectively.  Precisely, the
    00903     following transform is applied to each <em> PixelValue</em>:
    00904
    00905     \f[
    00906     \begin{array}{rcl}
    00907     V_1 & = & \frac{PixelValue - min}{max - min} \\
    00908     V_2 & = & V_1^\frac{1}{brightness} \\
    00909     V_3 & = & 2 V_2 - 1 \\
    00910     V_4 & = & \left\lbrace
    00911         \begin{array}{l}
    00912          V_3^\frac{1}{contrast} \mbox{\rm \quad if  } V_3 \ge 0 \\
    00913          - (-V_3)^\frac{1}{contrast} \mbox{\rm \quad otherwise}
    00914         \end{array} \right. \\
    00915     Result & = & \frac{V_4 + 1}{2} (max - min) + min
    00916     \end{array}
    00917     \f]
    00918
    00919     If the <TT>PixelType</TT> is <TT>unsigned char</TT>, a look-up-table is used
    00920     for faster computation.
    00921
    00922     <b> Traits defined:</b>
    00923
    00924     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
    00925
    00926     <b> Usage:</b>
    00927
    00928         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
    00929         Namespace: vigra
    00930
    00931     \code
    00932     vigra::BImage bimage(width, height);
    00933     double brightness, contrast;
    00934     ...
    00935     vigra::transformImage(srcImageRange(bimage), destImage(bimage),
    00936        vigra::BrightnessContrastFunctor<unsigned char>(brightness, contrast));
    00937
    00938
    00939
    00940     vigra::FImage fimage(width, height);
    00941     ...
    00942
    00943     vigra::FindMinmax<float> minmax;
    00944     vigra::inspectImage(srcImageRange(fimage), minmax);
    00945
    00946     vigra::transformImage(srcImageRange(fimage), destImage(fimage),
    00947        vigra::BrightnessContrastFunctor<float>(brightness, contrast, minmax.min, minmax.max));
    00948
    00949
    00950     \endcode
    00951
    00952     <b> Required Interface:</b>
    00953
    00954     Scalar types: must be a linear algebra (+, - *, NumericTraits),
    00955     strict weakly ordered (<), and <TT>pow()</TT> must be defined.
    00956
    00957     RGB values: the component type must meet the above requirements.
    00958 */
    00959 template <class PixelType>
    00960 class BrightnessContrastFunctor
    00961 {
    00962     typedef typename
    00963         NumericTraits<PixelType>::RealPromote promote_type;
    00964
    00965  public:
    00966
    00967         /** the functor's argument type
    00968         */
    00969     typedef PixelType argument_type;
    00970
    00971         /** the functor's result type
    00972         */
    00973     typedef PixelType result_type;
    00974
    00975         /** \deprecated use argument_type and result_type
    00976         */
    00977     typedef PixelType value_type;
    00978
    00979         /** Init functor for argument range <TT>[min, max]</TT>.
    00980             <TT>brightness</TT> and <TT>contrast</TT> values > 1 will
    00981             increase brightness and contrast, < 1 will decrease them, and == 1 means
    00982             no change.
    00983         */
    00984     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
    00985                               argument_type const & min, argument_type const & max)
    00986     : b_(1.0/brightness),
    00987       c_(1.0/contrast),
    00988       min_(min),
    00989       diff_(max - min),
    00990       zero_(NumericTraits<promote_type>::zero()),
    00991       one_(NumericTraits<promote_type>::one())
    00992     {}
    00993
    00994         /** Calculate modified gray or color value
    00995         */
    00996     result_type operator()(argument_type const & v) const
    00997     {
    00998         promote_type v1 = (v - min_) / diff_;
    00999         promote_type brighter = VIGRA_CSTD::pow(v1, b_);
    01000         promote_type v2 = 2.0 * brighter - one_;
    01001         promote_type contrasted = (v2 < zero_) ?
    01002                                      -VIGRA_CSTD::pow(-v2, c_) :
    01003                                       VIGRA_CSTD::pow(v2, c_);
    01004         return result_type(0.5 * diff_ * (contrasted + one_) + min_);
    01005     }
    01006
    01007   private:
    01008     promote_type b_, c_;
    01009     argument_type min_;
    01010     promote_type diff_, zero_, one_;
    01011 };
    01012
    01013 template <>
    01014 class BrightnessContrastFunctor<unsigned char>
    01015 {
    01016     typedef NumericTraits<unsigned char>::RealPromote promote_type;
    01017      unsigned char lut[256];
    01018
    01019  public:
    01020
    01021     typedef unsigned char value_type;
    01022
    01023     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
    01024                               value_type const & min = 0, value_type const & max = 255)
    01025     {
    01026         BrightnessContrastFunctor<promote_type> f(brightness, contrast, min, max);
    01027
    01028         for(int i = min; i <= max; ++i)
    01029         {
    01030             lut[i] = static_cast<unsigned char>(f(i)+0.5);
    01031         }
    01032     }
    01033
    01034     value_type operator()(value_type const & v) const
    01035     {
    01036
    01037         return lut[v];
    01038     }
    01039 };
    01040
    01041 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
    01042
    01043 template <class ComponentType>
    01044 class BrightnessContrastFunctor<RGBValue<ComponentType> >
    01045 {
    01046     typedef typename
    01047         NumericTraits<ComponentType>::RealPromote promote_type;
    01048     BrightnessContrastFunctor<ComponentType> red, green, blue;
    01049
    01050  public:
    01051
    01052     typedef RGBValue<ComponentType> value_type;
    01053
    01054     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
    01055                               value_type const & min, value_type const & max)
    01056     : red(brightness, contrast, min.red(), max.red()),
    01057       green(brightness, contrast, min.green(), max.green()),
    01058       blue(brightness, contrast, min.blue(), max.blue())
    01059     {}
    01060
    01061     value_type operator()(value_type const & v) const
    01062     {
    01063
    01064         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
    01065     }
    01066 };
    01067
    01068 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
    01069
    01070 template <>
    01071 class BrightnessContrastFunctor<RGBValue<int> >
    01072 {
    01073     typedef NumericTraits<int>::RealPromote promote_type;
    01074     BrightnessContrastFunctor<int> red, green, blue;
    01075
    01076  public:
    01077
    01078     typedef RGBValue<int> value_type;
    01079
    01080     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
    01081                               value_type const & min, value_type const & max)
    01082     : red(brightness, contrast, min.red(), max.red()),
    01083       green(brightness, contrast, min.green(), max.green()),
    01084       blue(brightness, contrast, min.blue(), max.blue())
    01085     {}
    01086
    01087     value_type operator()(value_type const & v) const
    01088     {
    01089
    01090         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
    01091     }
    01092 };
    01093
    01094 template <>
    01095 class BrightnessContrastFunctor<RGBValue<float> >
    01096 {
    01097     typedef NumericTraits<float>::RealPromote promote_type;
    01098     BrightnessContrastFunctor<float> red, green, blue;
    01099
    01100  public:
    01101
    01102     typedef RGBValue<float> value_type;
    01103
    01104     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
    01105                               value_type const & min, value_type const & max)
    01106     : red(brightness, contrast, min.red(), max.red()),
    01107       green(brightness, contrast, min.green(), max.green()),
    01108       blue(brightness, contrast, min.blue(), max.blue())
    01109     {}
    01110
    01111     value_type operator()(value_type const & v) const
    01112     {
    01113
    01114         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
    01115     }
    01116 };
    01117
    01118 template <class PixelType>
    01119 class FunctorTraits<BrightnessContrastFunctor<PixelType> >
    01120 : public FunctorTraitsBase<BrightnessContrastFunctor<PixelType> >
    01121 {
    01122   public:
    01123     typedef VigraTrueType isUnaryFunctor;
    01124 };
    01125
    01126 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
    01127
    01128 template <>
    01129 class BrightnessContrastFunctor<RGBValue<unsigned char> >
    01130 {
    01131     typedef NumericTraits<unsigned char>::RealPromote promote_type;
    01132     BrightnessContrastFunctor<unsigned char> red, green, blue;
    01133
    01134  public:
    01135
    01136     typedef RGBValue<unsigned char> value_type;
    01137
    01138     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
    01139        value_type const & min = value_type(0,0,0),
    01140        value_type const & max = value_type(255, 255, 255))
    01141     : red(brightness, contrast, min.red(), max.red()),
    01142       green(brightness, contrast, min.green(), max.green()),
    01143       blue(brightness, contrast, min.blue(), max.blue())
    01144     {}
    01145
    01146     value_type operator()(value_type const & v) const
    01147     {
    01148
    01149         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
    01150     }
    01151 };
    01152
    01153
    01154
    01155 /********************************************************/
    01156 /*                                                      */
    01157 /*                     GammaFunctor                     */
    01158 /*                                                      */
    01159 /********************************************************/
    01160
    01161 /** \brief Perform gamma correction of an image.
    01162
    01163     This functor applies a gamma correction to each pixel in order to
    01164     modify the brightness of the image.  Gamma values smaller than 1
    01165     will increase image brightness, whereas values greater than 1
    01166     decrease it. A value of gamma = 1 will have no effect.  (See also
    01167     BrightnessContrastFunctor, which additionally changes the
    01168     contrast.)
    01169
    01170     For \ref RGBValue "RGBValue's", the transforms are applied
    01171     component-wise.  For ease of use, the pixel values are assumed to
    01172     lie between the given minimum and maximum values (in case of RGB,
    01173     this is again understood component-wise). In case of <TT>unsigned
    01174     char</TT>, min and max default to 0 and 255 respectively.
    01175     Precisely, the following transform is applied to each <em>
    01176     PixelValue</em>:
    01177
    01178     \f[
    01179     \begin{array}{rcl}
    01180     V_1 & = & \frac{PixelValue - min}{max - min} \\
    01181     V_2 & = & V_1^{gamma} \\
    01182     Result & = & V_2 (max - min) + min
    01183     \end{array}
    01184     \f]
    01185
    01186     If the <TT>PixelType</TT> is <TT>unsigned char</TT>, a
    01187     look-up-table is used for faster computation.
    01188
    01189     <b> Traits defined:</b>
    01190
    01191     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
    01192
    01193     <b> Usage:</b>
    01194
    01195         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
    01196         Namespace: vigra
    01197
    01198     \code
    01199     vigra::BImage bimage(width, height);
    01200     double gamma;
    01201     ...
    01202     vigra::transformImage(srcImageRange(bimage), destImage(bimage),
    01203        vigra::GammaFunctor<unsigned char>(gamma));
    01204
    01205
    01206
    01207     vigra::FImage fimage(width, height);
    01208     ...
    01209
    01210     vigra::FindMinmax<float> minmax;
    01211     vigra::inspectImage(srcImageRange(fimage), minmax);
    01212
    01213     vigra::transformImage(srcImageRange(fimage), destImage(fimage),
    01214        vigra::GammaFunctor<float>(gamma, minmax.min, minmax.max));
    01215
    01216     \endcode
    01217
    01218     <b> Required Interface:</b>
    01219
    01220     Scalar types: must be a linear algebra (+, - *, NumericTraits),
    01221     strict weakly ordered (<), and <TT>pow()</TT> must be defined.
    01222
    01223     RGB values: the component type must meet the above requirements.
    01224 */
    01225 template <class PixelType>
    01226 class GammaFunctor
    01227 {
    01228     typedef typename
    01229         NumericTraits<PixelType>::RealPromote promote_type;
    01230
    01231  public:
    01232
    01233         /** the functor's argument type
    01234         */
    01235     typedef PixelType argument_type;
    01236
    01237         /** the functor's result type
    01238         */
    01239     typedef PixelType result_type;
    01240
    01241         /** \deprecated use argument_type and result_type
    01242         */
    01243     typedef PixelType value_type;
    01244
    01245         /** Init functor for argument range <TT>[min, max]</TT>.
    01246             <TT>gamma</TT> values < 1 will increase brightness, > 1
    01247             will decrease it (gamma == 1 means no change).
    01248         */
    01249     GammaFunctor(promote_type gamma,
    01250                  argument_type const & min, argument_type const & max)
    01251     : gamma_(gamma),
    01252       min_(min),
    01253       diff_(max - min),
    01254       zero_(NumericTraits<promote_type>::zero()),
    01255       one_(NumericTraits<promote_type>::one())
    01256     {}
    01257
    01258         /** Calculate modified gray or color value
    01259         */
    01260     result_type operator()(argument_type const & v) const
    01261     {
    01262         promote_type v1 = (v - min_) / diff_;
    01263         promote_type brighter = VIGRA_CSTD::pow(v1, gamma_);
    01264         return result_type(diff_ * brighter + min_);
    01265     }
    01266
    01267   private:
    01268     promote_type gamma_;
    01269     argument_type min_;
    01270     promote_type diff_, zero_, one_;
    01271 };
    01272
    01273 template <>
    01274 class GammaFunctor<unsigned char>
    01275 {
    01276     typedef NumericTraits<unsigned char>::RealPromote promote_type;
    01277      unsigned char lut[256];
    01278
    01279  public:
    01280
    01281     typedef unsigned char value_type;
    01282
    01283     GammaFunctor(promote_type gamma,
    01284                  value_type const & min = 0, value_type const & max = 255)
    01285     {
    01286         GammaFunctor<promote_type> f(gamma, min, max);
    01287
    01288         for(int i = min; i <= max; ++i)
    01289         {
    01290             lut[i] = static_cast<unsigned char>(f(i)+0.5);
    01291         }
    01292     }
    01293
    01294     value_type operator()(value_type const & v) const
    01295     {
    01296
    01297         return lut[v];
    01298     }
    01299 };
    01300
    01301 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
    01302
    01303 template <class ComponentType>
    01304 class GammaFunctor<RGBValue<ComponentType> >
    01305 {
    01306     typedef typename
    01307         NumericTraits<ComponentType>::RealPromote promote_type;
    01308     GammaFunctor<ComponentType> red, green, blue;
    01309
    01310  public:
    01311
    01312     typedef RGBValue<ComponentType> value_type;
    01313
    01314     GammaFunctor(promote_type gamma,
    01315                  value_type const & min, value_type const & max)
    01316     : red(gamma, min.red(), max.red()),
    01317       green(gamma, min.green(), max.green()),
    01318       blue(gamma, min.blue(), max.blue())
    01319     {}
    01320
    01321     value_type operator()(value_type const & v) const
    01322     {
    01323         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
    01324     }
    01325 };
    01326
    01327 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
    01328
    01329 template <>
    01330 class GammaFunctor<RGBValue<int> >
    01331 {
    01332     typedef NumericTraits<int>::RealPromote promote_type;
    01333     GammaFunctor<int> red, green, blue;
    01334
    01335  public:
    01336
    01337     typedef RGBValue<int> value_type;
    01338
    01339     GammaFunctor(promote_type gamma,
    01340                  value_type const & min, value_type const & max)
    01341     : red(gamma, min.red(), max.red()),
    01342       green(gamma, min.green(), max.green()),
    01343       blue(gamma, min.blue(), max.blue())
    01344     {}
    01345
    01346     value_type operator()(value_type const & v) const
    01347     {
    01348         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
    01349     }
    01350 };
    01351
    01352 template <>
    01353 class GammaFunctor<RGBValue<float> >
    01354 {
    01355     typedef NumericTraits<float>::RealPromote promote_type;
    01356     GammaFunctor<float> red, green, blue;
    01357
    01358  public:
    01359
    01360     typedef RGBValue<float> value_type;
    01361
    01362     GammaFunctor(promote_type gamma,
    01363                  value_type const & min, value_type const & max)
    01364     : red(gamma, min.red(), max.red()),
    01365       green(gamma, min.green(), max.green()),
    01366       blue(gamma, min.blue(), max.blue())
    01367     {}
    01368
    01369     value_type operator()(value_type const & v) const
    01370     {
    01371         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
    01372     }
    01373 };
    01374
    01375 template <class PixelType>
    01376 class FunctorTraits<GammaFunctor<PixelType> >
    01377 : public FunctorTraitsBase<GammaFunctor<PixelType> >
    01378 {
    01379   public:
    01380     typedef VigraTrueType isUnaryFunctor;
    01381 };
    01382
    01383 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
    01384
    01385 template <>
    01386 class GammaFunctor<RGBValue<unsigned char> >
    01387 {
    01388     typedef NumericTraits<unsigned char>::RealPromote promote_type;
    01389     GammaFunctor<unsigned char> red, green, blue;
    01390
    01391  public:
    01392     typedef RGBValue<unsigned char> value_type;
    01393
    01394     GammaFunctor(promote_type gamma,
    01395                  value_type const & min = value_type(0,0,0),
    01396                  value_type const & max = value_type(255, 255, 255))
    01397     : red(gamma, min.red(), max.red()),
    01398       green(gamma, min.green(), max.green()),
    01399       blue(gamma, min.blue(), max.blue())
    01400     {}
    01401
    01402     value_type operator()(value_type const & v) const
    01403     {
    01404         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
    01405     }
    01406 };
    01407
    01408
    01409 /********************************************************/
    01410 /*                                                      */
    01411 /*                     VectorNormFunctor                */
    01412 /*                                                      */
    01413 /********************************************************/
    01414
    01415 /** \brief A functor for computing the vector norm
    01416
    01417     Calculate the magnitude or norm from a given vector-valued
    01418     entity. The vector type will typically be some sort of
    01419     ref vigra::TinyVector. If the vector is represented by a pair of
    01420     scalar-valued images, use \ref vigra::MagnitudeFunctor instead.
    01421
    01422     At least, the vector type is required to have a function
    01423     '<em>result</em><TT> = dot(v,v)</TT>'.
    01424
    01425     <b> Traits defined:</b>
    01426
    01427     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
    01428
    01429     <b> Usage:</b>
    01430
    01431         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
    01432         Namespace: vigra
    01433
    01434     \code
    01435     typedef vigra::TinyVector<float, 2> Vector;
    01436     vigra::BasicImage<Vector> grad(width, height);
    01437     vigra::FImage magn(width,height);
    01438     ...
    01439     vigra::transformImage(srcImageRange(grad), destImage(magn),
    01440                           VectorNormFunctor<float>()
    01441                           );
    01442     \endcode
    01443
    01444     \see vigra::TinyVector, dot(), vigra::MagnitudeFunctor
    01445 */
    01446 template <class ValueType>
    01447 class VectorNormFunctor
    01448 {
    01449 public:
    01450   /** the functor's argument type
    01451    */
    01452   typedef ValueType argument_type;
    01453
    01454   /** the functor's result type
    01455    */
    01456   typedef typename NumericTraits<typename ValueType::value_type>::RealPromote result_type;
    01457
    01458   /** calculate transform '<TT>sqrt(v1*v1 + v2*v2 + ...)</TT>'.
    01459    */
    01460   result_type operator()( const argument_type &a ) const
    01461   {
    01462     return VIGRA_CSTD::sqrt( dot(a,a) );
    01463   }
    01464 };    //-- class VectorNormFunctor
    01465
    01466 template <class ValueType>
    01467 class FunctorTraits<VectorNormFunctor<ValueType> >
    01468 : public FunctorTraitsBase<VectorNormFunctor<ValueType> >
    01469 {
    01470   public:
    01471     typedef VigraTrueType isUnaryFunctor;
    01472 };
    01473
    01474 /** \brief A functor for computing the squared vector norm
    01475
    01476     Calculate the squared magnitude or norm from a given
    01477     vector-valued entity. The vector type will typically be some
    01478     sort of TinyVector.
    01479
    01480     At least, the vector type is required to have a function
    01481     '<em>result</em><TT> = dot(v,v)</TT>'.
    01482
    01483     For an example of its usage see VectorNormFunctor
    01484
    01485     <b> Traits defined:</b>
    01486
    01487     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
    01488
    01489     \see TinyVector, dot()
    01490 */
    01491 template <class ValueType>
    01492 class VectorNormSqFunctor
    01493 {
    01494 public:
    01495   /** the functor's argument type
    01496    */
    01497   typedef ValueType argument_type;
    01498
    01499   /** the functor's result type
    01500    */
    01501   typedef typename NumericTraits<typename ValueType::value_type>::RealPromote result_type;
    01502
    01503   /** calculate transform '<TT>v1*v1 + v2*v2 + ...</TT>'.
    01504    */
    01505   result_type operator()( const argument_type &a ) const
    01506   {
    01507     return dot(a,a);
    01508   }
    01509 };    //-- class VectorNormSqFunctor
    01510
    01511 template <class ValueType>
    01512 class FunctorTraits<VectorNormSqFunctor<ValueType> >
    01513 : public FunctorTraitsBase<VectorNormSqFunctor<ValueType> >
    01514 {
    01515   public:
    01516     typedef VigraTrueType isUnaryFunctor;
    01517 };
    01518
    01519 //@}
    01520
    01521 } // namespace vigra
    01522
    01523 #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.6.0 (13 Aug 2008)