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

rgbvalue.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 
37 #ifndef VIGRA_RGBVALUE_HXX
38 #define VIGRA_RGBVALUE_HXX
39 
40 #include <cmath> // abs(double)
41 #include <cstdlib> // abs(int)
42 #include "config.hxx"
43 #include "numerictraits.hxx"
44 #include "accessor.hxx"
45 #include "tinyvector.hxx"
46 #include "static_assert.hxx"
47 
48 namespace vigra {
49 
50 namespace detail {
51 
52 template <unsigned int I, unsigned int R, unsigned int G, unsigned int B>
53 struct SelectColorIndexRHS;
54 
55 template <unsigned int R, unsigned int G, unsigned int B>
56 struct SelectColorIndexRHS<0, R, G, B>
57 {
58  enum { res = R };
59 };
60 
61 template <unsigned int R, unsigned int G, unsigned int B>
62 struct SelectColorIndexRHS<1, R, G, B>
63 {
64  enum { res = G };
65 };
66 
67 template <unsigned int R, unsigned int G, unsigned int B>
68 struct SelectColorIndexRHS<2, R, G, B>
69 {
70  enum { res = B };
71 };
72 
73 } // namespace detail
74 
75 #ifndef DOXYGEN
76 
77 template <unsigned int R, unsigned int G, unsigned int B>
78 struct RGBValue_bad_color_indices
79 : staticAssert::AssertBool<(R < 3 && G < 3 && B < 3 &&
80  ((1 << R) + (1 << G) + (1 << B) == 7))>
81 {};
82 
83 #endif /* DOXYGEN */
84 
85 
86 /********************************************************/
87 /* */
88 /* RGBValue */
89 /* */
90 /********************************************************/
91 
92 /** \brief Class for a single RGB value.
93 
94  This class contains three values (of the specified type) that represent
95  red, green, and blue color channels. By means of the template parameters
96  <tt>RED_IDX, GREEN_IDX, BLUE_IDX</tt>, the indices 0, 1, 2 can be assigned to
97  the three colors arbitrarily, so that, for example, a BGR type can be created
98  as
99 
100  \code
101  typedef RGBValue<unsigned char, 2,1,0> BGRValue;
102  \endcode
103 
104  The standard order red=0, green=1, blue=2 is the default. There are three possibilities
105  to access the color values: accessor functions (\ref red(), \ref green(),
106  \ref blue()), index operator (operator[](dx), where the <tt>rgb[RED_IDX]</tt>
107  returns red etc.) and iterator (STL-compatible random access
108  iterator that references the three colors in turn). The latter two
109  methods, together with the necessary embedded typedefs, ensure
110  compatibility of a RGBValue with a STL vector.
111 
112  \ref RGBValueOperators "Arithmetic operations" are defined as component-wise applications of these
113  operations. Addition, subtraction, and multiplication of two RGBValues
114  (+=, -=, *=, +, -, *, unary -), multiplication and division of an
115  RGBValue with a double, and NumericTraits/PromoteTraits are defined,
116  so that RGBValue fulfills the requirements of a \ref LinearAlgebraConcept "Linear Algebra".
117 
118  A number of \ref RGBValueAccessors "accessors" are provided
119  that support access to RGBValues as a whole, to a selected
120  color component, or to the luminance value.
121 
122  <b>\#include</b> <vigra/rgbvalue.hxx><br>
123  Namespace: vigra
124 */
125 template <class VALUETYPE, unsigned int RED_IDX = 0, unsigned int GREEN_IDX = 1, unsigned int BLUE_IDX = 2>
126 class RGBValue
127 : public TinyVector<VALUETYPE, 3>
128 {
129  typedef TinyVector<VALUETYPE, 3> Base;
130 
131  // inverse mapping from index to color
132  enum {
133  IDX0 = (RED_IDX == 0) ? 0 : (GREEN_IDX == 0) ? 1 : 2,
134  IDX1 = (RED_IDX == 1) ? 0 : (GREEN_IDX == 1) ? 1 : 2,
135  IDX2 = (RED_IDX == 2) ? 0 : (GREEN_IDX == 2) ? 1 : 2
136  };
137 
138  public:
139  /** STL-compatible definition of valuetype
140  */
141  typedef typename Base::value_type value_type;
142  /** STL-compatible definition of iterator
143  */
144  typedef typename Base::iterator iterator;
145  /** STL-compatible definition of const iterator
146  */
147  typedef typename Base::const_iterator const_iterator;
148  /** squared norm type (result of squaredManitude())
149  */
150  typedef typename Base::SquaredNormType SquaredNormType;
151  /** norm type (result of magnitude())
152  */
153  typedef typename Base::NormType NormType;
154 
155  typedef typename Base::reference reference;
156  typedef typename Base::const_reference const_reference;
157  typedef typename Base::pointer pointer;
158  typedef typename Base::const_pointer const_pointer;
159  typedef typename Base::size_type size_type;
160  typedef typename Base::difference_type difference_type;
161  typedef typename Base::scalar_multiplier scalar_multiplier;
162  typedef typename Base::ReverseCopyTag ReverseCopyTag;
163 
164  /** Color index positions
165  */
166  enum
167  {
168  RedIdx = RED_IDX,
169  GreenIdx = GREEN_IDX,
170  BlueIdx = BLUE_IDX
171  };
172 
173  /** Construct from explicit color values.
174  \a first, \a second, \a third are written in this order,
175  irrespective of how the color indices are specified.
176  */
177  RGBValue(value_type first, value_type second, value_type third)
178  : Base(first, second, third)
179  {
180  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
181  }
182 
183  /** Construct gray value.
184  */
185  RGBValue(value_type gray)
186  : Base(gray, gray, gray)
187  {
188  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
189  }
190 
191  /** Copy from raw memory. The order is preserved,
192  irrespective of how the color indices are specified.
193  */
194  explicit RGBValue(const_pointer i)
195  : Base(i)
196  {
197  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
198  }
199 
200  /** Construct by reverse copying from raw memory.
201  */
202  RGBValue(const_pointer i, ReverseCopyTag reverse)
203  : Base(i, reverse)
204  {
205  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
206  }
207 
208  /** Default constructor (sets all components to 0)
209  */
210  RGBValue()
211  : Base(0, 0, 0)
212  {
213  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
214  }
215 
216 #if !defined(TEMPLATE_COPY_CONSTRUCTOR_BUG)
217 
218  RGBValue(RGBValue const & r)
219  : Base((Base const &)r)
220  {
221  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
222  }
223 
224  RGBValue & operator=(RGBValue const & r)
225  {
226  Base::operator=(r);
227  return *this;
228  }
229 
230 #endif // TEMPLATE_COPY_CONSTRUCTOR_BUG
231 
232  /** Copy constructor.
233  */
234  template <class U, unsigned int R, unsigned int G, unsigned int B>
235  RGBValue(RGBValue<U, R, G, B> const & r)
236  : Base(detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX0, R, G, B>::res]),
237  detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX1, R, G, B>::res]),
238  detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX2, R, G, B>::res]))
239  {
240  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
241  }
242 
243  /** Copy assignment.
244  */
245  template <class U, unsigned int R, unsigned int G, unsigned int B>
246  RGBValue & operator=(RGBValue<U, R, G, B> const & r)
247  {
248  setRed(detail::RequiresExplicitCast<value_type>::cast(r.red()));
249  setGreen(detail::RequiresExplicitCast<value_type>::cast(r.green()));
250  setBlue(detail::RequiresExplicitCast<value_type>::cast(r.blue()));
251  return *this;
252  }
253 
254  /** construct from TinyVector
255  */
256  RGBValue(TinyVector<value_type, 3> const & r)
257  : Base(r)
258  {
259  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
260  }
261 
262  /** assign TinyVector.
263  */
264  RGBValue & operator=(TinyVector<value_type, 3> const & r)
265  {
266  Base::operator=(r);
267  return *this;
268  }
269 
270  /** Unary negation (construct RGBValue with negative values)
271  */
272  RGBValue operator-() const
273  {
274  return RGBValue(-(*this)[0], -(*this)[1], -(*this)[2]);
275  }
276 
277  /** Access red component.
278  */
279  value_type & red() { return (*this)[RED_IDX]; }
280 
281  /** Access green component.
282  */
283  value_type & green() { return (*this)[GREEN_IDX]; }
284 
285  /** Access blue component.
286  */
287  value_type & blue() { return (*this)[BLUE_IDX]; }
288 
289  /** Get red component.
290  */
291  value_type const & red() const { return (*this)[RED_IDX]; }
292 
293  /** Get green component.
294  */
295  value_type const & green() const { return (*this)[GREEN_IDX]; }
296 
297  /** Get blue component.
298  */
299  value_type const & blue() const { return (*this)[BLUE_IDX]; }
300 
301  /** Calculate luminance.
302  */
303  value_type luminance() const {
304  return detail::RequiresExplicitCast<value_type>::cast(0.3*red() + 0.59*green() + 0.11*blue()); }
305 
306  /** Calculate magnitude.
307  */
308  NormType magnitude() const {
309  return Base::magnitude();
310  }
311 
312  /** Calculate squared magnitude.
313  */
314  SquaredNormType squaredMagnitude() const {
315  return Base::squaredMagnitude();
316  }
317 
318  /** Set red component. The type <TT>V</TT> of the passed
319  in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
320  */
321  template <class V>
322  void setRed(V value) { (*this)[RED_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); }
323 
324  /** Set green component.The type <TT>V</TT> of the passed
325  in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
326  */
327  template <class V>
328  void setGreen(V value) { (*this)[GREEN_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); }
329 
330  /** Set blue component.The type <TT>V</TT> of the passed
331  in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
332  */
333  template <class V>
334  void setBlue(V value) { (*this)[BLUE_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); }
335 
336 
337  template <class V>
338  void setRGB(V r, V g, V b)
339  {
340  (*this)[RED_IDX] = detail::RequiresExplicitCast<value_type>::cast(r);
341  (*this)[GREEN_IDX] = detail::RequiresExplicitCast<value_type>::cast(g);
342  (*this)[BLUE_IDX] = detail::RequiresExplicitCast<value_type>::cast(b);
343  }
344 };
345 
346 /********************************************************/
347 /* */
348 /* RGBValue Comparison */
349 /* */
350 /********************************************************/
351 
352 /** \addtogroup RGBValueOperators Functions for RGBValue
353 
354  \brief Implement basic arithmetic and equality for RGBValue.
355 
356  These functions fulfill the requirements of a Linear Algebra.
357  Return types are determined according to \ref RGBValueTraits.
358 
359  <b>\#include</b> <vigra/rgbvalue.hxx><br>
360  Namespace: vigra
361  <p>
362 
363  */
364 //@{
365  /// component-wise equal
366 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
367  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
368 inline
369 bool
370 operator==(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & l,
371  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
372 {
373  return (l.red() == r.red()) &&
374  (l.green() == r.green()) &&
375  (l.blue() == r.blue());
376 }
377 
378  /// component-wise not equal
379 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
380  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
381 inline
382 bool
383 operator!=(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & l,
384  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
385 {
386  return (l.red() != r.red()) ||
387  (l.green() != r.green()) ||
388  (l.blue() != r.blue());
389 }
390 
391 
392 //@}
393 
394 /********************************************************/
395 /* */
396 /* RGBValue-Traits */
397 /* */
398 /********************************************************/
399 
400 /** \page RGBValueTraits Numeric and Promote Traits of RGBValue
401  The numeric and promote traits for RGBValues follow
402  the general specifications for \ref NumericPromotionTraits.
403  They are implemented in terms of the traits of the basic types by
404  partial template specialization. Note that PromoteTraits are only defined
405  for the case that the color indices are the same in both RGBValues.
406 
407  \code
408 
409  template <class T, unsigned int R, unsigned int G, unsigned int B>
410  struct NumericTraits<RGBValue<T, R, G, B> >
411  {
412  typedef RGBValue<T, R, G, B> Type;
413  typedef RGBValue<typename NumericTraits<T>::Promote, R, G, B> Promote;
414  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> RealPromote;
415  typedef RGBValue<typename NumericTraits<T>::ComplexPromote, R, G, B> ComplexPromote;
416  typedef T ValueType;
417 
418  typedef typename NumericTraits<T>::isIntegral isIntegral;
419  typedef VigraFalseType isScalar;
420  typedef typename NumericTraits<T>::isSigned isSigned;
421 
422  // etc.
423  };
424 
425  template <class T, unsigned int R, unsigned int G, unsigned int B>
426  struct NormTraits<RGBValue<T, R, G, B> >
427  {
428  typedef RGBValue<T, R, G, B> Type;
429  typedef typename Type::SquaredNormType SquaredNormType;
430  typedef typename Type::NormType NormType;
431  };
432 
433  template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2>
434  struct PromoteTraits<RGBValue<T1, R, G, B>, RGBValue<T2, R, G, B> >
435  {
436  typedef RGBValue<typename PromoteTraits<T1, T2>::Promote, R, G, B> Promote;
437  };
438 
439  template <class T, unsigned int R, unsigned int G, unsigned int B>
440  struct PromoteTraits<RGBValue<T, R, G, B>, double >
441  {
442  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
443  };
444 
445  template <class T, unsigned int R, unsigned int G, unsigned int B>
446  struct PromoteTraits<double, RGBValue<T, R, G, B> >
447  {
448  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
449  };
450  \endcode
451 
452  <b>\#include</b> <vigra/rgbvalue.hxx><br>
453  Namespace: vigra
454 
455 */
456 
457 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
458 
459 template <class T, unsigned int R, unsigned int G, unsigned int B>
460 struct NumericTraits<RGBValue<T, R, G, B> >
461 {
462  typedef RGBValue<T, R, G, B> Type;
463  typedef RGBValue<typename NumericTraits<T>::Promote, R, G, B> Promote;
464  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> RealPromote;
465  typedef RGBValue<typename NumericTraits<T>::ComplexPromote, R, G, B> ComplexPromote;
466  typedef T ValueType;
467 
468  typedef typename NumericTraits<T>::isIntegral isIntegral;
469  typedef VigraFalseType isScalar;
470  typedef typename NumericTraits<T>::isSigned isSigned;
471  typedef VigraTrueType isOrdered;
472  typedef VigraFalseType isComplex;
473 
474  static Type zero()
475  {
476  return Type(NumericTraits<T>::zero());
477  }
478  static Type one()
479  {
480  return Type(NumericTraits<T>::one());
481  }
482  static Type nonZero()
483  {
484  return Type(NumericTraits<T>::nonZero());
485  }
486 
487  static Type min()
488  {
489  return Type(NumericTraits<T>::min());
490  }
491  static Type max()
492  {
493  return Type(NumericTraits<T>::max());
494  }
495 
496  static Promote toPromote(Type const & v)
497  {
498  return Promote(v);
499  }
500  static RealPromote toRealPromote(Type const & v)
501  {
502  return RealPromote(v);
503  }
504  static Type fromPromote(Promote const & v)
505  {
506  return Type(NumericTraits<T>::fromPromote(v.red()),
507  NumericTraits<T>::fromPromote(v.green()),
508  NumericTraits<T>::fromPromote(v.blue()));
509  }
510  static Type fromRealPromote(RealPromote const & v)
511  {
512  return Type(NumericTraits<T>::fromRealPromote(v.red()),
513  NumericTraits<T>::fromRealPromote(v.green()),
514  NumericTraits<T>::fromRealPromote(v.blue()));
515  }
516 };
517 
518 template <class T, unsigned int R, unsigned int G, unsigned int B>
519 struct NormTraits<RGBValue<T, R, G, B> >
520 {
521  typedef RGBValue<T, R, G, B> Type;
522  typedef typename Type::SquaredNormType SquaredNormType;
523  typedef typename Type::NormType NormType;
524 };
525 
526 template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2>
527 struct PromoteTraits<RGBValue<T1, R, G, B>, RGBValue<T2, R, G, B> >
528 {
529  typedef RGBValue<typename PromoteTraits<T1, T2>::Promote, R, G, B> Promote;
530 };
531 
532 template <class T, unsigned int R, unsigned int G, unsigned int B>
533 struct PromoteTraits<RGBValue<T, R, G, B>, double >
534 {
535  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
536 };
537 
538 template <class T, unsigned int R, unsigned int G, unsigned int B>
539 struct PromoteTraits<double, RGBValue<T, R, G, B> >
540 {
541  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
542 };
543 
544 template<class T, unsigned int R, unsigned int G, unsigned int B>
545 struct CanSkipInitialization<RGBValue<T, R, G, B> >
546 {
547  typedef typename CanSkipInitialization<T>::type type;
548  static const bool value = type::asBool;
549 };
550 
551 
552 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
553 
554 #define RGBVALUE_NUMTRAITS(T) \
555 template<>\
556 struct NumericTraits<RGBValue<T, 0, 1, 2> >\
557 {\
558  typedef RGBValue<T> Type; \
559  typedef RGBValue<NumericTraits<T>::Promote> Promote; \
560  typedef RGBValue<NumericTraits<T>::RealPromote> RealPromote; \
561  typedef RGBValue<NumericTraits<T>::ComplexPromote> ComplexPromote; \
562  typedef T ValueType; \
563  \
564  typedef NumericTraits<T>::isIntegral isIntegral; \
565  typedef VigraFalseType isScalar; \
566  typedef NumericTraits<T>::isSigned isSigned; \
567  typedef VigraFalseType isOrdered; \
568  typedef VigraFalseType isComplex; \
569  \
570  static RGBValue<T> zero() { \
571  return RGBValue<T>(NumericTraits<T>::zero()); \
572  }\
573  static RGBValue<T> one() { \
574  return RGBValue<T>(NumericTraits<T>::one()); \
575  }\
576  static RGBValue<T> nonZero() { \
577  return RGBValue<T>(NumericTraits<T>::nonZero()); \
578  }\
579  \
580  static Promote toPromote(RGBValue<T> const & v) { \
581  return Promote(v); \
582  }\
583  static RealPromote toRealPromote(RGBValue<T> const & v) { \
584  return RealPromote(v); \
585  }\
586  static RGBValue<T> fromPromote(Promote const & v) { \
587  RGBValue<T> res;\
588  RGBValue<T>::iterator d = res.begin();\
589  Promote::const_iterator s = v.begin();\
590  for(; d != res.end(); ++d, ++s)\
591  *d = NumericTraits<T>::fromPromote(*s);\
592  return res;\
593  }\
594  static RGBValue<T> fromRealPromote(RealPromote const & v) {\
595  RGBValue<T> res;\
596  RGBValue<T>::iterator d = res.begin();\
597  RealPromote::const_iterator s = v.begin();\
598  for(; d != res.end(); ++d, ++s)\
599  *d = NumericTraits<T>::fromRealPromote(*s);\
600  return res;\
601  }\
602 }; \
603 template<>\
604 struct NormTraits<RGBValue<T, 0, 1, 2> >\
605 {\
606  typedef RGBValue<T> Type;\
607  typedef Type::SquaredNormType SquaredNormType; \
608  typedef Type::NormType NormType; \
609 };
610 
611 #define RGBVALUE_PROMTRAITS1(type1) \
612 template<> \
613 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, RGBValue<type1, 0, 1, 2> > \
614 { \
615  typedef RGBValue<PromoteTraits<type1, type1>::Promote> Promote; \
616  static Promote toPromote(RGBValue<type1> const & v) { \
617  return static_cast<Promote>(v); } \
618 }; \
619 template <> \
620 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, double > \
621 { \
622  typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \
623 }; \
624 template <> \
625 struct PromoteTraits<double, RGBValue<type1, 0, 1, 2> > \
626 { \
627  typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \
628 };
629 
630 #define RGBVALUE_PROMTRAITS2(type1, type2) \
631 template<> \
632 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, RGBValue<type2, 0, 1, 2> > \
633 { \
634  typedef RGBValue<PromoteTraits<type1, type2>::Promote> Promote; \
635  static Promote toPromote(RGBValue<type1> const & v) { \
636  return static_cast<Promote>(v); } \
637  static Promote toPromote(RGBValue<type2> const & v) { \
638  return static_cast<Promote>(v); } \
639 };
640 
641 RGBVALUE_NUMTRAITS(unsigned char)
642 RGBVALUE_NUMTRAITS(int)
643 RGBVALUE_NUMTRAITS(float)
644 RGBVALUE_NUMTRAITS(double)
645 RGBVALUE_PROMTRAITS1(unsigned char)
646 RGBVALUE_PROMTRAITS1(int)
647 RGBVALUE_PROMTRAITS1(float)
648 RGBVALUE_PROMTRAITS1(double)
649 RGBVALUE_PROMTRAITS2(float, unsigned char)
650 RGBVALUE_PROMTRAITS2(unsigned char, float)
651 RGBVALUE_PROMTRAITS2(int, unsigned char)
652 RGBVALUE_PROMTRAITS2(unsigned char, int)
653 RGBVALUE_PROMTRAITS2(int, float)
654 RGBVALUE_PROMTRAITS2(float, int)
655 RGBVALUE_PROMTRAITS2(double, unsigned char)
656 RGBVALUE_PROMTRAITS2(unsigned char, double)
657 RGBVALUE_PROMTRAITS2(int, double)
658 RGBVALUE_PROMTRAITS2(double, int)
659 RGBVALUE_PROMTRAITS2(double, float)
660 RGBVALUE_PROMTRAITS2(float, double)
661 
662 #undef RGBVALUE_NUMTRAITS
663 #undef RGBVALUE_PROMTRAITS1
664 #undef RGBVALUE_PROMTRAITS2
665 
666 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
667 
668 
669 /********************************************************/
670 /* */
671 /* RGBValue-Arithmetic */
672 /* */
673 /********************************************************/
674 
675 /** \addtogroup RGBValueOperators
676  */
677 //@{
678  /// componentwise add-assignment
679 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
680  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
681 inline
682 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
683 operator+=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
684  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
685 {
686  l.red() += r.red();
687  l.green() += r.green();
688  l.blue() += r.blue();
689  return l;
690 }
691 
692  /// componentwise subtract-assignment
693 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
694  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
695 inline
696 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
697 operator-=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
698  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
699 {
700  l.red() -= r.red();
701  l.green() -= r.green();
702  l.blue() -= r.blue();
703  return l;
704 }
705 
706  /// componentwise multiply-assignment
707 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
708  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
709 inline
710 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
711 operator*=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
712  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
713 {
714  l.red() = V1(l.red() * r.red());
715  l.green() = V1(l.green() * r.green());
716  l.blue() = V1(l.blue() * r.blue());
717  return l;
718 }
719 
720  /// componentwise scalar multiply-assignment
721 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
722 inline
723 RGBValue<V, RIDX, GIDX, BIDX> &
724 operator*=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
725 {
726  l.red() = V(l.red() * r);
727  l.green() = V(l.green() * r);
728  l.blue() = V(l.blue() * r);
729  return l;
730 }
731 
732  /// componentwise divide-assignment
733 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
734  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
735 inline
736 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
737 operator/=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
738  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
739 {
740  l.red() = V1(l.red() / r.red());
741  l.green() = V1(l.green() / r.green());
742  l.blue() = V1(l.blue() / r.blue());
743  return l;
744 }
745 
746  /// componentwise scalar divide-assignment
747 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
748 inline
749 RGBValue<V, RIDX, GIDX, BIDX> &
750 operator/=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
751 {
752  l.red() = V(l.red() / r);
753  l.green() = V(l.green() / r);
754  l.blue() = V(l.blue() / r);
755  return l;
756 }
757 
758 using VIGRA_CSTD::abs;
759 
760  /// component-wise absolute value
761 template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
762 inline
763 RGBValue<T, RIDX, GIDX, BIDX>
764 abs(RGBValue<T, RIDX, GIDX, BIDX> const & v)
765 {
766  return RGBValue<T, RIDX, GIDX, BIDX>(abs(v.red()), abs(v.green()), abs(v.blue()));
767 }
768 
769  /// component-wise addition
770 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
771 inline
772 typename PromoteTraits<RGBValue<V1, R, G, B>,
773  RGBValue<V2, R, G, B> >::Promote
774 operator+(RGBValue<V1, R, G, B> const & r1,
775  RGBValue<V2, R, G, B> const & r2)
776 {
777  typename PromoteTraits<RGBValue<V1, R, G, B>,
778  RGBValue<V2, R, G, B> >::Promote res(r1);
779 
780  res += r2;
781 
782  return res;
783 }
784 
785  /// component-wise subtraction
786 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
787 inline
788 typename PromoteTraits<RGBValue<V1, R, G, B>,
789  RGBValue<V2, R, G, B> >::Promote
790 operator-(RGBValue<V1, R, G, B> const & r1,
791  RGBValue<V2, R, G, B> const & r2)
792 {
793  typename PromoteTraits<RGBValue<V1, R, G, B>,
794  RGBValue<V2, R, G, B> >::Promote res(r1);
795 
796  res -= r2;
797 
798  return res;
799 }
800 
801  /// component-wise multiplication
802 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
803 inline
804 typename PromoteTraits<RGBValue<V1, R, G, B>,
805  RGBValue<V2, R, G, B> >::Promote
806 operator*(RGBValue<V1, R, G, B> const & r1,
807  RGBValue<V2, R, G, B> const & r2)
808 {
809  typename PromoteTraits<RGBValue<V1, R, G, B>,
810  RGBValue<V2, R, G, B> >::Promote res(r1);
811 
812  res *= r2;
813 
814  return res;
815 }
816 
817  /// component-wise left scalar multiplication
818 template <class V, unsigned int R, unsigned int G, unsigned int B>
819 inline
820 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
821 operator*(double v, RGBValue<V, R, G, B> const & r)
822 {
823  typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
824 
825  res *= v;
826 
827  return res;
828 }
829 
830  /// component-wise right scalar multiplication
831 template <class V, unsigned int R, unsigned int G, unsigned int B>
832 inline
833 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
834 operator*(RGBValue<V, R, G, B> const & r, double v)
835 {
836  typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
837 
838  res *= v;
839 
840  return res;
841 }
842 
843  /// component-wise division
844 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
845 inline
846 typename PromoteTraits<RGBValue<V1, R, G, B>,
847  RGBValue<V2, R, G, B> >::Promote
848 operator/(RGBValue<V1, R, G, B> const & r1,
849  RGBValue<V2, R, G, B> const & r2)
850 {
851  typename PromoteTraits<RGBValue<V1, R, G, B>,
852  RGBValue<V2, R, G, B> >::Promote res(r1);
853 
854  res /= r2;
855 
856  return res;
857 }
858 
859  /// component-wise scalar division
860 template <class V, unsigned int R, unsigned int G, unsigned int B>
861 inline
862 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
863 operator/(RGBValue<V, R, G, B> const & r, double v)
864 {
865  typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
866 
867  res /= v;
868 
869  return res;
870 }
871 
872  /// cross product
873 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
874 inline
875 typename PromoteTraits<RGBValue<V1, R, G, B>,
876  RGBValue<V2, R, G, B> >::Promote
877 cross(RGBValue<V1, R, G, B> const & r1,
878  RGBValue<V2, R, G, B> const & r2)
879 {
880  typedef typename PromoteTraits<RGBValue<V1, R, G, B>,
881  RGBValue<V2, R, G, B> >::Promote
882  Res;
883 
884  return Res(r1.green()*r2.blue() - r1.blue()*r2.green(),
885  r1.blue()*r2.red() - r1.red()*r2.blue(),
886  r1.red()*r2.green() - r1.green()*r2.red());
887 }
888 
889  /// dot product
890 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
891  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
892 inline
893 typename PromoteTraits<V1, V2>::Promote
894 dot(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & r1,
895  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r2)
896 {
897  return r1.red()*r2.red() + r1.green()*r2.green() + r1.blue()*r2.blue();
898 }
899 
900 using VIGRA_CSTD::ceil;
901 
902  /** Apply ceil() function to each RGB component.
903  */
904 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
905 inline
906 RGBValue<V, RIDX, GIDX, BIDX>
907 ceil(RGBValue<V, RIDX, GIDX, BIDX> const & r)
908 {
909  return RGBValue<V, RIDX, GIDX, BIDX>(ceil(r.red()),
910  ceil(r.green()),
911  ceil(r.blue()));
912 }
913 
914 using VIGRA_CSTD::floor;
915 
916  /** Apply floor() function to each RGB component.
917  */
918 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
919 inline
920 RGBValue<V, RIDX, GIDX, BIDX>
921 floor(RGBValue<V, RIDX, GIDX, BIDX> const & r)
922 {
923  return RGBValue<V, RIDX, GIDX, BIDX>(floor(r.red()),
924  floor(r.green()),
925  floor(r.blue()));
926 }
927 
928 // overload min and max to avoid that std:min() and std::max() match
929 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
930 inline
931 RGBValue<V, RIDX, GIDX, BIDX>
932 min(RGBValue<V, RIDX, GIDX, BIDX> const & l,
933  RGBValue<V, RIDX, GIDX, BIDX> const & r)
934 {
935  typedef typename detail::LoopType<3>::type ltype;
936  RGBValue<V, RIDX, GIDX, BIDX> res(l);
937  ltype::min(res.begin(), r.begin());
938  return res;
939 }
940 
941 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
942 inline
943 RGBValue<V, RIDX, GIDX, BIDX>
944 max(RGBValue<V, RIDX, GIDX, BIDX> const & l,
945  RGBValue<V, RIDX, GIDX, BIDX> const & r)
946 {
947  typedef typename detail::LoopType<3>::type ltype;
948  RGBValue<V, RIDX, GIDX, BIDX> res(l);
949  ltype::max(res.begin(), r.begin());
950  return res;
951 }
952 
953 
954 //@}
955 
956 /********************************************************/
957 /* */
958 /* RGBValue-Accessors */
959 /* */
960 /********************************************************/
961 
962 /** \addtogroup DataAccessors
963 */
964 //@{
965 /** \defgroup RGBValueAccessors Accessors for RGBValue */
966 //@{
967  /** Encapsulate access to rgb values.
968 
969  <b>\#include</b> <vigra/rgbvalue.hxx><br>
970  Namespace: vigra
971  */
972 template <class RGBVALUE>
973 class RGBAccessor
974 : public VectorAccessor<RGBVALUE>
975 {
976  public:
977 
978  typedef typename RGBVALUE::value_type component_type;
979 
980  /** Get value of the red component
981  */
982  template <class RGBIterator>
983  component_type const & red(RGBIterator const & rgb) const
984  {
985  return (*rgb).red();
986  }
987 
988  template <class V, class RGBIterator>
989  void setRGB(V r, V g, V b, RGBIterator const & rgb) const
990  {
991  (*rgb).setRGB( r, g, b );
992  }
993 
994 
995  /** Set value of the red component. The type <TT>V</TT> of the passed
996  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
997  */
998  template <class V, class RGBIterator>
999  void setRed(V value, RGBIterator const & rgb) const
1000  {
1001  (*rgb).setRed(value);
1002  }
1003 
1004  /** Get value of the red component at an offset
1005  */
1006  template <class RGBIterator, class DIFFERENCE>
1007  component_type const & red(RGBIterator const & rgb, DIFFERENCE diff) const
1008  {
1009  return rgb[diff].red();
1010  }
1011 
1012  /** Set value of the red component at an offset. The type <TT>V</TT> of the passed
1013  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1014  */
1015  template <class V, class RGBIterator, class DIFFERENCE>
1016  void setRed(V value, RGBIterator const & rgb, DIFFERENCE diff) const
1017  {
1018  rgb[diff].setRed(value);
1019  }
1020 
1021  /** Get value of the green component
1022  */
1023  template <class RGBIterator>
1024  component_type const & green(RGBIterator const & rgb) const
1025  {
1026  return (*rgb).green();
1027  }
1028 
1029  /** Set value of the green component. The type <TT>V</TT> of the passed
1030  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1031  */
1032  template <class V, class RGBIterator>
1033  void setGreen(V value, RGBIterator const & rgb) const
1034  {
1035  (*rgb).setGreen(value);
1036  }
1037 
1038  /** Get value of the green component at an offset
1039  */
1040  template <class RGBIterator, class DIFFERENCE>
1041  component_type const & green(RGBIterator const & rgb, DIFFERENCE d) const
1042  {
1043  return rgb[d].green();
1044  }
1045 
1046  /** Set value of the green component at an offset. The type <TT>V</TT> of the passed
1047  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1048  */
1049  template <class V, class RGBIterator, class DIFFERENCE>
1050  void setGreen(V value, RGBIterator const & rgb, DIFFERENCE d) const
1051  {
1052  rgb[d].setGreen(value);
1053  }
1054 
1055  /** Get value of the blue component
1056  */
1057  template <class RGBIterator>
1058  component_type const & blue(RGBIterator const & rgb) const
1059  {
1060  return (*rgb).blue();
1061  }
1062 
1063  /** Set value of the blue component. The type <TT>V</TT> of the passed
1064  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1065  */
1066  template <class V, class RGBIterator>
1067  void setBlue(V value, RGBIterator const & rgb) const
1068  {
1069  (*rgb).setBlue(value);
1070  }
1071 
1072  /** Get value of the blue component at an offset
1073  */
1074  template <class RGBIterator, class DIFFERENCE>
1075  component_type const & blue(RGBIterator const & rgb, DIFFERENCE d) const
1076  {
1077  return rgb[d].blue();
1078  }
1079 
1080  /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed
1081  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1082  */
1083  template <class V, class RGBIterator, class DIFFERENCE>
1084  void setBlue(V value, RGBIterator const & rgb, DIFFERENCE d) const
1085  {
1086  rgb[d].setBlue(value);
1087  }
1088 
1089 };
1090 
1091 
1092 /********************************************************/
1093 /* */
1094 /* RedAccessor */
1095 /* */
1096 /********************************************************/
1097 
1098  /** Encapsulate access to red band of an rgb value.
1099 
1100  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1101  Namespace: vigra
1102  */
1103 template <class RGBVALUE>
1104 class RedAccessor
1105 {
1106  public:
1107  typedef typename RGBVALUE::value_type value_type;
1108 
1109  /** Get value of the red component
1110  */
1111  template <class ITERATOR>
1112  value_type const & operator()(ITERATOR const & i) const {
1113  return (*i).red();
1114  }
1115 
1116  /** Get value of the red component at an offset
1117  */
1118  template <class ITERATOR, class DIFFERENCE>
1119  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1120  {
1121  return i[d].red();
1122  }
1123 
1124  /** Set value of the red component. The type <TT>V</TT> of the passed
1125  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1126  */
1127  template <class V, class ITERATOR>
1128  void set(V value, ITERATOR const & i) const {
1129  (*i).setRed(value);
1130  }
1131 
1132 
1133  /** Set value of the red component at an offset. The type <TT>V</TT> of the passed
1134  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1135  */
1136  template <class V, class ITERATOR, class DIFFERENCE>
1137  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1138  {
1139  i[d].setRed(value);
1140  }
1141 };
1142 
1143 /********************************************************/
1144 /* */
1145 /* GreenAccessor */
1146 /* */
1147 /********************************************************/
1148 
1149  /** Encapsulate access to green band of an rgb value.
1150 
1151  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1152  Namespace: vigra
1153  */
1154 template <class RGBVALUE>
1155 class GreenAccessor
1156 {
1157  public:
1158  typedef typename RGBVALUE::value_type value_type;
1159 
1160  /** Get value of the green component
1161  */
1162  template <class ITERATOR>
1163  value_type const & operator()(ITERATOR const & i) const {
1164  return (*i).green();
1165  }
1166 
1167  /** Get value of the green component at an offset
1168  */
1169  template <class ITERATOR, class DIFFERENCE>
1170  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1171  {
1172  return i[d].green();
1173  }
1174 
1175  /** Set value of the green component. The type <TT>V</TT> of the passed
1176  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1177  */
1178  template <class V, class ITERATOR>
1179  void set(V value, ITERATOR const & i) const {
1180  (*i).setGreen(value);
1181  }
1182 
1183 
1184  /** Set value of the green component at an offset. The type <TT>V</TT> of the passed
1185  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1186  */
1187  template <class V, class ITERATOR, class DIFFERENCE>
1188  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1189  {
1190  i[d].setGreen(value);
1191  }
1192 };
1193 
1194 /********************************************************/
1195 /* */
1196 /* BlueAccessor */
1197 /* */
1198 /********************************************************/
1199 
1200  /** Encapsulate access to blue band of an rgb value.
1201 
1202  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1203  Namespace: vigra
1204  */
1205 template <class RGBVALUE>
1206 class BlueAccessor
1207 {
1208  public:
1209  typedef typename RGBVALUE::value_type value_type;
1210 
1211  /** Get value of the blue component
1212  */
1213  template <class ITERATOR>
1214  value_type const & operator()(ITERATOR const & i) const {
1215  return (*i).blue();
1216  }
1217 
1218  /** Get value of the blue component at an offset
1219  */
1220  template <class ITERATOR, class DIFFERENCE>
1221  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1222  {
1223  return i[d].blue();
1224  }
1225 
1226  /** Set value of the blue component. The type <TT>V</TT> of the passed
1227  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1228  */
1229  template <class V, class ITERATOR>
1230  void set(V value, ITERATOR const & i) const {
1231  (*i).setBlue(value);
1232  }
1233 
1234 
1235  /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed
1236  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1237  */
1238  template <class V, class ITERATOR, class DIFFERENCE>
1239  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1240  {
1241  i[d].setBlue(value);
1242  }
1243 };
1244 
1245 /********************************************************/
1246 /* */
1247 /* RGBToGrayAccessor */
1248 /* */
1249 /********************************************************/
1250 
1251  /** Encapsulate access to luminance of an rgb value.
1252 
1253  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1254  Namespace: vigra
1255  */
1256 template <class RGBVALUE>
1257 class RGBToGrayAccessor
1258 {
1259  public:
1260  typedef typename RGBVALUE::value_type value_type;
1261 
1262  /** Get value of the luminance
1263  */
1264  template <class ITERATOR>
1265  value_type operator()(ITERATOR const & i) const {
1266  return (*i).luminance(); }
1267 
1268  /** Get value of the luminance at an offset
1269  */
1270  template <class ITERATOR, class DIFFERENCE>
1271  value_type operator()(ITERATOR const & i, DIFFERENCE d) const
1272  {
1273  return i[d].luminance();
1274  }
1275 };
1276 
1277 
1278 /********************************************************/
1279 /* */
1280 /* GrayToRGBAccessor */
1281 /* */
1282 /********************************************************/
1283 
1284  /** Create an RGB view for a grayscale image by making all three channels
1285  equal.
1286 
1287  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1288  Namespace: vigra
1289  */
1290 template <class VALUETYPE>
1291 class GrayToRGBAccessor
1292 {
1293  public:
1294  typedef typename vigra::RGBValue<VALUETYPE> value_type;
1295 
1296  /** Get RGB value for the given pixel.
1297  */
1298  template <class ITERATOR>
1299  value_type operator()(ITERATOR const & i) const {
1300  return value_type(*i,*i,*i); }
1301 
1302  /** Get RGB value at an offset
1303  */
1304  template <class ITERATOR, class DIFFERENCE>
1305  value_type operator()(ITERATOR const & i, DIFFERENCE d) const
1306  {
1307  return value_type(i[d],i[d],i[d]);
1308  }
1309 };
1310 
1311 
1312 //@}
1313 //@}
1314 
1315 
1316 } // namespace vigra
1317 
1318 #endif // VIGRA_RGBVALUE_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.9.0 (Wed Feb 27 2013)