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

details vigra/transformimage.hxx VIGRA

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.2.0, Aug 07 2003 )                                    */
00008 /*    You may use, modify, and distribute this software according       */
00009 /*    to the terms stated in the LICENSE file included in               */
00010 /*    the VIGRA distribution.                                           */
00011 /*                                                                      */
00012 /*    The VIGRA Website is                                              */
00013 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00014 /*    Please direct questions, bug reports, and contributions to        */
00015 /*        koethe@informatik.uni-hamburg.de                              */
00016 /*                                                                      */
00017 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
00018 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
00019 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
00020 /*                                                                      */
00021 /************************************************************************/
00022 
00023 
00024 #ifndef VIGRA_TRANSFORMIMAGE_HXX
00025 #define VIGRA_TRANSFORMIMAGE_HXX
00026 
00027 #include "vigra/utilities.hxx"
00028 #include "vigra/numerictraits.hxx"
00029 #include "vigra/iteratortraits.hxx"
00030 #include "vigra/rgbvalue.hxx"
00031 
00032 namespace vigra {
00033 
00034 /** \addtogroup TransformAlgo Algorithms to Transform Images
00035     Apply functor to calculate a pixelwise transformation of one image
00036 
00037     @{
00038 */
00039 
00040 /********************************************************/
00041 /*                                                      */
00042 /*                      transformLine                   */
00043 /*                                                      */
00044 /********************************************************/
00045 
00046 template <class SrcIterator, class SrcAccessor,
00047           class DestIterator, class DestAccessor, class Functor>
00048 void
00049 transformLine(SrcIterator s,
00050               SrcIterator send, SrcAccessor src,
00051               DestIterator d, DestAccessor dest,
00052               Functor const & f)
00053 {
00054     for(; s != send; ++s, ++d)
00055         dest.set(f(src(s)), d);
00056 }
00057 
00058 template <class SrcIterator, class SrcAccessor,
00059           class MaskIterator, class MaskAccessor,
00060           class DestIterator, class DestAccessor,
00061           class Functor>
00062 void
00063 transformLineIf(SrcIterator s,
00064                 SrcIterator send, SrcAccessor src,
00065                 MaskIterator m, MaskAccessor mask,
00066                 DestIterator d, DestAccessor dest,
00067                 Functor const & f)
00068 {
00069     for(; s != send; ++s, ++d, ++m)
00070         if(mask(m))
00071             dest.set(f(src(s)), d);
00072 }
00073 
00074 /********************************************************/
00075 /*                                                      */
00076 /*                      transformImage                  */
00077 /*                                                      */
00078 /********************************************************/
00079 
00080 /** \brief Apply unary point transformation to each pixel.
00081 
00082     The transformation given by the functor is applied to every source
00083     pixel and the result written into the corresponding destination pixel.
00084     The function uses accessors to access the pixel data.
00085     Note that the unary functors of the STL can be used in addition to
00086     the functors specifically defined in \ref TransformFunctor.
00087     Creation of new functors is easiest by using \ref FunctorExpressions.
00088 
00089     <b> Declarations:</b>
00090 
00091     pass arguments explicitly:
00092     \code
00093     namespace vigra {
00094         template <class SrcImageIterator, class SrcAccessor,
00095               class DestImageIterator, class DestAccessor, class Functor>
00096         void
00097         transformImage(SrcImageIterator src_upperleft,
00098                SrcImageIterator src_lowerright, SrcAccessor sa,
00099                DestImageIterator dest_upperleft, DestAccessor da,
00100                Functor const & f)
00101     }
00102     \endcode
00103 
00104 
00105     use argument objects in conjuction with \ref ArgumentObjectFactories:
00106     \code
00107     namespace vigra {
00108         template <class SrcImageIterator, class SrcAccessor,
00109               class DestImageIterator, class DestAccessor, class Functor>
00110         void
00111         transformImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00112                pair<DestImageIterator, DestAccessor> dest,
00113                Functor const & f)
00114     }
00115     \endcode
00116 
00117     <b> Usage:</b>
00118 
00119         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00120         Namespace: vigra
00121 
00122     \code
00123 
00124     #include <math.h>         // for sqrt()
00125 
00126     vigra::transformImage(srcImageRange(src),
00127                           destImage(dest),
00128                           &::sqrt );
00129 
00130     \endcode
00131 
00132     <b> Required Interface:</b>
00133 
00134     \code
00135     SrcImageIterator src_upperleft, src_lowerright;
00136     DestImageIterator      dest_upperleft;
00137     SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
00138     DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
00139 
00140     SrcAccessor src_accessor;
00141     DestAccessor dest_accessor;
00142 
00143     Functor functor;
00144 
00145     dest_accessor.set(functor(src_accessor(sx)), dx);
00146 
00147     \endcode
00148 
00149 */
00150 template <class SrcImageIterator, class SrcAccessor,
00151           class DestImageIterator, class DestAccessor, class Functor>
00152 void
00153 transformImage(SrcImageIterator src_upperleft,
00154                SrcImageIterator src_lowerright, SrcAccessor sa,
00155                DestImageIterator dest_upperleft, DestAccessor da,
00156                Functor const & f)
00157 {
00158     int w = src_lowerright.x - src_upperleft.x;
00159 
00160     for(; src_upperleft.y < src_lowerright.y; ++src_upperleft.y, ++dest_upperleft.y)
00161     {
00162         transformLine(src_upperleft.rowIterator(),
00163                       src_upperleft.rowIterator() + w, sa,
00164                       dest_upperleft.rowIterator(), da, f);
00165     }
00166 }
00167 
00168 template <class SrcImageIterator, class SrcAccessor,
00169       class DestImageIterator, class DestAccessor, class Functor>
00170 inline
00171 void
00172 transformImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00173                pair<DestImageIterator, DestAccessor> dest,
00174                Functor const & f)
00175 {
00176     transformImage(src.first, src.second, src.third,
00177                    dest.first, dest.second, f);
00178 }
00179 
00180 /********************************************************/
00181 /*                                                      */
00182 /*                   transformImageIf                   */
00183 /*                                                      */
00184 /********************************************************/
00185 
00186 /** \brief Apply unary point transformation to each pixel within the ROI
00187     (i.e., where the mask is non-zero).
00188 
00189     The transformation given by the functor is applied to every source
00190     pixel in the ROI (i.e. when the return vlaue of the mask's accessor
00191     is not zero)
00192     and the result is written into the corresponding destination pixel.
00193     The function uses accessors to access the pixel data.
00194     Note that the unary functors of the STL can be used in addition to
00195     the functors specifically defined in \ref TransformFunctor.
00196     Creation of new functors is easiest by using \ref FunctorExpressions.
00197 
00198     <b> Declarations:</b>
00199 
00200     pass arguments explicitly:
00201     \code
00202     namespace vigra {
00203         template <class SrcImageIterator, class SrcAccessor,
00204               class MaskImageIterator, class MaskAccessor,
00205               class DestImageIterator, clas DestAccessor,
00206               class Functor>
00207         void
00208         transformImageIf(SrcImageIterator src_upperleft,
00209             SrcImageIterator src_lowerright, SrcAccessor sa,
00210             MaskImageIterator mask_upperleft, MaskAccessor ma,
00211             DestImageIterator dest_upperleft, DestAccessor da,
00212             Functor const & f)
00213     }
00214     \endcode
00215 
00216 
00217     use argument objects in conjuction with \ref ArgumentObjectFactories:
00218     \code
00219     namespace vigra {
00220         template <class SrcImageIterator, class SrcAccessor,
00221               class MaskImageIterator, class MaskAccessor,
00222               class DestImageIterator, clas DestAccessor,
00223               class Functor>
00224         void
00225         transformImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00226                  pair<MaskImageIterator, MaskAccessor> mask,
00227                  pair<DestImageIterator, DestAccessor> dest,
00228                  Functor const & f)
00229     }
00230     \endcode
00231 
00232     <b> Usage:</b>
00233 
00234         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00235         Namespace: vigra
00236 
00237     \code
00238     #include <math.h>         // for sqrt()
00239 
00240     vigra::transformImageIf(srcImageRange(src),
00241                             maskImage(mask),
00242                             destImage(dest),
00243                             &::sqrt );
00244 
00245     \endcode
00246 
00247     <b> Required Interface:</b>
00248 
00249     \code
00250     SrcImageIterator src_upperleft, src_lowerright;
00251     DestImageIterator  dest_upperleft;
00252     MaskImageIterator mask_upperleft;
00253     SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
00254     MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
00255     DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
00256 
00257     SrcAccessor src_accessor;
00258     DestAccessor dest_accessor;
00259     MaskAccessor mask_accessor;
00260     Functor functor;
00261 
00262     if(mask_accessor(mx))
00263        dest_accessor.set(functor(src_accessor(sx)), dx);
00264 
00265     \endcode
00266 
00267 */
00268 template <class SrcImageIterator, class SrcAccessor,
00269           class MaskImageIterator, class MaskAccessor,
00270           class DestImageIterator, class DestAccessor,
00271           class Functor>
00272 void
00273 transformImageIf(SrcImageIterator src_upperleft,
00274                  SrcImageIterator src_lowerright, SrcAccessor sa,
00275                  MaskImageIterator mask_upperleft, MaskAccessor ma,
00276                  DestImageIterator dest_upperleft, DestAccessor da,
00277                  Functor const & f)
00278 {
00279     int w = src_lowerright.x - src_upperleft.x;
00280 
00281     for(; src_upperleft.y < src_lowerright.y;
00282              ++src_upperleft.y, ++mask_upperleft.y, ++dest_upperleft.y)
00283     {
00284         transformLineIf(src_upperleft.rowIterator(),
00285                         src_upperleft.rowIterator() + w, sa,
00286                         mask_upperleft.rowIterator(), ma,
00287                         dest_upperleft.rowIterator(), da, f);
00288     }
00289 }
00290 
00291 template <class SrcImageIterator, class SrcAccessor,
00292           class MaskImageIterator, class MaskAccessor,
00293           class DestImageIterator, class DestAccessor,
00294           class Functor>
00295 inline
00296 void
00297 transformImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00298                  pair<MaskImageIterator, MaskAccessor> mask,
00299                  pair<DestImageIterator, DestAccessor> dest,
00300                  Functor const & f)
00301 {
00302     transformImageIf(src.first, src.second, src.third,
00303                      mask.first, mask.second,
00304                      dest.first, dest.second, f);
00305 }
00306 
00307 /********************************************************/
00308 /*                                                      */
00309 /*               gradientBasedTransform                 */
00310 /*                                                      */
00311 /********************************************************/
00312 
00313 /** \brief Calculate a function of the image gradient.
00314 
00315     The gradient and the function represented by <TT>Functor f</TT>
00316     are calculated in one go: for each location, the symmetric
00317     difference in x- and y-directions (asymmetric difference at the
00318     image borders) are passed to the given functor, and the result is
00319     written the destination image. Functors to be used with this
00320     function include \ref MagnitudeFunctor and \ref
00321     RGBGradientMagnitudeFunctor.
00322 
00323     <b> Declarations:</b>
00324 
00325     pass arguments explicitly:
00326     \code
00327     namespace vigra {
00328         template <class SrcImageIterator, class SrcAccessor,
00329                   class DestImageIterator, class DestAccessor, class Functor>
00330         void
00331         gradientBasedTransform(SrcImageIterator srcul, SrcImageIterator srclr, SrcAccessor sa,
00332                       DestImageIterator destul, DestAccessor da, Functor const & f)
00333     }
00334     \endcode
00335 
00336 
00337     use argument objects in conjuction with \ref ArgumentObjectFactories:
00338     \code
00339     namespace vigra {
00340         template <class SrcImageIterator, class SrcAccessor,
00341                   class DestImageIterator, class DestAccessor, class Functor>
00342         void
00343         gradientBasedTransform(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00344                        pair<DestImageIterator, DestAccessor> dest, Functor const & const & f)
00345     }
00346     \endcode
00347 
00348     <b> Usage:</b>
00349 
00350     <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"
00351 
00352 
00353     \code
00354     vigra::FImage src(w,h), magnitude(w,h);
00355     ...
00356 
00357     gradientBasedTransform(srcImageRange(src), destImage(magnitude),
00358                                 vigra::MagnitudeFunctor<float>());
00359     \endcode
00360 
00361     <b> Required Interface:</b>
00362 
00363     \code
00364     SrcImageIterator is, isend;
00365     DestImageIterator id;
00366 
00367     SrcAccessor src_accessor;
00368     DestAccessor dest_accessor;
00369 
00370     typename NumericTraits<typename SrcAccessor::value_type>::RealPromote
00371         diffx, diffy;
00372 
00373     diffx = src_accessor(is, Diff2D(-1,0)) - src_accessor(is, Diff2D(1,0));
00374     diffy = src_accessor(is, Diff2D(0,-1)) - src_accessor(is, Diff2D(0,1));
00375 
00376     Functor f;
00377 
00378     dest_accessor.set(f(diffx, diffy), id);
00379 
00380     \endcode
00381 
00382 */
00383 
00384 template <class SrcImageIterator, class SrcAccessor,
00385           class DestImageIterator, class DestAccessor, class Functor>
00386 void
00387 gradientBasedTransform(SrcImageIterator srcul, SrcImageIterator srclr, SrcAccessor sa,
00388                        DestImageIterator destul, DestAccessor da, Functor const & grad)
00389 {
00390     int w = srclr.x - srcul.x;
00391     int h = srclr.y - srcul.y;
00392     int x,y;
00393 
00394     SrcImageIterator sy = srcul;
00395     DestImageIterator dy = destul;
00396 
00397     static const Diff2D left(-1,0);
00398     static const Diff2D right(1,0);
00399     static const Diff2D top(0,-1);
00400     static const Diff2D bottom(0,1);
00401 
00402     typename NumericTraits<typename SrcAccessor::value_type>::RealPromote
00403              diffx, diffy;
00404 
00405     SrcImageIterator sx = sy;
00406     DestImageIterator dx = dy;
00407 
00408     diffx = sa(sx) - sa(sx, right);
00409     diffy = sa(sx) - sa(sx, bottom);
00410     da.set(grad(diffx, diffy), dx);
00411 
00412     for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
00413     {
00414         diffx = (sa(sx, left) - sa(sx, right)) / 2.0;
00415         diffy = sa(sx) - sa(sx, bottom);
00416         da.set(grad(diffx, diffy), dx);
00417     }
00418 
00419     diffx = sa(sx, left) - sa(sx);
00420     diffy = sa(sx) - sa(sx, bottom);
00421     da.set(grad(diffx, diffy), dx);
00422 
00423     ++sy.y;
00424     ++dy.y;
00425 
00426     for(y=2; y<h; ++y, ++sy.y, ++dy.y)
00427     {
00428         sx = sy;
00429         dx = dy;
00430 
00431         diffx = sa(sx) - sa(sx, right);
00432         diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0;
00433         da.set(grad(diffx, diffy), dx);
00434 
00435         for(x=2, ++sx.x, ++dx.x; x<w; ++x, ++sx.x, ++dx.x)
00436         {
00437             diffx = (sa(sx, left) - sa(sx, right)) / 2.0;
00438             diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0;
00439             da.set(grad(diffx, diffy), dx);
00440         }
00441 
00442         diffx = sa(sx, left) - sa(sx);
00443         diffy = (sa(sx, top) - sa(sx, bottom)) / 2.0;
00444         da.set(grad(diffx, diffy), dx);
00445     }
00446 
00447     sx = sy;
00448     dx = dy;
00449 
00450     diffx = sa(sx) - sa(sx, right);
00451     diffy = sa(sx, top) - sa(sx);
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)) / 2.0;
00457         diffy = sa(sx, top) - sa(sx);
00458         da.set(grad(diffx, diffy), dx);
00459     }
00460 
00461     diffx = sa(sx, left) - sa(sx);
00462     diffy = sa(sx, top) - sa(sx);
00463     da.set(grad(diffx, diffy), dx);
00464 }
00465 
00466 template <class SrcImageIterator, class SrcAccessor,
00467           class DestImageIterator, class DestAccessor, class Functor>
00468 inline
00469 void
00470 gradientBasedTransform(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
00471                        pair<DestImageIterator, DestAccessor> dest, Functor const & grad)
00472 {
00473     gradientBasedTransform(src.first, src.second, src.third,
00474                            dest.first, dest.second, grad);
00475 }
00476 
00477 /** @} */
00478 /** \addtogroup TransformFunctor Functors to Transform Images
00479 
00480     Note that the unary functors of the STL can also be used in
00481     connection with \ref transformImage().
00482 */
00483 //@{
00484 
00485 template <class DestValueType, class Multiplier = double>
00486 class LinearIntensityTransform
00487 {
00488   public:
00489         /* the functors argument type (actually, since 
00490            <tt>operator()</tt> is a template, much more types are possible)
00491         */
00492     typedef DestValueType argument_type;
00493 
00494         /* the functors result type
00495         */
00496     typedef DestValueType result_type;
00497 
00498         /* \deprecated use argument_type and result_type
00499         */
00500     typedef DestValueType value_type;
00501 
00502         /* type of the offset (used in internal calculations to prevent
00503             overflows and minimize round-off errors).
00504         */
00505     typedef typename
00506             NumericTraits<DestValueType>::RealPromote argument_promote;
00507 
00508         /* type of the scale factor
00509         */
00510     typedef Multiplier scalar_multiplier_type;
00511 
00512         /* init scale and offset
00513         */
00514     LinearIntensityTransform(scalar_multiplier_type scale, argument_promote offset)
00515     : scale_(scale), offset_(offset)
00516     {}
00517 
00518         /* calculate transform
00519         */
00520     template <class SrcValueType>
00521     result_type operator()(SrcValueType const & s) const
00522     {
00523         return NumericTraits<result_type>::fromRealPromote(scale_ * (s + offset_));
00524     }
00525 
00526   private:
00527 
00528     scalar_multiplier_type scale_;
00529     argument_promote offset_;
00530 };
00531 
00532 
00533 template <class DestValueType, class Multiplier = double>
00534 class ScalarIntensityTransform
00535 {
00536   public:
00537         /* the functors argument type (actually, since 
00538            <tt>operator()</tt> is a template, much more types are possible)
00539         */
00540     typedef DestValueType argument_type;
00541 
00542         /* the functors result type
00543         */
00544     typedef DestValueType result_type;
00545 
00546         /* \deprecated use argument_type and result_type
00547         */
00548     typedef DestValueType value_type;
00549 
00550         /* type of the scale factor
00551         */
00552     typedef Multiplier scalar_multiplier_type;
00553 
00554         /* init scale
00555         */
00556     ScalarIntensityTransform(scalar_multiplier_type scale)
00557     : scale_(scale)
00558     {}
00559 
00560         /* calculate transform
00561         */
00562     template <class SrcValueType>
00563     result_type operator()(SrcValueType const & s) const
00564     {
00565         return NumericTraits<result_type>::fromRealPromote(scale_ * s);
00566     }
00567 
00568   private:
00569     scalar_multiplier_type scale_;
00570 };
00571 
00572 /********************************************************/
00573 /*                                                      */
00574 /*              linearIntensityTransform                */
00575 /*                                                      */
00576 /********************************************************/
00577 
00578 /** \brief Apply a linear transform to the source pixel values
00579 
00580     Factory function for a functor that linearly transforms the
00581     source pixel values. The functor applies the transform
00582     '<TT>destvalue = scale * (srcvalue + offset)</TT>' to every pixel.
00583     This can, for example, be used to transform images into the visible
00584     range 0...255 or to invert an image.
00585 
00586     If you leave out the second parameter / offset, you will get an
00587     optimized version of the functor which only scales by the given
00588     factor, however you have to make the template parameter (pixel
00589     type) explicit.
00590 
00591     <b> Declaration:</b>
00592 
00593     \code
00594     namespace vigra {
00595         template <class Multiplier, class DestValueType>
00596         LinearIntensityTransform<DestValueType, Multiplier>
00597         linearIntensityTransform(Multiplier scale, DestValueType offset);
00598 
00599         template <class DestValueType, class Multiplier>
00600         ScalarIntensityTransform<DestValueType, Multiplier>
00601         linearIntensityTransform(Multiplier scale);
00602     }
00603     \endcode
00604 
00605     <b> Usage:</b>
00606 
00607         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00608         Namespace: vigra
00609 
00610     \code
00611     vigra::IImage src(width, height);
00612     vigra::BImage dest(width, height);
00613     ...
00614     vigra::FindMinMax<IImage::PixelType> minmax;   // functor to find range
00615 
00616     vigra::inspectImage(srcImageRange(src), minmax); // find original range
00617 
00618     // transform to range 0...255
00619     vigra::transformImage(srcImageRange(src), destImage(dest),
00620                           linearIntensityTransform(
00621                             255.0 / (minmax.max - minmax.min), // scaling
00622                           - minmax.min));                    // offset
00623     \endcode
00624 
00625     The one-parameter version can be used like this:
00626 
00627     \code
00628     // scale from 0..255 to 0..1.0
00629     FImage dest(src.size());
00630 
00631     vigra::transformImage(srcImageRange(src), destImage(dest),
00632                           linearIntensityTransform<float>(1.0 / 255));
00633     \endcode
00634 
00635     <b> Required Interface:</b>
00636 
00637     The source and destination value types must be models of \ref LinearSpace in both cases.
00638 
00639 */
00640 template <class Multiplier, class DestValueType>
00641 LinearIntensityTransform<DestValueType, Multiplier>
00642 linearIntensityTransform(Multiplier scale, DestValueType offset)
00643 {
00644     return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
00645 }
00646 
00647 template <class DestValueType, class Multiplier>
00648 ScalarIntensityTransform<DestValueType, Multiplier>
00649 linearIntensityTransform(Multiplier scale)
00650 {
00651     return ScalarIntensityTransform<DestValueType, Multiplier>(scale);
00652 }
00653 
00654 /********************************************************/
00655 /*                                                      */
00656 /*                   linearRangeMapping                 */
00657 /*                                                      */
00658 /********************************************************/
00659 
00660 /** \brief Map a source intensity range linearly to a destination range.
00661 
00662     Factory function for a functor that linearly transforms the
00663     source pixel values. The functor applies the transform
00664     '<TT>destvalue = scale * (srcvalue + offset)</TT>' to every pixel,
00665     where <tt>scale = (dest_max - dest_min) / (src_max - src_min)</tt>
00666     and <tt>offset = dest_min / scale - src_min</tt>. As a result,
00667     the pixel values <tt>src_max</tt>, <tt>src_min</tt> in the source image 
00668     are mapped onto <tt>dest_max</tt>, <tt>dest_min</tt> respectively. 
00669     This works for scalar as well as vector pixel types.
00670 
00671     <b> Declaration:</b>
00672 
00673     \code
00674     namespace vigra {
00675         template <class SrcValueType, class DestValueType>
00676         LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00677         linearRangeMapping(SrcValueType src_min, SrcValueType src_max, 
00678                            DestValueType dest_min, DestValueType dest_max );
00679     }
00680     \endcode
00681 
00682     <b> Usage:</b>
00683 
00684         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00685         Namespace: vigra
00686 
00687     \code
00688     vigra::IImage src(width, height);
00689     vigra::BImage dest(width, height);
00690     ...
00691     vigra::FindMinMax<IImage::PixelType> minmax;   // functor to find range
00692 
00693     vigra::inspectImage(srcImageRange(src), minmax); // find original range
00694 
00695     // transform to range 0...255
00696     vigra::transformImage(srcImageRange(src), destImage(dest),
00697                           linearRangeTransform(
00698                             minmax.min, minmax.max,               // src range
00699                             (unsigned char)0, (unsigned char)255) // dest range
00700                           );
00701     \endcode
00702 
00703     <b> Required Interface:</b>
00704 
00705     The source and destination value types must be models of \ref LinearSpace in both cases.
00706 
00707 */
00708 template <class SrcValueType, class DestValueType>
00709 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00710 linearRangeMapping(SrcValueType src_min, SrcValueType src_max, 
00711                    DestValueType dest_min, DestValueType dest_max )
00712 {
00713     return linearRangeMapping(src_min, src_max, dest_min, dest_max,
00714             typename NumericTraits<DestValueType>::isScalar());
00715 } 
00716 
00717 template <class SrcValueType, class DestValueType>
00718 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00719 linearRangeMapping(
00720     SrcValueType src_min, SrcValueType src_max, 
00721     DestValueType dest_min, DestValueType dest_max,
00722     VigraTrueType /* isScalar */ )
00723 {
00724     typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
00725     Multiplier diff = src_max - src_min;
00726     Multiplier scale = diff == NumericTraits<Multiplier>::zero()
00727                      ? NumericTraits<Multiplier>::one() 
00728                      : (dest_max - dest_min) / diff;
00729     return LinearIntensityTransform<DestValueType, Multiplier>(
00730                                    scale, dest_min / scale - src_min );
00731 } 
00732 
00733 template <class SrcValueType, class DestValueType>
00734 LinearIntensityTransform<DestValueType, typename NumericTraits<DestValueType>::RealPromote>
00735 linearRangeMapping(
00736     SrcValueType src_min, SrcValueType src_max, 
00737     DestValueType dest_min, DestValueType dest_max,
00738     VigraFalseType /* isScalar */ )
00739 {
00740     typedef typename NumericTraits<DestValueType>::RealPromote Multiplier;
00741     typedef typename Multiplier::value_type MComponent;
00742     Multiplier scale(dest_max), offset(dest_max);
00743     for(int i=0; i<src_min.size(); ++i)
00744     { 
00745         MComponent diff = src_max[i] - src_min[i];
00746         scale[i] = diff == NumericTraits<MComponent>::zero()
00747                      ? NumericTraits<MComponent>::one() 
00748                      : (dest_max[i] - dest_min[i]) / diff;
00749         offset[i] = dest_min[i] / scale[i] - src_min[i];
00750     }
00751     return LinearIntensityTransform<DestValueType, Multiplier>(scale, offset);
00752 } 
00753 
00754 /********************************************************/
00755 /*                                                      */
00756 /*                      Threshold                       */
00757 /*                                                      */
00758 /********************************************************/
00759 
00760 /** \brief Threshold an image.
00761 
00762     If a source pixel is above or equal the lower and below
00763     or equal the higher threshold (i.e. within the closed interval
00764     [lower, heigher]) the destination pixel is set to 'yesresult',
00765     otherwise to 'noresult'.
00766 
00767     <b> Usage:</b>
00768 
00769         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00770         Namespace: vigra
00771 
00772     \code
00773     vigra::BImage src(width, height), dest(width, height);
00774     ...
00775     vigra::transformImage(src.upperLeft(), src.lowerRight(), src.accessor(),
00776        dest.upperLeft(), dest.accessor(),
00777        vigra::Threshold<
00778           vigra::BImage::PixelType, vigra::BImage::PixelType>(10, 100, 0, 255));
00779 
00780     \endcode
00781 
00782     <b> Required Interface:</b>
00783 
00784     \code
00785 
00786     SrcValueType   src;
00787     DestValueType  dest, yesresult, noresult;
00788 
00789     dest = ((src < lower) || (higher < src)) ? noresult : yesresult;
00790 
00791     \endcode
00792 
00793 */
00794 template <class SrcValueType, class DestValueType>
00795 class Threshold
00796 {
00797    public:
00798 
00799         /** the functor's argument type
00800         */
00801     typedef SrcValueType argument_type;
00802 
00803         /** the functor's result type
00804         */
00805     typedef DestValueType result_type;
00806 
00807         /** init thresholds and return values
00808         */
00809     Threshold(argument_type lower, argument_type higher,
00810               result_type noresult, result_type yesresult)
00811     : lower_(lower), higher_(higher),
00812       yesresult_(yesresult), noresult_(noresult)
00813     {}
00814 
00815         /** calculate transform
00816         */
00817     result_type operator()(argument_type s) const
00818     {
00819         return ((s < lower_) || (higher_ < s)) ? noresult_ : yesresult_;
00820     }
00821 
00822   private:
00823 
00824     argument_type lower_, higher_;
00825     result_type yesresult_, noresult_;
00826 };
00827 
00828 /********************************************************/
00829 /*                                                      */
00830 /*                BrightnessContrastFunctor             */
00831 /*                                                      */
00832 /********************************************************/
00833 
00834 /** \brief Adjust brightness and contrast of an image.
00835 
00836     This functor applies a gamma correction to each pixel in order to
00837     modify the brightness of the image. To the result of the gamma correction,
00838     another transform is applied that modifies the contrast. The brightness and
00839     contrast parameters must be positive. Values greater than 1 will increase image
00840     brightness and contrast, values smaller than 1 decrease them. A value = 1 will
00841     have no effect.
00842     For \ref RGBValue "RGBValue's", the transforms are applied component-wise. The pixel
00843     values are assumed to lie between the given minimum and maximum
00844     values. In case of RGB, this is again understood component-wise. In case
00845     of <TT>unsigned char</TT>, min and max default to 0 and 255 respectively.
00846     Precisely, the following transform is applied to each <em> PixelValue</em>:
00847 
00848     \f[
00849     \begin{array}{rcl}
00850     V_1 & = & \frac{PixelValue - min}{max - min} \\
00851     V_2 & = & V_1^\frac{1}{brightness} \\
00852     V_3 & = & 2 V_2 - 1 \\
00853     V_4 & = & \left\lbrace
00854         \begin{array}{l}
00855          V_3^\frac{1}{contrast} \mbox{\rm \quad if  } V_3 \ge 0 \\
00856          - (-V_3)^\frac{1}{contrast} \mbox{\rm \quad otherwise}
00857         \end{array} \right. \\
00858     Result & = & \frac{V_4 + 1}{2} (max - min) + min
00859     \end{array}
00860     \f]
00861 
00862     If the <TT>PixelType</TT> is <TT>unsigned char</TT>, a look-up-table is used
00863     for faster computation.
00864 
00865     <b> Usage:</b>
00866 
00867         <b>\#include</b> "<a href="transformimage_8hxx-source.html">vigra/transformimage.hxx</a>"<br>
00868         Namespace: vigra
00869 
00870     \code
00871     vigra::BImage bimage(width, height);
00872     double brightness, contrast;
00873     ...
00874     vigra::transformImage(srcImageRange(bimage), destImage(bimage),
00875        vigra::BrightnessContrastFunctor<unsigned char>(brightness, contrast));
00876 
00877 
00878 
00879     vigra::FImage fimage(width, height);
00880     ...
00881 
00882     vigra::FindMinmax<float> minmax;
00883     vigra::inspectImage(srcImageRange(fimage), minmax);
00884 
00885     vigra::transformImage(srcImageRange(fimage), destImage(fimage),
00886        vigra::BrightnessContrastFunctor<float>(brightness, contrast, minmax.min, minmax.max));
00887 
00888 
00889     \endcode
00890 
00891     <b> Required Interface:</b>
00892 
00893     Scalar types: must be a linear algebra (+, - *, NumericTraits),
00894     strict weakly ordered (<), and <TT>pow()</TT> must be defined.
00895 
00896     RGB values: the component type must meet the above requirements.
00897 */
00898 template <class PixelType>
00899 class BrightnessContrastFunctor
00900 {
00901     typedef typename
00902         NumericTraits<PixelType>::RealPromote promote_type;
00903 
00904  public:
00905 
00906         /** the functor's argument type
00907         */
00908     typedef PixelType argument_type;
00909 
00910         /** the functor's result type
00911         */
00912     typedef PixelType result_type;
00913 
00914         /** \deprecated use argument_type and result_type
00915         */
00916     typedef PixelType value_type;
00917 
00918         /** Init functor for argument range <TT>[min, max]</TT>.
00919             <TT>brightness</TT> and <TT>contrast</TT> values > 1 will
00920             increase brightness and contrast, < 1 will decrease them, and == 1 means
00921             no change.
00922         */
00923     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
00924                               argument_type const & min, argument_type const & max)
00925     : b_(1.0/brightness),
00926       c_(1.0/contrast),
00927       min_(min),
00928       diff_(max - min),
00929       zero_(NumericTraits<promote_type>::zero()),
00930       one_(NumericTraits<promote_type>::one())
00931     {}
00932 
00933         /** Calculate modified gray or color value
00934         */
00935     result_type operator()(argument_type const & v) const
00936     {
00937         promote_type v1 = (v - min_) / diff_;
00938         promote_type brighter = pow(v1, b_);
00939         promote_type v2 = 2.0 * brighter - one_;
00940         promote_type contrasted = (v2 < zero_) ?
00941                                      -pow(-v2, c_) :
00942                                       pow(v2, c_);
00943         return result_type(0.5 * diff_ * (contrasted + one_) + min_);
00944     }
00945 
00946   private:
00947     promote_type b_, c_;
00948     argument_type min_;
00949     promote_type diff_, zero_, one_;
00950 };
00951 
00952 template <>
00953 class BrightnessContrastFunctor<unsigned char>
00954 {
00955     typedef NumericTraits<unsigned char>::RealPromote promote_type;
00956      unsigned char lut[256];
00957 
00958  public:
00959 
00960     typedef unsigned char value_type;
00961 
00962     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
00963                               value_type const & min = 0, value_type const & max = 255)
00964     {
00965         BrightnessContrastFunctor<promote_type> f(brightness, contrast, min, max);
00966 
00967         for(int i = min; i <= max; ++i)
00968         {
00969             lut[i] = static_cast<unsigned char>(f(i)+0.5);
00970         }
00971     }
00972 
00973     value_type operator()(value_type const & v) const
00974     {
00975 
00976         return lut[v];
00977     }
00978 };
00979 
00980 #ifndef NO_PARTIAL_TEMPLATE_SPECIALIZATION
00981 
00982 template <class ComponentType>
00983 class BrightnessContrastFunctor<RGBValue<ComponentType> >
00984 {
00985     typedef typename
00986         NumericTraits<ComponentType>::RealPromote promote_type;
00987     BrightnessContrastFunctor<ComponentType> red, green, blue;
00988 
00989  public:
00990 
00991     typedef RGBValue<ComponentType> value_type;
00992 
00993     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
00994                               value_type const & min, value_type const & max)
00995     : red(brightness, contrast, min.red(), max.red()),
00996       green(brightness, contrast, min.green(), max.green()),
00997       blue(brightness, contrast, min.blue(), max.blue())
00998     {}
00999 
01000     value_type operator()(value_type const & v) const
01001     {
01002 
01003         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01004     }
01005 };
01006 
01007 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01008 
01009 template <>
01010 class BrightnessContrastFunctor<RGBValue<int> >
01011 {
01012     typedef NumericTraits<int>::RealPromote promote_type;
01013     BrightnessContrastFunctor<int> red, green, blue;
01014 
01015  public:
01016 
01017     typedef RGBValue<int> value_type;
01018 
01019     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01020                               value_type const & min, value_type const & max)
01021     : red(brightness, contrast, min.red(), max.red()),
01022       green(brightness, contrast, min.green(), max.green()),
01023       blue(brightness, contrast, min.blue(), max.blue())
01024     {}
01025 
01026     value_type operator()(value_type const & v) const
01027     {
01028 
01029         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01030     }
01031 };
01032 
01033 template <>
01034 class BrightnessContrastFunctor<RGBValue<float> >
01035 {
01036     typedef NumericTraits<float>::RealPromote promote_type;
01037     BrightnessContrastFunctor<float> red, green, blue;
01038 
01039  public:
01040 
01041     typedef RGBValue<float> value_type;
01042 
01043     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01044                               value_type const & min, value_type const & max)
01045     : red(brightness, contrast, min.red(), max.red()),
01046       green(brightness, contrast, min.green(), max.green()),
01047       blue(brightness, contrast, min.blue(), max.blue())
01048     {}
01049 
01050     value_type operator()(value_type const & v) const
01051     {
01052 
01053         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01054     }
01055 };
01056 
01057 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
01058 
01059 template <>
01060 class BrightnessContrastFunctor<RGBValue<unsigned char> >
01061 {
01062     typedef NumericTraits<unsigned char>::RealPromote promote_type;
01063     BrightnessContrastFunctor<unsigned char> red, green, blue;
01064 
01065  public:
01066 
01067     typedef RGBValue<unsigned char> value_type;
01068 
01069     BrightnessContrastFunctor(promote_type brightness, promote_type contrast,
01070        value_type const & min = value_type(0,0,0),
01071        value_type const & max = value_type(255, 255, 255))
01072     : red(brightness, contrast, min.red(), max.red()),
01073       green(brightness, contrast, min.green(), max.green()),
01074       blue(brightness, contrast, min.blue(), max.blue())
01075     {}
01076 
01077     value_type operator()(value_type const & v) const
01078     {
01079 
01080         return value_type(red(v.red()), green(v.green()), blue(v.blue()));
01081     }
01082 };
01083 
01084 //@}
01085 
01086 } // namespace vigra
01087 
01088 #endif // VIGRA_TRANSFORMIMAGE_HXX

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.2.0 (7 Aug 2003)