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

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

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

html generated using doxygen and Python
vigra 1.7.0 (Thu Aug 25 2011)