[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 1998-2002 by Ullrich Koethe */ 00004 /* Cognitive Systems Group, University of Hamburg, Germany */ 00005 /* */ 00006 /* This file is part of the VIGRA computer vision library. */ 00007 /* ( Version 1.6.0, Aug 13 2008 ) */ 00008 /* The VIGRA Website is */ 00009 /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ 00010 /* Please direct questions, bug reports, and contributions to */ 00011 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00012 /* vigra@informatik.uni-hamburg.de */ 00013 /* */ 00014 /* Permission is hereby granted, free of charge, to any person */ 00015 /* obtaining a copy of this software and associated documentation */ 00016 /* files (the "Software"), to deal in the Software without */ 00017 /* restriction, including without limitation the rights to use, */ 00018 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00019 /* sell copies of the Software, and to permit persons to whom the */ 00020 /* Software is furnished to do so, subject to the following */ 00021 /* conditions: */ 00022 /* */ 00023 /* The above copyright notice and this permission notice shall be */ 00024 /* included in all copies or substantial portions of the */ 00025 /* Software. */ 00026 /* */ 00027 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00028 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00029 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00030 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00031 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00032 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00033 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00034 /* OTHER DEALINGS IN THE SOFTWARE. */ 00035 /* */ 00036 /************************************************************************/ 00037 00038 00039 #ifndef VIGRA_RGBVALUE_HXX 00040 #define VIGRA_RGBVALUE_HXX 00041 00042 #include <cmath> // abs(double) 00043 #include <cstdlib> // abs(int) 00044 #include "config.hxx" 00045 #include "numerictraits.hxx" 00046 #include "accessor.hxx" 00047 #include "tinyvector.hxx" 00048 #include "static_assert.hxx" 00049 00050 namespace vigra { 00051 00052 namespace detail { 00053 00054 template <unsigned int I, unsigned int R, unsigned int G, unsigned int B> 00055 struct SelectColorIndexRHS; 00056 00057 template <unsigned int R, unsigned int G, unsigned int B> 00058 struct SelectColorIndexRHS<0, R, G, B> 00059 { 00060 enum { res = R }; 00061 }; 00062 00063 template <unsigned int R, unsigned int G, unsigned int B> 00064 struct SelectColorIndexRHS<1, R, G, B> 00065 { 00066 enum { res = G }; 00067 }; 00068 00069 template <unsigned int R, unsigned int G, unsigned int B> 00070 struct SelectColorIndexRHS<2, R, G, B> 00071 { 00072 enum { res = B }; 00073 }; 00074 00075 } // namespace detail 00076 00077 #ifndef DOXYGEN 00078 00079 template <unsigned int R, unsigned int G, unsigned int B> 00080 struct RGBValue_bad_color_indices 00081 : staticAssert::AssertBool<(R < 3 && G < 3 && B < 3 && 00082 ((1 << R) + (1 << G) + (1 << B) == 7))> 00083 {}; 00084 00085 #endif /* DOXYGEN */ 00086 00087 00088 /********************************************************/ 00089 /* */ 00090 /* RGBValue */ 00091 /* */ 00092 /********************************************************/ 00093 00094 /** \brief Class for a single RGB value. 00095 00096 This class contains three values (of the specified type) that represent 00097 red, green, and blue color channels. By means of the template parameters 00098 <tt>RED_IDX, GREEN_IDX, BLUE_IDX</tt>, the indices 0, 1, 2 can be assigned to 00099 the three colors arbitrarily, so that, for example, a BGR type can be created 00100 as 00101 00102 \code 00103 typedef RGBValue<unsigned char, 2,1,0> BGRValue; 00104 \endcode 00105 00106 The standard order red=0, green=1, blue=2 is the default. There are three possibilities 00107 to access the color values: accessor functions (\ref red(), \ref green(), 00108 \ref blue()), index operator (operator[](dx), where the <tt>rgb[RED_IDX]</tt> 00109 returns red etc.) and iterator (STL-compatible random access 00110 iterator that references the three colors in turn). The latter two 00111 methods, together with the necessary embedded typedefs, ensure 00112 compatibility of a RGBValue with a STL vector. 00113 00114 \ref RGBValueOperators "Arithmetic operations" are defined as component-wise applications of these 00115 operations. Addition, subtraction, and multiplication of two RGBValues 00116 (+=, -=, *=, +, -, *, unary -), multiplication and division of an 00117 RGBValue with a double, and NumericTraits/PromoteTraits are defined, 00118 so that RGBValue fulfills the requirements of a \ref LinearAlgebraConcept "Linear Algebra". 00119 00120 A number of \ref RGBValueAccessors "accessors" are provided 00121 that support access to RGBValues as a whole, to a selected 00122 color component, or to the luminance value. 00123 00124 <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br> 00125 Namespace: vigra 00126 */ 00127 template <class VALUETYPE, unsigned int RED_IDX = 0, unsigned int GREEN_IDX = 1, unsigned int BLUE_IDX = 2> 00128 class RGBValue 00129 : public TinyVector<VALUETYPE, 3> 00130 { 00131 typedef TinyVector<VALUETYPE, 3> Base; 00132 00133 // inverse mapping from index to color 00134 enum { 00135 IDX0 = (RED_IDX == 0) ? 0 : (GREEN_IDX == 0) ? 1 : 2, 00136 IDX1 = (RED_IDX == 1) ? 0 : (GREEN_IDX == 1) ? 1 : 2, 00137 IDX2 = (RED_IDX == 2) ? 0 : (GREEN_IDX == 2) ? 1 : 2 00138 }; 00139 00140 public: 00141 /** STL-compatible definition of valuetype 00142 */ 00143 typedef typename Base::value_type value_type; 00144 /** STL-compatible definition of iterator 00145 */ 00146 typedef typename Base::iterator iterator; 00147 /** STL-compatible definition of const iterator 00148 */ 00149 typedef typename Base::const_iterator const_iterator; 00150 /** squared norm type (result of squaredManitude()) 00151 */ 00152 typedef typename Base::SquaredNormType SquaredNormType; 00153 /** norm type (result of magnitude()) 00154 */ 00155 typedef typename Base::NormType NormType; 00156 00157 /** Color index positions 00158 */ 00159 enum 00160 { 00161 RedIdx = RED_IDX, 00162 GreenIdx = GREEN_IDX, 00163 BlueIdx = BLUE_IDX 00164 }; 00165 00166 /** Construct from explicit color values. 00167 \a first, \a second, \a third are written in this order, 00168 irrespective of how the color indices are specified. 00169 */ 00170 RGBValue(value_type first, value_type second, value_type third) 00171 : Base(first, second, third) 00172 { 00173 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); 00174 } 00175 00176 /** Construct gray value 00177 */ 00178 RGBValue(value_type gray) 00179 : Base(gray, gray, gray) 00180 { 00181 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); 00182 } 00183 00184 /** Construct from another sequence (must have length 3!) 00185 */ 00186 template <class Iterator> 00187 RGBValue(Iterator i, Iterator end) 00188 : Base(i[0], i[1], i[2]) 00189 { 00190 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); 00191 } 00192 00193 /** Default constructor (sets all components to 0) 00194 */ 00195 RGBValue() 00196 : Base(0, 0, 0) 00197 { 00198 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); 00199 } 00200 00201 #if !defined(TEMPLATE_COPY_CONSTRUCTOR_BUG) 00202 00203 RGBValue(RGBValue const & r) 00204 : Base(r) 00205 { 00206 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); 00207 } 00208 00209 RGBValue & operator=(RGBValue const & r) 00210 { 00211 Base::operator=(r); 00212 return *this; 00213 } 00214 00215 #endif // TEMPLATE_COPY_CONSTRUCTOR_BUG 00216 00217 /** Copy constructor. 00218 */ 00219 template <class U, unsigned int R, unsigned int G, unsigned int B> 00220 RGBValue(RGBValue<U, R, G, B> const & r) 00221 : Base(detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX0, R, G, B>::res]), 00222 detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX1, R, G, B>::res]), 00223 detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX2, R, G, B>::res])) 00224 { 00225 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); 00226 } 00227 00228 /** Copy assignment. 00229 */ 00230 template <class U, unsigned int R, unsigned int G, unsigned int B> 00231 RGBValue & operator=(RGBValue<U, R, G, B> const & r) 00232 { 00233 setRed(detail::RequiresExplicitCast<value_type>::cast(r.red())); 00234 setGreen(detail::RequiresExplicitCast<value_type>::cast(r.green())); 00235 setBlue(detail::RequiresExplicitCast<value_type>::cast(r.blue())); 00236 return *this; 00237 } 00238 00239 /** construct from TinyVector 00240 */ 00241 RGBValue(TinyVector<value_type, 3> const & r) 00242 : Base(r) 00243 { 00244 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>)); 00245 } 00246 00247 /** assign TinyVector. 00248 */ 00249 RGBValue & operator=(TinyVector<value_type, 3> const & r) 00250 { 00251 Base::operator=(r); 00252 return *this; 00253 } 00254 00255 /** Unary negation (construct RGBValue with negative values) 00256 */ 00257 RGBValue operator-() const 00258 { 00259 return RGBValue(-red(), -green(), -blue()); 00260 } 00261 00262 /** Access red component. 00263 */ 00264 value_type & red() { return (*this)[RED_IDX]; } 00265 00266 /** Access green component. 00267 */ 00268 value_type & green() { return (*this)[GREEN_IDX]; } 00269 00270 /** Access blue component. 00271 */ 00272 value_type & blue() { return (*this)[BLUE_IDX]; } 00273 00274 /** Get red component. 00275 */ 00276 value_type const & red() const { return (*this)[RED_IDX]; } 00277 00278 /** Get green component. 00279 */ 00280 value_type const & green() const { return (*this)[GREEN_IDX]; } 00281 00282 /** Get blue component. 00283 */ 00284 value_type const & blue() const { return (*this)[BLUE_IDX]; } 00285 00286 /** Calculate luminance. 00287 */ 00288 value_type luminance() const { 00289 return detail::RequiresExplicitCast<value_type>::cast(0.3*red() + 0.59*green() + 0.11*blue()); } 00290 00291 /** Calculate magnitude. 00292 */ 00293 NormType magnitude() const { 00294 return Base::magnitude(); 00295 } 00296 00297 /** Calculate squared magnitude. 00298 */ 00299 SquaredNormType squaredMagnitude() const { 00300 return Base::squaredMagnitude(); 00301 } 00302 00303 /** Set red component. The type <TT>V</TT> of the passed 00304 in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>. 00305 */ 00306 template <class V> 00307 void setRed(V value) { (*this)[RED_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); } 00308 00309 /** Set green component.The type <TT>V</TT> of the passed 00310 in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>. 00311 */ 00312 template <class V> 00313 void setGreen(V value) { (*this)[GREEN_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); } 00314 00315 /** Set blue component.The type <TT>V</TT> of the passed 00316 in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>. 00317 */ 00318 template <class V> 00319 void setBlue(V value) { (*this)[BLUE_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); } 00320 00321 00322 template <class V> 00323 void setRGB(V r, V g, V b) 00324 { 00325 (*this)[RED_IDX] = detail::RequiresExplicitCast<value_type>::cast(r); 00326 (*this)[GREEN_IDX] = detail::RequiresExplicitCast<value_type>::cast(g); 00327 (*this)[BLUE_IDX] = detail::RequiresExplicitCast<value_type>::cast(b); 00328 } 00329 }; 00330 00331 /********************************************************/ 00332 /* */ 00333 /* RGBValue Comparison */ 00334 /* */ 00335 /********************************************************/ 00336 00337 /** \addtogroup RGBValueOperators Functions for RGBValue 00338 00339 \brief Implement basic arithmetic and equality for RGBValue. 00340 00341 These functions fulfill the requirements of a Linear Algebra. 00342 Return types are determined according to \ref RGBValueTraits. 00343 00344 <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br> 00345 Namespace: vigra 00346 <p> 00347 00348 */ 00349 //@{ 00350 /// component-wise equal 00351 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1, 00352 class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2> 00353 inline 00354 bool 00355 operator==(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & l, 00356 RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r) 00357 { 00358 return (l.red() == r.red()) && 00359 (l.green() == r.green()) && 00360 (l.blue() == r.blue()); 00361 } 00362 00363 /// component-wise not equal 00364 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1, 00365 class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2> 00366 inline 00367 bool 00368 operator!=(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & l, 00369 RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r) 00370 { 00371 return (l.red() != r.red()) || 00372 (l.green() != r.green()) || 00373 (l.blue() != r.blue()); 00374 } 00375 00376 00377 //@} 00378 00379 /********************************************************/ 00380 /* */ 00381 /* RGBValue-Traits */ 00382 /* */ 00383 /********************************************************/ 00384 00385 /** \page RGBValueTraits Numeric and Promote Traits of RGBValue 00386 The numeric and promote traits for RGBValues follow 00387 the general specifications for \ref NumericPromotionTraits. 00388 They are implemented in terms of the traits of the basic types by 00389 partial template specialization. Note that PromoteTraits are only defined 00390 for the case that the color indices are the same in both RGBValues. 00391 00392 \code 00393 00394 template <class T, unsigned int R, unsigned int G, unsigned int B> 00395 struct NumericTraits<RGBValue<T, R, G, B> > 00396 { 00397 typedef RGBValue<T, R, G, B> Type; 00398 typedef RGBValue<typename NumericTraits<T>::Promote, R, G, B> Promote; 00399 typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> RealPromote; 00400 typedef RGBValue<typename NumericTraits<T>::ComplexPromote, R, G, B> ComplexPromote; 00401 typedef T ValueType; 00402 00403 typedef typename NumericTraits<T>::isIntegral isIntegral; 00404 typedef VigraFalseType isScalar; 00405 typedef typename NumericTraits<T>::isSigned isSigned; 00406 00407 // etc. 00408 }; 00409 00410 template <class T, unsigned int R, unsigned int G, unsigned int B> 00411 struct NormTraits<RGBValue<T, R, G, B> > 00412 { 00413 typedef RGBValue<T, R, G, B> Type; 00414 typedef typename Type::SquaredNormType SquaredNormType; 00415 typedef typename Type::NormType NormType; 00416 }; 00417 00418 template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2> 00419 struct PromoteTraits<RGBValue<T1, R, G, B>, RGBValue<T2, R, G, B> > 00420 { 00421 typedef RGBValue<typename PromoteTraits<T1, T2>::Promote, R, G, B> Promote; 00422 }; 00423 00424 template <class T, unsigned int R, unsigned int G, unsigned int B> 00425 struct PromoteTraits<RGBValue<T, R, G, B>, double > 00426 { 00427 typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote; 00428 }; 00429 00430 template <class T, unsigned int R, unsigned int G, unsigned int B> 00431 struct PromoteTraits<double, RGBValue<T, R, G, B> > 00432 { 00433 typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote; 00434 }; 00435 \endcode 00436 00437 <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br> 00438 Namespace: vigra 00439 00440 */ 00441 00442 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION) 00443 00444 template <class T, unsigned int R, unsigned int G, unsigned int B> 00445 struct NumericTraits<RGBValue<T, R, G, B> > 00446 { 00447 typedef RGBValue<T, R, G, B> Type; 00448 typedef RGBValue<typename NumericTraits<T>::Promote, R, G, B> Promote; 00449 typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> RealPromote; 00450 typedef RGBValue<typename NumericTraits<T>::ComplexPromote, R, G, B> ComplexPromote; 00451 typedef T ValueType; 00452 00453 typedef typename NumericTraits<T>::isIntegral isIntegral; 00454 typedef VigraFalseType isScalar; 00455 typedef typename NumericTraits<T>::isSigned isSigned; 00456 typedef VigraFalseType isOrdered; 00457 typedef VigraFalseType isComplex; 00458 00459 static Type zero() { 00460 return Type(NumericTraits<T>::zero()); 00461 } 00462 static Type one() { 00463 return Type(NumericTraits<T>::one()); 00464 } 00465 static Type nonZero() { 00466 return Type(NumericTraits<T>::nonZero()); 00467 } 00468 00469 static Promote toPromote(Type const & v) { 00470 return Promote(v); 00471 } 00472 static RealPromote toRealPromote(Type const & v) { 00473 return RealPromote(v); 00474 } 00475 static Type fromPromote(Promote const & v) { 00476 return Type(NumericTraits<T>::fromPromote(v.red()), 00477 NumericTraits<T>::fromPromote(v.green()), 00478 NumericTraits<T>::fromPromote(v.blue())); 00479 } 00480 static Type fromRealPromote(RealPromote const & v) { 00481 return Type(NumericTraits<T>::fromRealPromote(v.red()), 00482 NumericTraits<T>::fromRealPromote(v.green()), 00483 NumericTraits<T>::fromRealPromote(v.blue())); 00484 } 00485 }; 00486 00487 template <class T, unsigned int R, unsigned int G, unsigned int B> 00488 struct NormTraits<RGBValue<T, R, G, B> > 00489 { 00490 typedef RGBValue<T, R, G, B> Type; 00491 typedef typename Type::SquaredNormType SquaredNormType; 00492 typedef typename Type::NormType NormType; 00493 }; 00494 00495 template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2> 00496 struct PromoteTraits<RGBValue<T1, R, G, B>, RGBValue<T2, R, G, B> > 00497 { 00498 typedef RGBValue<typename PromoteTraits<T1, T2>::Promote, R, G, B> Promote; 00499 }; 00500 00501 template <class T, unsigned int R, unsigned int G, unsigned int B> 00502 struct PromoteTraits<RGBValue<T, R, G, B>, double > 00503 { 00504 typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote; 00505 }; 00506 00507 template <class T, unsigned int R, unsigned int G, unsigned int B> 00508 struct PromoteTraits<double, RGBValue<T, R, G, B> > 00509 { 00510 typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote; 00511 }; 00512 00513 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION 00514 00515 #define RGBVALUE_NUMTRAITS(T) \ 00516 template<>\ 00517 struct NumericTraits<RGBValue<T, 0, 1, 2> >\ 00518 {\ 00519 typedef RGBValue<T> Type; \ 00520 typedef RGBValue<NumericTraits<T>::Promote> Promote; \ 00521 typedef RGBValue<NumericTraits<T>::RealPromote> RealPromote; \ 00522 typedef RGBValue<NumericTraits<T>::ComplexPromote> ComplexPromote; \ 00523 typedef T ValueType; \ 00524 \ 00525 typedef NumericTraits<T>::isIntegral isIntegral; \ 00526 typedef VigraFalseType isScalar; \ 00527 typedef NumericTraits<T>::isSigned isSigned; \ 00528 typedef VigraFalseType isOrdered; \ 00529 typedef VigraFalseType isComplex; \ 00530 \ 00531 static RGBValue<T> zero() { \ 00532 return RGBValue<T>(NumericTraits<T>::zero()); \ 00533 }\ 00534 static RGBValue<T> one() { \ 00535 return RGBValue<T>(NumericTraits<T>::one()); \ 00536 }\ 00537 static RGBValue<T> nonZero() { \ 00538 return RGBValue<T>(NumericTraits<T>::nonZero()); \ 00539 }\ 00540 \ 00541 static Promote toPromote(RGBValue<T> const & v) { \ 00542 return Promote(v); \ 00543 }\ 00544 static RealPromote toRealPromote(RGBValue<T> const & v) { \ 00545 return RealPromote(v); \ 00546 }\ 00547 static RGBValue<T> fromPromote(Promote const & v) { \ 00548 RGBValue<T> res;\ 00549 RGBValue<T>::iterator d = res.begin();\ 00550 Promote::const_iterator s = v.begin();\ 00551 for(; d != res.end(); ++d, ++s)\ 00552 *d = NumericTraits<T>::fromPromote(*s);\ 00553 return res;\ 00554 }\ 00555 static RGBValue<T> fromRealPromote(RealPromote const & v) {\ 00556 RGBValue<T> res;\ 00557 RGBValue<T>::iterator d = res.begin();\ 00558 RealPromote::const_iterator s = v.begin();\ 00559 for(; d != res.end(); ++d, ++s)\ 00560 *d = NumericTraits<T>::fromRealPromote(*s);\ 00561 return res;\ 00562 }\ 00563 }; \ 00564 template<>\ 00565 struct NormTraits<RGBValue<T, 0, 1, 2> >\ 00566 {\ 00567 typedef RGBValue<T> Type;\ 00568 typedef Type::SquaredNormType SquaredNormType; \ 00569 typedef Type::NormType NormType; \ 00570 }; 00571 00572 #define RGBVALUE_PROMTRAITS1(type1) \ 00573 template<> \ 00574 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, RGBValue<type1, 0, 1, 2> > \ 00575 { \ 00576 typedef RGBValue<PromoteTraits<type1, type1>::Promote> Promote; \ 00577 static Promote toPromote(RGBValue<type1> const & v) { \ 00578 return static_cast<Promote>(v); } \ 00579 }; \ 00580 template <> \ 00581 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, double > \ 00582 { \ 00583 typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \ 00584 }; \ 00585 template <> \ 00586 struct PromoteTraits<double, RGBValue<type1, 0, 1, 2> > \ 00587 { \ 00588 typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \ 00589 }; 00590 00591 #define RGBVALUE_PROMTRAITS2(type1, type2) \ 00592 template<> \ 00593 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, RGBValue<type2, 0, 1, 2> > \ 00594 { \ 00595 typedef RGBValue<PromoteTraits<type1, type2>::Promote> Promote; \ 00596 static Promote toPromote(RGBValue<type1> const & v) { \ 00597 return static_cast<Promote>(v); } \ 00598 static Promote toPromote(RGBValue<type2> const & v) { \ 00599 return static_cast<Promote>(v); } \ 00600 }; 00601 00602 RGBVALUE_NUMTRAITS(unsigned char) 00603 RGBVALUE_NUMTRAITS(int) 00604 RGBVALUE_NUMTRAITS(float) 00605 RGBVALUE_NUMTRAITS(double) 00606 RGBVALUE_PROMTRAITS1(unsigned char) 00607 RGBVALUE_PROMTRAITS1(int) 00608 RGBVALUE_PROMTRAITS1(float) 00609 RGBVALUE_PROMTRAITS1(double) 00610 RGBVALUE_PROMTRAITS2(float, unsigned char) 00611 RGBVALUE_PROMTRAITS2(unsigned char, float) 00612 RGBVALUE_PROMTRAITS2(int, unsigned char) 00613 RGBVALUE_PROMTRAITS2(unsigned char, int) 00614 RGBVALUE_PROMTRAITS2(int, float) 00615 RGBVALUE_PROMTRAITS2(float, int) 00616 RGBVALUE_PROMTRAITS2(double, unsigned char) 00617 RGBVALUE_PROMTRAITS2(unsigned char, double) 00618 RGBVALUE_PROMTRAITS2(int, double) 00619 RGBVALUE_PROMTRAITS2(double, int) 00620 RGBVALUE_PROMTRAITS2(double, float) 00621 RGBVALUE_PROMTRAITS2(float, double) 00622 00623 #undef RGBVALUE_NUMTRAITS 00624 #undef RGBVALUE_PROMTRAITS1 00625 #undef RGBVALUE_PROMTRAITS2 00626 00627 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION 00628 00629 00630 /********************************************************/ 00631 /* */ 00632 /* RGBValue-Arithmetic */ 00633 /* */ 00634 /********************************************************/ 00635 00636 /** \addtogroup RGBValueOperators 00637 */ 00638 //@{ 00639 /// componentwise add-assignment 00640 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1, 00641 class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2> 00642 inline 00643 RGBValue<V1, RIDX1, GIDX1, BIDX1> & 00644 operator+=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l, 00645 RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r) 00646 { 00647 l.red() += r.red(); 00648 l.green() += r.green(); 00649 l.blue() += r.blue(); 00650 return l; 00651 } 00652 00653 /// componentwise subtract-assignment 00654 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1, 00655 class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2> 00656 inline 00657 RGBValue<V1, RIDX1, GIDX1, BIDX1> & 00658 operator-=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l, 00659 RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r) 00660 { 00661 l.red() -= r.red(); 00662 l.green() -= r.green(); 00663 l.blue() -= r.blue(); 00664 return l; 00665 } 00666 00667 /// componentwise multiply-assignment 00668 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1, 00669 class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2> 00670 inline 00671 RGBValue<V1, RIDX1, GIDX1, BIDX1> & 00672 operator*=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l, 00673 RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r) 00674 { 00675 l.red() *= r.red(); 00676 l.green() *= r.green(); 00677 l.blue() *= r.blue(); 00678 return l; 00679 } 00680 00681 /// componentwise scalar multiply-assignment 00682 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> 00683 inline 00684 RGBValue<V, RIDX, GIDX, BIDX> & 00685 operator*=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r) 00686 { 00687 l.red() *= r; 00688 l.green() *= r; 00689 l.blue() *= r; 00690 return l; 00691 } 00692 00693 /// componentwise scalar divide-assignment 00694 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> 00695 inline 00696 RGBValue<V, RIDX, GIDX, BIDX> & 00697 operator/=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r) 00698 { 00699 l.red() /= r; 00700 l.green() /= r; 00701 l.blue() /= r; 00702 return l; 00703 } 00704 00705 using VIGRA_CSTD::abs; 00706 00707 /// component-wise absolute value 00708 template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> 00709 inline 00710 RGBValue<T, RIDX, GIDX, BIDX> 00711 abs(RGBValue<T, RIDX, GIDX, BIDX> const & v) 00712 { 00713 return RGBValue<T, RIDX, GIDX, BIDX>(abs(v.red()), abs(v.green()), abs(v.blue())); 00714 } 00715 00716 /// component-wise addition 00717 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2> 00718 inline 00719 typename PromoteTraits<RGBValue<V1, R, G, B>, 00720 RGBValue<V2, R, G, B> >::Promote 00721 operator+(RGBValue<V1, R, G, B> const & r1, 00722 RGBValue<V2, R, G, B> const & r2) 00723 { 00724 typename PromoteTraits<RGBValue<V1, R, G, B>, 00725 RGBValue<V2, R, G, B> >::Promote res(r1); 00726 00727 res += r2; 00728 00729 return res; 00730 } 00731 00732 /// component-wise subtraction 00733 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2> 00734 inline 00735 typename PromoteTraits<RGBValue<V1, R, G, B>, 00736 RGBValue<V2, R, G, B> >::Promote 00737 operator-(RGBValue<V1, R, G, B> const & r1, 00738 RGBValue<V2, R, G, B> const & r2) 00739 { 00740 typename PromoteTraits<RGBValue<V1, R, G, B>, 00741 RGBValue<V2, R, G, B> >::Promote res(r1); 00742 00743 res -= r2; 00744 00745 return res; 00746 } 00747 00748 /// component-wise multiplication 00749 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2> 00750 inline 00751 typename PromoteTraits<RGBValue<V1, R, G, B>, 00752 RGBValue<V2, R, G, B> >::Promote 00753 operator*(RGBValue<V1, R, G, B> const & r1, 00754 RGBValue<V2, R, G, B> const & r2) 00755 { 00756 typename PromoteTraits<RGBValue<V1, R, G, B>, 00757 RGBValue<V2, R, G, B> >::Promote res(r1); 00758 00759 res *= r2; 00760 00761 return res; 00762 } 00763 00764 /// component-wise left scalar multiplication 00765 template <class V, unsigned int R, unsigned int G, unsigned int B> 00766 inline 00767 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote 00768 operator*(double v, RGBValue<V, R, G, B> const & r) 00769 { 00770 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r); 00771 00772 res *= v; 00773 00774 return res; 00775 } 00776 00777 /// component-wise right scalar multiplication 00778 template <class V, unsigned int R, unsigned int G, unsigned int B> 00779 inline 00780 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote 00781 operator*(RGBValue<V, R, G, B> const & r, double v) 00782 { 00783 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r); 00784 00785 res *= v; 00786 00787 return res; 00788 } 00789 00790 /// component-wise scalar division 00791 template <class V, unsigned int R, unsigned int G, unsigned int B> 00792 inline 00793 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote 00794 operator/(RGBValue<V, R, G, B> const & r, double v) 00795 { 00796 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r); 00797 00798 res /= v; 00799 00800 return res; 00801 } 00802 00803 /// cross product 00804 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2> 00805 inline 00806 typename PromoteTraits<RGBValue<V1, R, G, B>, 00807 RGBValue<V2, R, G, B> >::Promote 00808 cross(RGBValue<V1, R, G, B> const & r1, 00809 RGBValue<V2, R, G, B> const & r2) 00810 { 00811 typedef typename PromoteTraits<RGBValue<V1, R, G, B>, 00812 RGBValue<V2, R, G, B> >::Promote 00813 Res; 00814 00815 return Res(r1.green()*r2.blue() - r1.blue()*r2.green(), 00816 r1.blue()*r2.red() - r1.red()*r2.blue(), 00817 r1.red()*r2.green() - r1.green()*r2.red()); 00818 } 00819 00820 /// dot product 00821 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1, 00822 class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2> 00823 inline 00824 typename PromoteTraits<V1, V2>::Promote 00825 dot(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & r1, 00826 RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r2) 00827 { 00828 return r1.red()*r2.red() + r1.green()*r2.green() + r1.blue()*r2.blue(); 00829 } 00830 00831 using VIGRA_CSTD::ceil; 00832 00833 /** Apply ceil() function to each RGB component. 00834 */ 00835 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> 00836 inline 00837 RGBValue<V, RIDX, GIDX, BIDX> 00838 ceil(RGBValue<V, RIDX, GIDX, BIDX> const & r) 00839 { 00840 return RGBValue<V, RIDX, GIDX, BIDX>(ceil(r.red()), 00841 ceil(r.green()), 00842 ceil(r.blue())); 00843 } 00844 00845 using VIGRA_CSTD::floor; 00846 00847 /** Apply floor() function to each RGB component. 00848 */ 00849 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX> 00850 inline 00851 RGBValue<V, RIDX, GIDX, BIDX> 00852 floor(RGBValue<V, RIDX, GIDX, BIDX> const & r) 00853 { 00854 return RGBValue<V, RIDX, GIDX, BIDX>(floor(r.red()), 00855 floor(r.green()), 00856 floor(r.blue())); 00857 } 00858 00859 //@} 00860 00861 /********************************************************/ 00862 /* */ 00863 /* RGBValue-Accessors */ 00864 /* */ 00865 /********************************************************/ 00866 00867 /** \addtogroup DataAccessors 00868 */ 00869 //@{ 00870 /** \defgroup RGBValueAccessors Accessors for RGBValue */ 00871 //@{ 00872 /** Encapsulate access to rgb values. 00873 00874 <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br> 00875 Namespace: vigra 00876 */ 00877 template <class RGBVALUE> 00878 class RGBAccessor 00879 : public VectorAccessor<RGBVALUE> 00880 { 00881 public: 00882 00883 typedef typename RGBVALUE::value_type component_type; 00884 00885 /** Get value of the red component 00886 */ 00887 template <class RGBIterator> 00888 component_type const & red(RGBIterator const & rgb) const 00889 { 00890 return (*rgb).red(); 00891 } 00892 00893 template <class V, class RGBIterator> 00894 void setRGB(V r, V g, V b, RGBIterator const & rgb) const 00895 { 00896 (*rgb).setRGB( r, g, b ); 00897 } 00898 00899 00900 /** Set value of the red component. The type <TT>V</TT> of the passed 00901 in <TT>value</TT> is automatically converted to <TT>component_type</TT>. 00902 */ 00903 template <class V, class RGBIterator> 00904 void setRed(V value, RGBIterator const & rgb) const 00905 { 00906 (*rgb).setRed(value); 00907 } 00908 00909 /** Get value of the red component at an offset 00910 */ 00911 template <class RGBIterator, class DIFFERENCE> 00912 component_type const & red(RGBIterator const & rgb, DIFFERENCE diff) const 00913 { 00914 return rgb[diff].red(); 00915 } 00916 00917 /** Set value of the red component at an offset. The type <TT>V</TT> of the passed 00918 in <TT>value</TT> is automatically converted to <TT>component_type</TT>. 00919 */ 00920 template <class V, class RGBIterator, class DIFFERENCE> 00921 void setRed(V value, RGBIterator const & rgb, DIFFERENCE diff) const 00922 { 00923 rgb[diff].setRed(value); 00924 } 00925 00926 /** Get value of the green component 00927 */ 00928 template <class RGBIterator> 00929 component_type const & green(RGBIterator const & rgb) const 00930 { 00931 return (*rgb).green(); 00932 } 00933 00934 /** Set value of the green component. The type <TT>V</TT> of the passed 00935 in <TT>value</TT> is automatically converted to <TT>component_type</TT>. 00936 */ 00937 template <class V, class RGBIterator> 00938 void setGreen(V value, RGBIterator const & rgb) const 00939 { 00940 (*rgb).setGreen(value); 00941 } 00942 00943 /** Get value of the green component at an offset 00944 */ 00945 template <class RGBIterator, class DIFFERENCE> 00946 component_type const & green(RGBIterator const & rgb, DIFFERENCE d) const 00947 { 00948 return rgb[d].green(); 00949 } 00950 00951 /** Set value of the green component at an offset. The type <TT>V</TT> of the passed 00952 in <TT>value</TT> is automatically converted to <TT>component_type</TT>. 00953 */ 00954 template <class V, class RGBIterator, class DIFFERENCE> 00955 void setGreen(V value, RGBIterator const & rgb, DIFFERENCE d) const 00956 { 00957 rgb[d].setGreen(value); 00958 } 00959 00960 /** Get value of the blue component 00961 */ 00962 template <class RGBIterator> 00963 component_type const & blue(RGBIterator const & rgb) const 00964 { 00965 return (*rgb).blue(); 00966 } 00967 00968 /** Set value of the blue component. The type <TT>V</TT> of the passed 00969 in <TT>value</TT> is automatically converted to <TT>component_type</TT>. 00970 */ 00971 template <class V, class RGBIterator> 00972 void setBlue(V value, RGBIterator const & rgb) const 00973 { 00974 (*rgb).setBlue(value); 00975 } 00976 00977 /** Get value of the blue component at an offset 00978 */ 00979 template <class RGBIterator, class DIFFERENCE> 00980 component_type const & blue(RGBIterator const & rgb, DIFFERENCE d) const 00981 { 00982 return rgb[d].blue(); 00983 } 00984 00985 /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed 00986 in <TT>value</TT> is automatically converted to <TT>component_type</TT>. 00987 */ 00988 template <class V, class RGBIterator, class DIFFERENCE> 00989 void setBlue(V value, RGBIterator const & rgb, DIFFERENCE d) const 00990 { 00991 rgb[d].setBlue(value); 00992 } 00993 00994 }; 00995 00996 00997 /********************************************************/ 00998 /* */ 00999 /* RedAccessor */ 01000 /* */ 01001 /********************************************************/ 01002 01003 /** Encapsulate access to red band of an rgb value. 01004 01005 <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br> 01006 Namespace: vigra 01007 */ 01008 template <class RGBVALUE> 01009 class RedAccessor 01010 { 01011 public: 01012 typedef typename RGBVALUE::value_type value_type; 01013 01014 /** Get value of the red component 01015 */ 01016 template <class ITERATOR> 01017 value_type const & operator()(ITERATOR const & i) const { 01018 return (*i).red(); 01019 } 01020 01021 /** Get value of the red component at an offset 01022 */ 01023 template <class ITERATOR, class DIFFERENCE> 01024 value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const 01025 { 01026 return i[d].red(); 01027 } 01028 01029 /** Set value of the red component. The type <TT>V</TT> of the passed 01030 in <TT>value</TT> is automatically converted to <TT>value_type</TT>. 01031 */ 01032 template <class V, class ITERATOR> 01033 void set(V value, ITERATOR const & i) const { 01034 (*i).setRed(value); 01035 } 01036 01037 01038 /** Set value of the red component at an offset. The type <TT>V</TT> of the passed 01039 in <TT>value</TT> is automatically converted to <TT>value_type</TT>. 01040 */ 01041 template <class V, class ITERATOR, class DIFFERENCE> 01042 void set(V value, ITERATOR const & i, DIFFERENCE d) const 01043 { 01044 i[d].setRed(value); 01045 } 01046 }; 01047 01048 /********************************************************/ 01049 /* */ 01050 /* GreenAccessor */ 01051 /* */ 01052 /********************************************************/ 01053 01054 /** Encapsulate access to green band of an rgb value. 01055 01056 <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br> 01057 Namespace: vigra 01058 */ 01059 template <class RGBVALUE> 01060 class GreenAccessor 01061 { 01062 public: 01063 typedef typename RGBVALUE::value_type value_type; 01064 01065 /** Get value of the green component 01066 */ 01067 template <class ITERATOR> 01068 value_type const & operator()(ITERATOR const & i) const { 01069 return (*i).green(); 01070 } 01071 01072 /** Get value of the green component at an offset 01073 */ 01074 template <class ITERATOR, class DIFFERENCE> 01075 value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const 01076 { 01077 return i[d].green(); 01078 } 01079 01080 /** Set value of the green component. The type <TT>V</TT> of the passed 01081 in <TT>value</TT> is automatically converted to <TT>value_type</TT>. 01082 */ 01083 template <class V, class ITERATOR> 01084 void set(V value, ITERATOR const & i) const { 01085 (*i).setGreen(value); 01086 } 01087 01088 01089 /** Set value of the green component at an offset. The type <TT>V</TT> of the passed 01090 in <TT>value</TT> is automatically converted to <TT>value_type</TT>. 01091 */ 01092 template <class V, class ITERATOR, class DIFFERENCE> 01093 void set(V value, ITERATOR const & i, DIFFERENCE d) const 01094 { 01095 i[d].setGreen(value); 01096 } 01097 }; 01098 01099 /********************************************************/ 01100 /* */ 01101 /* BlueAccessor */ 01102 /* */ 01103 /********************************************************/ 01104 01105 /** Encapsulate access to blue band of an rgb value. 01106 01107 <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br> 01108 Namespace: vigra 01109 */ 01110 template <class RGBVALUE> 01111 class BlueAccessor 01112 { 01113 public: 01114 typedef typename RGBVALUE::value_type value_type; 01115 01116 /** Get value of the blue component 01117 */ 01118 template <class ITERATOR> 01119 value_type const & operator()(ITERATOR const & i) const { 01120 return (*i).blue(); 01121 } 01122 01123 /** Get value of the blue component at an offset 01124 */ 01125 template <class ITERATOR, class DIFFERENCE> 01126 value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const 01127 { 01128 return i[d].blue(); 01129 } 01130 01131 /** Set value of the blue component. The type <TT>V</TT> of the passed 01132 in <TT>value</TT> is automatically converted to <TT>value_type</TT>. 01133 */ 01134 template <class V, class ITERATOR> 01135 void set(V value, ITERATOR const & i) const { 01136 (*i).setBlue(value); 01137 } 01138 01139 01140 /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed 01141 in <TT>value</TT> is automatically converted to <TT>value_type</TT>. 01142 */ 01143 template <class V, class ITERATOR, class DIFFERENCE> 01144 void set(V value, ITERATOR const & i, DIFFERENCE d) const 01145 { 01146 i[d].setBlue(value); 01147 } 01148 }; 01149 01150 /********************************************************/ 01151 /* */ 01152 /* RGBToGrayAccessor */ 01153 /* */ 01154 /********************************************************/ 01155 01156 /** Encapsulate access to luminance of an rgb value. 01157 01158 <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br> 01159 Namespace: vigra 01160 */ 01161 template <class RGBVALUE> 01162 class RGBToGrayAccessor 01163 { 01164 public: 01165 typedef typename RGBVALUE::value_type value_type; 01166 01167 /** Get value of the luminance 01168 */ 01169 template <class ITERATOR> 01170 value_type operator()(ITERATOR const & i) const { 01171 return (*i).luminance(); } 01172 01173 /** Get value of the luminance at an offset 01174 */ 01175 template <class ITERATOR, class DIFFERENCE> 01176 value_type operator()(ITERATOR const & i, DIFFERENCE d) const 01177 { 01178 return i[d].luminance(); 01179 } 01180 }; 01181 01182 01183 /********************************************************/ 01184 /* */ 01185 /* GrayToRGBAccessor */ 01186 /* */ 01187 /********************************************************/ 01188 01189 /** Create an RGB view for a grayscale image by making all three channels 01190 equal. 01191 01192 <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br> 01193 Namespace: vigra 01194 */ 01195 template <class VALUETYPE> 01196 class GrayToRGBAccessor 01197 { 01198 public: 01199 typedef typename vigra::RGBValue<VALUETYPE> value_type; 01200 01201 /** Get RGB value for the given pixel. 01202 */ 01203 template <class ITERATOR> 01204 value_type operator()(ITERATOR const & i) const { 01205 return value_type(*i,*i,*i); } 01206 01207 /** Get RGB value at an offset 01208 */ 01209 template <class ITERATOR, class DIFFERENCE> 01210 value_type operator()(ITERATOR const & i, DIFFERENCE d) const 01211 { 01212 return value_type(i[d],i[d],i[d]); 01213 } 01214 }; 01215 01216 01217 //@} 01218 //@} 01219 01220 01221 } // namespace vigra 01222 01223 #endif // VIGRA_RGBVALUE_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|