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