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

vigra/transformimage.hxx |

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