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