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

vigra/transformimage.hxx

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

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

html generated using doxygen and Python
VIGRA 1.6.0 (13 Aug 2008)