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

details vigra/rgbvalue.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
00005 /*                                                                      */
00006 /*    This file is part of the VIGRA computer vision library.           */
00007 /*    ( Version 1.5.0, Dec 07 2006 )                                    */
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 /*        koethe@informatik.uni-hamburg.de          or                  */
00012 /*        vigra@kogs1.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 LinearAlgebra.
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 <b>\#include</b> "<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>
00340 
00341     These functions fulfill the requirements of a Linear Algebra.
00342     Return types are determined according to \ref RGBValueTraits.
00343 
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 BIDX1, unsigned int GIDX1, class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
00668 inline
00669 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
00670 operator*=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
00671            RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
00672 {
00673     l.red() *= r.red();
00674     l.green() *= r.green();
00675     l.blue() *= r.blue();
00676     return l;
00677 }
00678 
00679     /// componentwise scalar multiply-assignment
00680 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
00681 inline
00682 RGBValue<V, RIDX, GIDX, BIDX> &
00683 operator*=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
00684 {
00685     l.red() *= r;
00686     l.green() *= r;
00687     l.blue() *= r;
00688     return l;
00689 }
00690 
00691     /// componentwise scalar divide-assignment
00692 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
00693 inline
00694 RGBValue<V, RIDX, GIDX, BIDX> &
00695 operator/=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
00696 {
00697     l.red() /= r;
00698     l.green() /= r;
00699     l.blue() /= r;
00700     return l;
00701 }
00702 
00703 using VIGRA_CSTD::abs;
00704 
00705     /// component-wise absolute value
00706 template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
00707 inline
00708 RGBValue<T, RIDX, GIDX, BIDX>
00709 abs(RGBValue<T, RIDX, GIDX, BIDX> const & v)
00710 {
00711   return RGBValue<T, RIDX, GIDX, BIDX>(abs(v.red()), abs(v.green()), abs(v.blue()));
00712 }
00713 
00714     /// component-wise addition
00715 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
00716 inline
00717 typename PromoteTraits<RGBValue<V1, R, G, B>,
00718                        RGBValue<V2, R, G, B> >::Promote
00719 operator+(RGBValue<V1, R, G, B> const & r1,
00720           RGBValue<V2, R, G, B> const & r2)
00721 {
00722     typename PromoteTraits<RGBValue<V1, R, G, B>,
00723                            RGBValue<V2, R, G, B> >::Promote res(r1);
00724 
00725     res += r2;
00726 
00727     return res;
00728 }
00729 
00730     /// component-wise subtraction
00731 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
00732 inline
00733 typename PromoteTraits<RGBValue<V1, R, G, B>,
00734                        RGBValue<V2, R, G, B> >::Promote
00735 operator-(RGBValue<V1, R, G, B> const & r1,
00736           RGBValue<V2, R, G, B> const & r2)
00737 {
00738     typename PromoteTraits<RGBValue<V1, R, G, B>,
00739                            RGBValue<V2, R, G, B> >::Promote res(r1);
00740 
00741     res -= r2;
00742 
00743     return res;
00744 }
00745 
00746     /// component-wise multiplication
00747 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
00748 inline
00749 typename PromoteTraits<RGBValue<V1, R, G, B>,
00750                        RGBValue<V2, R, G, B> >::Promote
00751 operator*(RGBValue<V1, R, G, B> const & r1,
00752           RGBValue<V2, R, G, B> const & r2)
00753 {
00754     typename PromoteTraits<RGBValue<V1, R, G, B>,
00755                            RGBValue<V2, R, G, B> >::Promote res(r1);
00756 
00757     res *= r2;
00758 
00759     return res;
00760 }
00761 
00762     /// component-wise left scalar multiplication
00763 template <class V, unsigned int R, unsigned int G, unsigned int B>
00764 inline
00765 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
00766 operator*(double v, RGBValue<V, R, G, B> const & r)
00767 {
00768     typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
00769 
00770     res *= v;
00771 
00772     return res;
00773 }
00774 
00775     /// component-wise right scalar multiplication
00776 template <class V, unsigned int R, unsigned int G, unsigned int B>
00777 inline
00778 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
00779 operator*(RGBValue<V, R, G, B> const & r, double v)
00780 {
00781     typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
00782 
00783     res *= v;
00784 
00785     return res;
00786 }
00787 
00788     /// component-wise scalar division
00789 template <class V, unsigned int R, unsigned int G, unsigned int B>
00790 inline
00791 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
00792 operator/(RGBValue<V, R, G, B> const & r, double v)
00793 {
00794     typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
00795 
00796     res /= v;
00797 
00798     return res;
00799 }
00800 
00801     /// cross product
00802 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
00803 inline
00804 typename PromoteTraits<RGBValue<V1, R, G, B>,
00805                        RGBValue<V2, R, G, B> >::Promote
00806 cross(RGBValue<V1, R, G, B> const & r1,
00807       RGBValue<V2, R, G, B> const & r2)
00808 {
00809     typedef typename PromoteTraits<RGBValue<V1, R, G, B>,
00810                                    RGBValue<V2, R, G, B> >::Promote
00811             Res;
00812 
00813     return  Res(r1.green()*r2.blue() - r1.blue()*r2.green(),
00814                 r1.blue()*r2.red() - r1.red()*r2.blue(),
00815                 r1.red()*r2.green() - r1.green()*r2.red());
00816 }
00817 
00818     /// dot product
00819 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
00820           class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
00821 inline
00822 typename PromoteTraits<V1, V2>::Promote
00823 dot(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & r1,
00824     RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r2)
00825 {
00826     return r1.red()*r2.red() + r1.green()*r2.green() + r1.blue()*r2.blue();
00827 }
00828 
00829 using VIGRA_CSTD::ceil;
00830 
00831     /** Apply ceil() function to each RGB component.
00832     */
00833 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
00834 inline
00835 RGBValue<V, RIDX, GIDX, BIDX>
00836 ceil(RGBValue<V, RIDX, GIDX, BIDX> const & r)
00837 {
00838     return RGBValue<V, RIDX, GIDX, BIDX>(ceil(r.red()),
00839                                          ceil(r.green()),
00840                                          ceil(r.blue()));
00841 }
00842 
00843 using VIGRA_CSTD::floor;
00844 
00845     /** Apply floor() function to each RGB component.
00846     */
00847 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
00848 inline
00849 RGBValue<V, RIDX, GIDX, BIDX>
00850 floor(RGBValue<V, RIDX, GIDX, BIDX> const & r)
00851 {
00852     return RGBValue<V, RIDX, GIDX, BIDX>(floor(r.red()),
00853                                          floor(r.green()),
00854                                          floor(r.blue()));
00855 }
00856 
00857 //@}
00858 
00859 /********************************************************/
00860 /*                                                      */
00861 /*                      RGBValue-Accessors              */
00862 /*                                                      */
00863 /********************************************************/
00864 
00865 /** \addtogroup DataAccessors
00866 */
00867 //@{
00868 /** \defgroup RGBValueAccessors Accessors for RGBValue */
00869 //@{
00870     /** Encapsulate access to rgb values.
00871 
00872     <b>\#include</b> "<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>"<br>
00873     Namespace: vigra
00874     */
00875 template <class RGBVALUE>
00876 class RGBAccessor
00877 : public VectorAccessor<RGBVALUE>
00878 {
00879   public:
00880 
00881     typedef typename RGBVALUE::value_type component_type;
00882 
00883         /** Get value of the red component
00884         */
00885     template <class RGBIterator>
00886     component_type const & red(RGBIterator const & rgb) const
00887     {
00888         return (*rgb).red();
00889     }
00890 
00891     template <class V, class RGBIterator>
00892     void setRGB(V r, V g, V b, RGBIterator const & rgb) const
00893     {
00894         (*rgb).setRGB( r, g, b );
00895     }
00896 
00897 
00898         /** Set value of the red component. The type <TT>V</TT> of the passed
00899             in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
00900         */
00901     template <class V, class RGBIterator>
00902     void setRed(V value, RGBIterator const & rgb) const
00903     {
00904         (*rgb).setRed(value);
00905     }
00906 
00907         /** Get value of the red component at an offset
00908         */
00909     template <class RGBIterator, class DIFFERENCE>
00910     component_type const & red(RGBIterator const & rgb, DIFFERENCE diff) const
00911     {
00912         return rgb[diff].red();
00913     }
00914 
00915         /** Set value of the red component at an offset. The type <TT>V</TT> of the passed
00916             in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
00917         */
00918     template <class V, class RGBIterator, class DIFFERENCE>
00919     void setRed(V value, RGBIterator const & rgb, DIFFERENCE diff) const
00920     {
00921         rgb[diff].setRed(value);
00922     }
00923 
00924         /** Get value of the green component
00925         */
00926     template <class RGBIterator>
00927     component_type const & green(RGBIterator const & rgb) const
00928     {
00929         return (*rgb).green();
00930     }
00931 
00932         /** Set value of the green component. The type <TT>V</TT> of the passed
00933             in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
00934         */
00935     template <class V, class RGBIterator>
00936     void setGreen(V value, RGBIterator const & rgb) const
00937     {
00938         (*rgb).setGreen(value);
00939     }
00940 
00941         /** Get value of the green component at an offset
00942         */
00943     template <class RGBIterator, class DIFFERENCE>
00944     component_type const & green(RGBIterator const & rgb, DIFFERENCE d) const
00945     {
00946         return rgb[d].green();
00947     }
00948 
00949         /** Set value of the green component at an offset. The type <TT>V</TT> of the passed
00950             in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
00951         */
00952     template <class V, class RGBIterator, class DIFFERENCE>
00953     void setGreen(V value, RGBIterator const & rgb, DIFFERENCE d) const
00954     {
00955         rgb[d].setGreen(value);
00956     }
00957 
00958         /** Get value of the blue component
00959         */
00960     template <class RGBIterator>
00961     component_type const & blue(RGBIterator const & rgb) const
00962     {
00963         return (*rgb).blue();
00964     }
00965 
00966         /** Set value of the blue component. The type <TT>V</TT> of the passed
00967             in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
00968         */
00969     template <class V, class RGBIterator>
00970     void setBlue(V value, RGBIterator const & rgb) const
00971     {
00972         (*rgb).setBlue(value);
00973     }
00974 
00975         /** Get value of the blue component at an offset
00976         */
00977     template <class RGBIterator, class DIFFERENCE>
00978     component_type const & blue(RGBIterator const & rgb, DIFFERENCE d) const
00979     {
00980         return rgb[d].blue();
00981     }
00982 
00983         /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed
00984             in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
00985         */
00986     template <class V, class RGBIterator, class DIFFERENCE>
00987     void setBlue(V value, RGBIterator const & rgb, DIFFERENCE d) const
00988     {
00989         rgb[d].setBlue(value);
00990     }
00991 
00992 };
00993 
00994 
00995 /********************************************************/
00996 /*                                                      */
00997 /*                       RedAccessor                    */
00998 /*                                                      */
00999 /********************************************************/
01000 
01001     /** Encapsulate access to red band of an rgb value.
01002 
01003     <b>\#include</b> "<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>"<br>
01004     Namespace: vigra
01005     */
01006 template <class RGBVALUE>
01007 class RedAccessor
01008 {
01009   public:
01010     typedef typename RGBVALUE::value_type value_type;
01011 
01012         /** Get value of the red component
01013         */
01014     template <class ITERATOR>
01015     value_type const & operator()(ITERATOR const & i) const {
01016         return (*i).red();
01017     }
01018 
01019         /** Get value of the red component at an offset
01020         */
01021     template <class ITERATOR, class DIFFERENCE>
01022     value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
01023     {
01024         return i[d].red();
01025     }
01026 
01027         /** Set value of the red component. The type <TT>V</TT> of the passed
01028             in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
01029         */
01030     template <class V, class ITERATOR>
01031     void set(V value, ITERATOR const & i) const {
01032         (*i).setRed(value);
01033     }
01034 
01035 
01036         /** Set value of the red component at an offset. The type <TT>V</TT> of the passed
01037             in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
01038         */
01039     template <class V, class ITERATOR, class DIFFERENCE>
01040     void set(V value, ITERATOR const & i, DIFFERENCE d) const
01041     {
01042         i[d].setRed(value);
01043     }
01044 };
01045 
01046 /********************************************************/
01047 /*                                                      */
01048 /*                     GreenAccessor                    */
01049 /*                                                      */
01050 /********************************************************/
01051 
01052     /** Encapsulate access to green band of an rgb value.
01053 
01054     <b>\#include</b> "<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>"<br>
01055     Namespace: vigra
01056     */
01057 template <class RGBVALUE>
01058 class GreenAccessor
01059 {
01060   public:
01061     typedef typename RGBVALUE::value_type value_type;
01062 
01063         /** Get value of the green component
01064         */
01065     template <class ITERATOR>
01066     value_type const & operator()(ITERATOR const & i) const {
01067         return (*i).green();
01068     }
01069 
01070         /** Get value of the green component at an offset
01071         */
01072     template <class ITERATOR, class DIFFERENCE>
01073     value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
01074     {
01075         return i[d].green();
01076     }
01077 
01078         /** Set value of the green component. The type <TT>V</TT> of the passed
01079             in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
01080         */
01081     template <class V, class ITERATOR>
01082     void set(V value, ITERATOR const & i) const {
01083         (*i).setGreen(value);
01084     }
01085 
01086 
01087         /** Set value of the green component at an offset. The type <TT>V</TT> of the passed
01088             in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
01089         */
01090     template <class V, class ITERATOR, class DIFFERENCE>
01091     void set(V value, ITERATOR const & i, DIFFERENCE d) const
01092     {
01093         i[d].setGreen(value);
01094     }
01095 };
01096 
01097 /********************************************************/
01098 /*                                                      */
01099 /*                     BlueAccessor                     */
01100 /*                                                      */
01101 /********************************************************/
01102 
01103     /** Encapsulate access to blue band of an rgb value.
01104 
01105     <b>\#include</b> "<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>"<br>
01106     Namespace: vigra
01107     */
01108 template <class RGBVALUE>
01109 class BlueAccessor
01110 {
01111   public:
01112     typedef typename RGBVALUE::value_type value_type;
01113 
01114         /** Get value of the blue component
01115         */
01116     template <class ITERATOR>
01117     value_type const & operator()(ITERATOR const & i) const {
01118         return (*i).blue();
01119     }
01120 
01121         /** Get value of the blue component at an offset
01122         */
01123     template <class ITERATOR, class DIFFERENCE>
01124     value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
01125     {
01126         return i[d].blue();
01127     }
01128 
01129         /** Set value of the blue component. The type <TT>V</TT> of the passed
01130             in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
01131         */
01132     template <class V, class ITERATOR>
01133     void set(V value, ITERATOR const & i) const {
01134         (*i).setBlue(value);
01135     }
01136 
01137 
01138         /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed
01139             in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
01140         */
01141     template <class V, class ITERATOR, class DIFFERENCE>
01142     void set(V value, ITERATOR const & i, DIFFERENCE d) const
01143     {
01144         i[d].setBlue(value);
01145     }
01146 };
01147 
01148 /********************************************************/
01149 /*                                                      */
01150 /*                  RGBToGrayAccessor                   */
01151 /*                                                      */
01152 /********************************************************/
01153 
01154     /** Encapsulate access to luminance of an rgb value.
01155 
01156     <b>\#include</b> "<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>"<br>
01157     Namespace: vigra
01158     */
01159 template <class RGBVALUE>
01160 class RGBToGrayAccessor
01161 {
01162   public:
01163     typedef typename RGBVALUE::value_type value_type;
01164 
01165         /** Get value of the luminance
01166         */
01167     template <class ITERATOR>
01168     value_type operator()(ITERATOR const & i) const {
01169                 return (*i).luminance(); }
01170 
01171         /** Get value of the luminance at an offset
01172         */
01173     template <class ITERATOR, class DIFFERENCE>
01174     value_type operator()(ITERATOR const & i, DIFFERENCE d) const
01175     {
01176         return i[d].luminance();
01177     }
01178 };
01179 
01180 
01181 /********************************************************/
01182 /*                                                      */
01183 /*                  GrayToRGBAccessor                   */
01184 /*                                                      */
01185 /********************************************************/
01186 
01187     /** Create an RGB view for a grayscale image by making all three channels
01188         equal.
01189 
01190     <b>\#include</b> "<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>"<br>
01191     Namespace: vigra
01192     */
01193 template <class VALUETYPE>
01194 class GrayToRGBAccessor
01195 {
01196    public:
01197      typedef typename vigra::RGBValue<VALUETYPE> value_type;
01198 
01199          /** Get RGB value for the given pixel.
01200          */
01201      template <class ITERATOR>
01202      value_type operator()(ITERATOR const & i) const {
01203                  return value_type(*i,*i,*i); }
01204 
01205          /** Get RGB value at an offset
01206          */
01207      template <class ITERATOR, class DIFFERENCE>
01208      value_type operator()(ITERATOR const & i, DIFFERENCE d) const
01209      {
01210          return value_type(i[d],i[d],i[d]);
01211      }
01212 };
01213 
01214 
01215 //@}
01216 //@}
01217 
01218 
01219 } // namespace vigra
01220 
01221 #endif // VIGRA_RGBVALUE_HXX

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

html generated using doxygen and Python
VIGRA 1.5.0 (7 Dec 2006)