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