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

vigra/transformimage.hxx VIGRA

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)