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

vigra/transformimage.hxx

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    The VIGRA Website is                                              */
00008 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00009 /*    Please direct questions, bug reports, and contributions to        */
00010 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00011 /*        vigra@informatik.uni-hamburg.de                               */
00012 /*                                                                      */
00013 /*    Permission is hereby granted, free of charge, to any person       */
00014 /*    obtaining a copy of this software and associated documentation    */
00015 /*    files (the "Software"), to deal in the Software without           */
00016 /*    restriction, including without limitation the rights to use,      */
00017 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00018 /*    sell copies of the Software, and to permit persons to whom the    */
00019 /*    Software is furnished to do so, subject to the following          */
00020 /*    conditions:                                                       */
00021 /*                                                                      */
00022 /*    The above copyright notice and this permission notice shall be    */
00023 /*    included in all copies or substantial portions of the             */
00024 /*    Software.                                                         */
00025 /*                                                                      */
00026 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00027 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00028 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00029 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00030 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00031 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00032 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00033 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
00034 /*                                                                      */
00035 /************************************************************************/
00036 
00037 
00038 #ifndef VIGRA_TRANSFORMIMAGE_HXX
00039 #define VIGRA_TRANSFORMIMAGE_HXX
00040 
00041 #include "utilities.hxx"
00042 #include "numerictraits.hxx"
00043 #include "iteratortraits.hxx"
00044 #include "rgbvalue.hxx"
00045 #include "functortraits.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> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><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 vlaue 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> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><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> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>>
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     typename NumericTraits<typename SrcAccessor::value_type>::RealPromote
00423              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)) / 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)) / 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)) / 2.0;
00458             diffy = (sa(sx, top) - sa(sx, bottom)) / 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)) / 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)) / 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> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><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.
00709 
00710     <b> Declaration:</b>
00711 
00712     \code
00713     namespace vigra {
00714         template <class SrcValueType, class DestValueType>
00715         LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00716         linearRangeMapping(SrcValueType src_min, SrcValueType src_max,
00717                            DestValueType dest_min, DestValueType dest_max );
00718     }
00719     \endcode
00720 
00721     <b> Usage:</b>
00722 
00723         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
00724         Namespace: vigra
00725 
00726     \code
00727     vigra::IImage src(width, height);
00728     vigra::BImage dest(width, height);
00729     ...
00730     vigra::FindMinMax<IImage::PixelType> minmax;   // functor to find range
00731 
00732     vigra::inspectImage(srcImageRange(src), minmax); // find original range
00733 
00734     // transform to range 0...255
00735     vigra::transformImage(srcImageRange(src), destImage(dest),
00736                           linearRangeTransform(
00737                             minmax.min, minmax.max,               // src range
00738                             (unsigned char)0, (unsigned char)255) // dest range
00739                           );
00740     \endcode
00741 
00742     <b> Required Interface:</b>
00743 
00744     The source and destination value types must be models of \ref LinearSpace in both cases.
00745 
00746 */
00747 template <class SrcValueType, class DestValueType>
00748 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00749 linearRangeMapping(SrcValueType src_min, SrcValueType src_max,
00750                    DestValueType dest_min, DestValueType dest_max )
00751 {
00752     return linearRangeMapping(src_min, src_max, dest_min, dest_max,
00753             typename NumericTraits<DestValueType>::isScalar());
00754 }
00755 
00756 template <class SrcValueType, class DestValueType>
00757 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00758 linearRangeMapping(
00759     SrcValueType src_min, SrcValueType src_max,
00760     DestValueType dest_min, DestValueType dest_max,
00761     VigraTrueType /* isScalar */ )
00762 {
00763     typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
00764     Multiplier diff = src_max - src_min;
00765     Multiplier scale = diff == NumericTraits<Multiplier>::zero()
00766                      ? NumericTraits<Multiplier>::one()
00767                      : (dest_max - dest_min) / diff;
00768     return LinearIntensityTransform<DestValueType, Multiplier>(
00769                                    scale, dest_min / scale - src_min );
00770 }
00771 
00772 template <class SrcValueType, class DestValueType>
00773 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00774 linearRangeMapping(
00775     SrcValueType src_min, SrcValueType src_max,
00776     DestValueType dest_min, DestValueType dest_max,
00777     VigraFalseType /* isScalar */ )
00778 {
00779     typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
00780     typedef typename Multiplier::value_type MComponent;
00781     Multiplier scale(dest_max), offset(dest_max);
00782     for(unsigned int i=0; i<src_min.size(); ++i)
00783     {
00784         MComponent diff = src_max[i] - src_min[i];
00785         scale[i] = diff == NumericTraits<MComponent>::zero()
00786                      ? NumericTraits<MComponent>::one()
00787                      : (dest_max[i] - dest_min[i]) / diff;
00788         offset[i] = dest_min[i] / scale[i] - src_min[i];
00789     }
00790     return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
00791 }
00792 
00793 /********************************************************/
00794 /*                                                      */
00795 /*                      Threshold                       */
00796 /*                                                      */
00797 /********************************************************/
00798 
00799 /** \brief Threshold an image.
00800 
00801     If a source pixel is above or equal the lower and below
00802     or equal the higher threshold (i.e. within the closed interval
00803     [lower, heigher]) the destination pixel is set to 'yesresult',
00804     otherwise to 'noresult'.
00805 
00806     <b> Traits defined:</b>
00807 
00808     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
00809 
00810     <b> Usage:</b>
00811 
00812         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
00813         Namespace: vigra
00814 
00815     \code
00816     vigra::BImage src(width, height), dest(width, height);
00817     ...
00818     vigra::transformImage(src.upperLeft(), src.lowerRight(), src.accessor(),
00819        dest.upperLeft(), dest.accessor(),
00820        vigra::Threshold<
00821           vigra::BImage::PixelType, vigra::BImage::PixelType>(10, 100, 0, 255));
00822 
00823     \endcode
00824 
00825     <b> Required Interface:</b>
00826 
00827     \code
00828 
00829     SrcValueType   src;
00830     DestValueType  dest, yesresult, noresult;
00831 
00832     dest = ((src < lower) || (higher < src)) ? noresult : yesresult;
00833 
00834     \endcode
00835 
00836 */
00837 template <class SrcValueType, class DestValueType>
00838 class Threshold
00839 {
00840    public:
00841 
00842         /** the functor's argument type
00843         */
00844     typedef SrcValueType argument_type;
00845 
00846         /** the functor's result type
00847         */
00848     typedef DestValueType result_type;
00849 
00850         /** init thresholds and return values
00851         */
00852     Threshold(argument_type lower, argument_type higher,
00853               result_type noresult, result_type yesresult)
00854     : lower_(lower), higher_(higher),
00855       yesresult_(yesresult), noresult_(noresult)
00856     {}
00857 
00858         /** calculate transform
00859         */
00860     result_type operator()(argument_type s) const
00861     {
00862         return ((s < lower_) || (higher_ < s)) ? noresult_ : yesresult_;
00863     }
00864 
00865   private:
00866 
00867     argument_type lower_, higher_;
00868     result_type yesresult_, noresult_;
00869 };
00870 
00871 template <class SrcValueType, class DestValueType>
00872 class FunctorTraits<Threshold<SrcValueType, DestValueType> >
00873 : public FunctorTraitsBase<Threshold<SrcValueType, DestValueType> >
00874 {
00875   public:
00876     typedef VigraTrueType isUnaryFunctor;
00877 };
00878 
00879 /********************************************************/
00880 /*                                                      */
00881 /*                BrightnessContrastFunctor             */
00882 /*                                                      */
00883 /********************************************************/
00884 
00885 /** \brief Adjust brightness and contrast of an image.
00886 
00887     This functor applies a gamma correction to each pixel in order to
00888     modify the brightness of the image. To the result of the gamma
00889     correction, another transform is applied that modifies the
00890     contrast. The brightness and contrast parameters must be
00891     positive. Values greater than 1 will increase image brightness or
00892     contrast respectively, values smaller than 1 decrease them.  A
00893     value of exactly 1 will have no effect.  If contrast is set to 1,
00894     the result is equivalent to that of the GammaFunctor with gamma =
00895     1./brightness.
00896 
00897     For \ref RGBValue "RGBValue's", the transforms are applied
00898     component-wise. The pixel values are assumed to lie between the
00899     given minimum and maximum values (in case of RGB, this is again
00900     understood component-wise). In case of <TT>unsigned char</TT>, min
00901     and max default to 0 and 255 respectively.  Precisely, the
00902     following transform is applied to each <em> PixelValue</em>:
00903 
00904     \f[
00905     \begin{array}{rcl}
00906     V_1 & = & \frac{PixelValue - min}{max - min} \\
00907     V_2 & = & V_1^\frac{1}{brightness} \\
00908     V_3 & = & 2 V_2 - 1 \\
00909     V_4 & = & \left\lbrace
00910         \begin{array}{l}
00911          V_3^\frac{1}{contrast} \mbox{\rm \quad if  } V_3 \ge 0 \\
00912          - (-V_3)^\frac{1}{contrast} \mbox{\rm \quad otherwise}
00913         \end{array} \right. \\
00914     Result & = & \frac{V_4 + 1}{2} (max - min) + min
00915     \end{array}
00916     \f]
00917 
00918     If the <TT>PixelType</TT> is <TT>unsigned char</TT>, a look-up-table is used
00919     for faster computation.
00920 
00921     <b> Traits defined:</b>
00922 
00923     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
00924 
00925     <b> Usage:</b>
00926 
00927         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
00928         Namespace: vigra
00929 
00930     \code
00931     vigra::BImage bimage(width, height);
00932     double brightness, contrast;
00933     ...
00934     vigra::transformImage(srcImageRange(bimage), destImage(bimage),
00935        vigra::BrightnessContrastFunctor<unsigned char>(brightness, contrast));
00936 
00937 
00938 
00939     vigra::FImage fimage(width, height);
00940     ...
00941 
00942     vigra::FindMinmax<float> minmax;
00943     vigra::inspectImage(srcImageRange(fimage), minmax);
00944 
00945     vigra::transformImage(srcImageRange(fimage), destImage(fimage),
00946        vigra::BrightnessContrastFunctor<float>(brightness, contrast, minmax.min, minmax.max));
00947 
00948 
00949     \endcode
00950 
00951     <b> Required Interface:</b>
00952 
00953     Scalar types: must be a linear algebra (+, - *, NumericTraits),
00954     strict weakly ordered (<), and <TT>pow()</TT> must be defined.
00955 
00956     RGB values: the component type must meet the above requirements.
00957 */
00958 template <class PixelType>
00959 class BrightnessContrastFunctor
00960 {
00961     typedef typename
00962         NumericTraits<PixelType>::RealPromote promote_type;
00963 
00964  public:
00965 
00966         /** the functor's argument type
00967         */
00968     typedef PixelType argument_type;
00969 
00970         /** the functor's result type
00971         */
00972     typedef PixelType result_type;
00973 
00974         /** \deprecated use argument_type and result_type
00975         */
00976     typedef PixelType value_type;
00977 
00978         /** Init functor for argument range <TT>[min, max]</TT>.
00979             <TT>brightness</TT> and <TT>contrast</TT> values > 1 will
00980             increase brightness and contrast, < 1 will decrease them, and == 1 means
00981             no change.
00982         */
00983     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
00984                               argument_type const & min, argument_type const & max)
00985     : b_(1.0/brightness),
00986       c_(1.0/contrast),
00987       min_(min),
00988       diff_(max - min),
00989       zero_(NumericTraits<promote_type>::zero()),
00990       one_(NumericTraits<promote_type>::one())
00991     {}
00992 
00993         /** Calculate modified gray or color value
00994         */
00995     result_type operator()(argument_type const & v) const
00996     {
00997         promote_type v1 = (v - min_) / diff_;
00998         promote_type brighter = VIGRA_CSTD::pow(v1, b_);
00999         promote_type v2 = 2.0 * brighter - one_;
01000         promote_type contrasted = (v2 < zero_) ?
01001                                      -VIGRA_CSTD::pow(-v2, c_) :
01002                                       VIGRA_CSTD::pow(v2, c_);
01003         return result_type(0.5 * diff_ * (contrasted + one_) + min_);
01004     }
01005 
01006   private:
01007     promote_type b_, c_;
01008     argument_type min_;
01009     promote_type diff_, zero_, one_;
01010 };
01011 
01012 template <>
01013 class BrightnessContrastFunctor<unsigned char>
01014 {
01015     typedef NumericTraits<unsigned char>::RealPromote promote_type;
01016      unsigned char lut[256];
01017 
01018  public:
01019 
01020     typedef unsigned char value_type;
01021 
01022     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01023                               value_type const & min = 0, value_type const & max = 255)
01024     {
01025         BrightnessContrastFunctor<promote_type> f(brightness, contrast, min, max);
01026 
01027         for(int i = min; i <= max; ++i)
01028         {
01029             lut[i] = static_cast<unsigned char>(f(i)+0.5);
01030         }
01031     }
01032 
01033     value_type operator()(value_type const & v) const
01034     {
01035 
01036         return lut[v];
01037     }
01038 };
01039 
01040 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
01041 
01042 template <class ComponentType>
01043 class BrightnessContrastFunctor<RGBValue<ComponentType> >
01044 {
01045     typedef typename
01046         NumericTraits<ComponentType>::RealPromote promote_type;
01047     BrightnessContrastFunctor<ComponentType> red, green, blue;
01048 
01049  public:
01050 
01051     typedef RGBValue<ComponentType> value_type;
01052 
01053     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01054                               value_type const & min, value_type const & max)
01055     : red(brightness, contrast, min.red(), max.red()),
01056       green(brightness, contrast, min.green(), max.green()),
01057       blue(brightness, contrast, min.blue(), max.blue())
01058     {}
01059 
01060     value_type operator()(value_type const & v) const
01061     {
01062 
01063         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01064     }
01065 };
01066 
01067 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01068 
01069 template <>
01070 class BrightnessContrastFunctor<RGBValue<int> >
01071 {
01072     typedef NumericTraits<int>::RealPromote promote_type;
01073     BrightnessContrastFunctor<int> red, green, blue;
01074 
01075  public:
01076 
01077     typedef RGBValue<int> value_type;
01078 
01079     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01080                               value_type const & min, value_type const & max)
01081     : red(brightness, contrast, min.red(), max.red()),
01082       green(brightness, contrast, min.green(), max.green()),
01083       blue(brightness, contrast, min.blue(), max.blue())
01084     {}
01085 
01086     value_type operator()(value_type const & v) const
01087     {
01088 
01089         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01090     }
01091 };
01092 
01093 template <>
01094 class BrightnessContrastFunctor<RGBValue<float> >
01095 {
01096     typedef NumericTraits<float>::RealPromote promote_type;
01097     BrightnessContrastFunctor<float> red, green, blue;
01098 
01099  public:
01100 
01101     typedef RGBValue<float> value_type;
01102 
01103     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01104                               value_type const & min, value_type const & max)
01105     : red(brightness, contrast, min.red(), max.red()),
01106       green(brightness, contrast, min.green(), max.green()),
01107       blue(brightness, contrast, min.blue(), max.blue())
01108     {}
01109 
01110     value_type operator()(value_type const & v) const
01111     {
01112 
01113         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01114     }
01115 };
01116 
01117 template <class PixelType>
01118 class FunctorTraits<BrightnessContrastFunctor<PixelType> >
01119 : public FunctorTraitsBase<BrightnessContrastFunctor<PixelType> >
01120 {
01121   public:
01122     typedef VigraTrueType isUnaryFunctor;
01123 };
01124 
01125 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01126 
01127 template <>
01128 class BrightnessContrastFunctor<RGBValue<unsigned char> >
01129 {
01130     typedef NumericTraits<unsigned char>::RealPromote promote_type;
01131     BrightnessContrastFunctor<unsigned char> red, green, blue;
01132 
01133  public:
01134 
01135     typedef RGBValue<unsigned char> value_type;
01136 
01137     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01138        value_type const & min = value_type(0,0,0),
01139        value_type const & max = value_type(255, 255, 255))
01140     : red(brightness, contrast, min.red(), max.red()),
01141       green(brightness, contrast, min.green(), max.green()),
01142       blue(brightness, contrast, min.blue(), max.blue())
01143     {}
01144 
01145     value_type operator()(value_type const & v) const
01146     {
01147 
01148         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01149     }
01150 };
01151 
01152 
01153 
01154 /********************************************************/
01155 /*                                                      */
01156 /*                     GammaFunctor                     */
01157 /*                                                      */
01158 /********************************************************/
01159 
01160 /** \brief Perform gamma correction of an image.
01161 
01162     This functor applies a gamma correction to each pixel in order to
01163     modify the brightness of the image.  Gamma values smaller than 1
01164     will increase image brightness, whereas values greater than 1
01165     decrease it. A value of gamma = 1 will have no effect.  (See also
01166     BrightnessContrastFunctor, which additionally changes the
01167     contrast.)
01168 
01169     For \ref RGBValue "RGBValue's", the transforms are applied
01170     component-wise.  For ease of use, the pixel values are assumed to
01171     lie between the given minimum and maximum values (in case of RGB,
01172     this is again understood component-wise). In case of <TT>unsigned
01173     char</TT>, min and max default to 0 and 255 respectively.
01174     Precisely, the following transform is applied to each <em>
01175     PixelValue</em>:
01176 
01177     \f[
01178     \begin{array}{rcl}
01179     V_1 & = & \frac{PixelValue - min}{max - min} \\
01180     V_2 & = & V_1^{gamma} \\
01181     Result & = & V_2 (max - min) + min
01182     \end{array}
01183     \f]
01184 
01185     If the <TT>PixelType</TT> is <TT>unsigned char</TT>, a
01186     look-up-table is used for faster computation.
01187 
01188     <b> Traits defined:</b>
01189 
01190     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
01191 
01192     <b> Usage:</b>
01193 
01194         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
01195         Namespace: vigra
01196 
01197     \code
01198     vigra::BImage bimage(width, height);
01199     double gamma;
01200     ...
01201     vigra::transformImage(srcImageRange(bimage), destImage(bimage),
01202        vigra::GammaFunctor<unsigned char>(gamma));
01203 
01204 
01205 
01206     vigra::FImage fimage(width, height);
01207     ...
01208 
01209     vigra::FindMinmax<float> minmax;
01210     vigra::inspectImage(srcImageRange(fimage), minmax);
01211 
01212     vigra::transformImage(srcImageRange(fimage), destImage(fimage),
01213        vigra::GammaFunctor<float>(gamma, minmax.min, minmax.max));
01214 
01215     \endcode
01216 
01217     <b> Required Interface:</b>
01218 
01219     Scalar types: must be a linear algebra (+, - *, NumericTraits),
01220     strict weakly ordered (<), and <TT>pow()</TT> must be defined.
01221 
01222     RGB values: the component type must meet the above requirements.
01223 */
01224 template <class PixelType>
01225 class GammaFunctor
01226 {
01227     typedef typename
01228         NumericTraits<PixelType>::RealPromote promote_type;
01229 
01230  public:
01231 
01232         /** the functor's argument type
01233         */
01234     typedef PixelType argument_type;
01235 
01236         /** the functor's result type
01237         */
01238     typedef PixelType result_type;
01239 
01240         /** \deprecated use argument_type and result_type
01241         */
01242     typedef PixelType value_type;
01243 
01244         /** Init functor for argument range <TT>[min, max]</TT>.
01245             <TT>gamma</TT> values < 1 will increase brightness, > 1
01246             will decrease it (gamma == 1 means no change).
01247         */
01248     GammaFunctor(promote_type gamma,
01249                  argument_type const & min, argument_type const & max)
01250     : gamma_(gamma),
01251       min_(min),
01252       diff_(max - min),
01253       zero_(NumericTraits<promote_type>::zero()),
01254       one_(NumericTraits<promote_type>::one())
01255     {}
01256 
01257         /** Calculate modified gray or color value
01258         */
01259     result_type operator()(argument_type const & v) const
01260     {
01261         promote_type v1 = (v - min_) / diff_;
01262         promote_type brighter = VIGRA_CSTD::pow(v1, gamma_);
01263         return result_type(diff_ * brighter + min_);
01264     }
01265 
01266   private:
01267     promote_type gamma_;
01268     argument_type min_;
01269     promote_type diff_, zero_, one_;
01270 };
01271 
01272 template <>
01273 class GammaFunctor<unsigned char>
01274 {
01275     typedef NumericTraits<unsigned char>::RealPromote promote_type;
01276      unsigned char lut[256];
01277 
01278  public:
01279 
01280     typedef unsigned char value_type;
01281 
01282     GammaFunctor(promote_type gamma,
01283                  value_type const & min = 0, value_type const & max = 255)
01284     {
01285         GammaFunctor<promote_type> f(gamma, min, max);
01286 
01287         for(int i = min; i <= max; ++i)
01288         {
01289             lut[i] = static_cast<unsigned char>(f(i)+0.5);
01290         }
01291     }
01292 
01293     value_type operator()(value_type const & v) const
01294     {
01295 
01296         return lut[v];
01297     }
01298 };
01299 
01300 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
01301 
01302 template <class ComponentType>
01303 class GammaFunctor<RGBValue<ComponentType> >
01304 {
01305     typedef typename
01306         NumericTraits<ComponentType>::RealPromote promote_type;
01307     GammaFunctor<ComponentType> red, green, blue;
01308 
01309  public:
01310 
01311     typedef RGBValue<ComponentType> value_type;
01312 
01313     GammaFunctor(promote_type gamma,
01314                  value_type const & min, value_type const & max)
01315     : red(gamma, min.red(), max.red()),
01316       green(gamma, min.green(), max.green()),
01317       blue(gamma, min.blue(), max.blue())
01318     {}
01319 
01320     value_type operator()(value_type const & v) const
01321     {
01322         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01323     }
01324 };
01325 
01326 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01327 
01328 template <>
01329 class GammaFunctor<RGBValue<int> >
01330 {
01331     typedef NumericTraits<int>::RealPromote promote_type;
01332     GammaFunctor<int> red, green, blue;
01333 
01334  public:
01335 
01336     typedef RGBValue<int> value_type;
01337 
01338     GammaFunctor(promote_type gamma,
01339                  value_type const & min, value_type const & max)
01340     : red(gamma, min.red(), max.red()),
01341       green(gamma, min.green(), max.green()),
01342       blue(gamma, min.blue(), max.blue())
01343     {}
01344 
01345     value_type operator()(value_type const & v) const
01346     {
01347         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01348     }
01349 };
01350 
01351 template <>
01352 class GammaFunctor<RGBValue<float> >
01353 {
01354     typedef NumericTraits<float>::RealPromote promote_type;
01355     GammaFunctor<float> red, green, blue;
01356 
01357  public:
01358 
01359     typedef RGBValue<float> 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 <class PixelType>
01375 class FunctorTraits<GammaFunctor<PixelType> >
01376 : public FunctorTraitsBase<GammaFunctor<PixelType> >
01377 {
01378   public:
01379     typedef VigraTrueType isUnaryFunctor;
01380 };
01381 
01382 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01383 
01384 template <>
01385 class GammaFunctor<RGBValue<unsigned char> >
01386 {
01387     typedef NumericTraits<unsigned char>::RealPromote promote_type;
01388     GammaFunctor<unsigned char> red, green, blue;
01389 
01390  public:
01391     typedef RGBValue<unsigned char> value_type;
01392 
01393     GammaFunctor(promote_type gamma,
01394                  value_type const & min = value_type(0,0,0),
01395                  value_type const & max = value_type(255, 255, 255))
01396     : red(gamma, min.red(), max.red()),
01397       green(gamma, min.green(), max.green()),
01398       blue(gamma, min.blue(), max.blue())
01399     {}
01400 
01401     value_type operator()(value_type const & v) const
01402     {
01403         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01404     }
01405 };
01406 
01407 
01408 /********************************************************/
01409 /*                                                      */
01410 /*                     VectorNormFunctor                */
01411 /*                                                      */
01412 /********************************************************/
01413 
01414 /** \brief A functor for computing the vector norm
01415 
01416     Calculate the magnitude or norm from a given vector-valued
01417     entity. The vector type will typically be some sort of
01418     ref vigra::TinyVector. If the vector is represented by a pair of
01419     scalar-valued images, use \ref vigra::MagnitudeFunctor instead.
01420 
01421     At least, the vector type is required to have a function
01422     '<em>result</em><TT> = dot(v,v)</TT>'.
01423 
01424     <b> Traits defined:</b>
01425 
01426     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
01427 
01428     <b> Usage:</b>
01429 
01430         <b>\#include</b> <<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>><br>
01431         Namespace: vigra
01432 
01433     \code
01434     typedef vigra::TinyVector<float, 2> Vector;
01435     vigra::BasicImage<Vector> grad(width, height);
01436     vigra::FImage magn(width,height);
01437     ...
01438     vigra::transformImage(srcImageRange(grad), destImage(magn),
01439                           VectorNormFunctor<float>()
01440                           );
01441     \endcode
01442 
01443     \see vigra::TinyVector, dot(), vigra::MagnitudeFunctor
01444 */
01445 template <class ValueType>
01446 class VectorNormFunctor
01447 {
01448 public:
01449   /** the functor's argument type
01450    */
01451   typedef ValueType argument_type;
01452 
01453   /** the functor's result type
01454    */
01455   typedef typename NumericTraits<typename ValueType::value_type>::RealPromote result_type;
01456 
01457   /** calculate transform '<TT>sqrt(v1*v1 + v2*v2 + ...)</TT>'.
01458    */
01459   result_type operator()( const argument_type &a ) const
01460   {
01461     return VIGRA_CSTD::sqrt( dot(a,a) );
01462   }
01463 };    //-- class VectorNormFunctor
01464 
01465 template <class ValueType>
01466 class FunctorTraits<VectorNormFunctor<ValueType> >
01467 : public FunctorTraitsBase<VectorNormFunctor<ValueType> >
01468 {
01469   public:
01470     typedef VigraTrueType isUnaryFunctor;
01471 };
01472 
01473 /** \brief A functor for computing the squared vector norm
01474 
01475     Calculate the squared magnitude or norm from a given
01476     vector-valued entity. The vector type will typically be some
01477     sort of TinyVector.
01478 
01479     At least, the vector type is required to have a function
01480     '<em>result</em><TT> = dot(v,v)</TT>'.
01481 
01482     For an example of its usage see VectorNormFunctor
01483 
01484     <b> Traits defined:</b>
01485 
01486     <tt>FunctorTraits::isUnaryFunctor</tt> is true (<tt>VigraTrueType</tt>)
01487 
01488     \see TinyVector, dot()
01489 */
01490 template <class ValueType>
01491 class VectorNormSqFunctor
01492 {
01493 public:
01494   /** the functor's argument type
01495    */
01496   typedef ValueType argument_type;
01497 
01498   /** the functor's result type
01499    */
01500   typedef typename NumericTraits<typename ValueType::value_type>::RealPromote result_type;
01501 
01502   /** calculate transform '<TT>v1*v1 + v2*v2 + ...</TT>'.
01503    */
01504   result_type operator()( const argument_type &a ) const
01505   {
01506     return dot(a,a);
01507   }
01508 };    //-- class VectorNormSqFunctor
01509 
01510 template <class ValueType>
01511 class FunctorTraits<VectorNormSqFunctor<ValueType> >
01512 : public FunctorTraitsBase<VectorNormSqFunctor<ValueType> >
01513 {
01514   public:
01515     typedef VigraTrueType isUnaryFunctor;
01516 };
01517 
01518 //@}
01519 
01520 } // namespace vigra
01521 
01522 #endif // VIGRA_TRANSFORMIMAGE_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
VIGRA 1.6.0 (5 Nov 2009)