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

rgbvalue.hxx VIGRA

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 
163  /** Color index positions
164  */
165  enum
166  {
167  RedIdx = RED_IDX,
168  GreenIdx = GREEN_IDX,
169  BlueIdx = BLUE_IDX
170  };
171 
172  /** Construct from explicit color values.
173  \a first, \a second, \a third are written in this order,
174  irrespective of how the color indices are specified.
175  */
176  RGBValue(value_type first, value_type second, value_type third)
177  : Base(first, second, third)
178  {
179  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
180  }
181 
182  /** Construct gray value.
183  */
184  RGBValue(value_type gray)
185  : Base(gray, gray, gray)
186  {
187  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
188  }
189 
190  /** Copy from raw memory. The order is preserved,
191  irrespective of how the color indices are specified.
192  */
193  explicit RGBValue(const_pointer i)
194  : Base(i)
195  {
196  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
197  }
198 
199  /** Construct by reverse copying from raw memory.
200  */
201  RGBValue(const_pointer i, ReverseCopyTag reverse)
202  : Base(i, reverse)
203  {
204  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
205  }
206 
207  /** Default constructor (sets all components to 0)
208  */
209  RGBValue()
210  : Base(0, 0, 0)
211  {
212  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
213  }
214 
215 #if !defined(TEMPLATE_COPY_CONSTRUCTOR_BUG)
216 
217  RGBValue(RGBValue const & r)
218  : Base((Base const &)r)
219  {
220  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
221  }
222 
223  RGBValue & operator=(RGBValue const & r)
224  {
225  Base::operator=(r);
226  return *this;
227  }
228 
229 #endif // TEMPLATE_COPY_CONSTRUCTOR_BUG
230 
231  /** Copy constructor.
232  */
233  template <class U, unsigned int R, unsigned int G, unsigned int B>
234  RGBValue(RGBValue<U, R, G, B> const & r)
235  : Base(detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX0, R, G, B>::res]),
236  detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX1, R, G, B>::res]),
237  detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX2, R, G, B>::res]))
238  {
239  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
240  }
241 
242  /** Copy assignment.
243  */
244  template <class U, unsigned int R, unsigned int G, unsigned int B>
245  RGBValue & operator=(RGBValue<U, R, G, B> const & r)
246  {
247  setRed(detail::RequiresExplicitCast<value_type>::cast(r.red()));
248  setGreen(detail::RequiresExplicitCast<value_type>::cast(r.green()));
249  setBlue(detail::RequiresExplicitCast<value_type>::cast(r.blue()));
250  return *this;
251  }
252 
253  /** construct from TinyVector
254  */
255  RGBValue(TinyVector<value_type, 3> const & r)
256  : Base(r)
257  {
258  VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
259  }
260 
261  /** assign TinyVector.
262  */
263  RGBValue & operator=(TinyVector<value_type, 3> const & r)
264  {
265  Base::operator=(r);
266  return *this;
267  }
268 
269  /** Unary negation (construct RGBValue with negative values)
270  */
271  RGBValue operator-() const
272  {
273  return RGBValue(-(*this)[0], -(*this)[1], -(*this)[2]);
274  }
275 
276  /** Access red component.
277  */
278  value_type & red() { return (*this)[RED_IDX]; }
279 
280  /** Access green component.
281  */
282  value_type & green() { return (*this)[GREEN_IDX]; }
283 
284  /** Access blue component.
285  */
286  value_type & blue() { return (*this)[BLUE_IDX]; }
287 
288  /** Get red component.
289  */
290  value_type const & red() const { return (*this)[RED_IDX]; }
291 
292  /** Get green component.
293  */
294  value_type const & green() const { return (*this)[GREEN_IDX]; }
295 
296  /** Get blue component.
297  */
298  value_type const & blue() const { return (*this)[BLUE_IDX]; }
299 
300  /** Calculate luminance.
301  */
302  value_type luminance() const {
303  return detail::RequiresExplicitCast<value_type>::cast(0.3*red() + 0.59*green() + 0.11*blue()); }
304 
305  /** Calculate magnitude.
306  */
307  NormType magnitude() const {
308  return Base::magnitude();
309  }
310 
311  /** Calculate squared magnitude.
312  */
313  SquaredNormType squaredMagnitude() const {
314  return Base::squaredMagnitude();
315  }
316 
317  /** Set red component. The type <TT>V</TT> of the passed
318  in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
319  */
320  template <class V>
321  void setRed(V value) { (*this)[RED_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); }
322 
323  /** Set green component.The type <TT>V</TT> of the passed
324  in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
325  */
326  template <class V>
327  void setGreen(V value) { (*this)[GREEN_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); }
328 
329  /** Set blue component.The type <TT>V</TT> of the passed
330  in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
331  */
332  template <class V>
333  void setBlue(V value) { (*this)[BLUE_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); }
334 
335 
336  template <class V>
337  void setRGB(V r, V g, V b)
338  {
339  (*this)[RED_IDX] = detail::RequiresExplicitCast<value_type>::cast(r);
340  (*this)[GREEN_IDX] = detail::RequiresExplicitCast<value_type>::cast(g);
341  (*this)[BLUE_IDX] = detail::RequiresExplicitCast<value_type>::cast(b);
342  }
343 };
344 
345 /********************************************************/
346 /* */
347 /* RGBValue Comparison */
348 /* */
349 /********************************************************/
350 
351 /** \addtogroup RGBValueOperators Functions for RGBValue
352 
353  \brief Implement basic arithmetic and equality for RGBValue.
354 
355  These functions fulfill the requirements of a Linear Algebra.
356  Return types are determined according to \ref RGBValueTraits.
357 
358  <b>\#include</b> <vigra/rgbvalue.hxx><br>
359  Namespace: vigra
360  <p>
361 
362  */
363 //@{
364  /// component-wise equal
365 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
366  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
367 inline
368 bool
369 operator==(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & l,
370  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
371 {
372  return (l.red() == r.red()) &&
373  (l.green() == r.green()) &&
374  (l.blue() == r.blue());
375 }
376 
377  /// component-wise not equal
378 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
379  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
380 inline
381 bool
382 operator!=(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & l,
383  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
384 {
385  return (l.red() != r.red()) ||
386  (l.green() != r.green()) ||
387  (l.blue() != r.blue());
388 }
389 
390 template <class V, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
391  unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
392 inline
393 bool
394 closeAtTolerance(RGBValue<V, RIDX1, GIDX1, BIDX1> const & l,
395  RGBValue<V, RIDX2, GIDX2, BIDX2> const & r,
396  V epsilon = NumericTraits<V>::epsilon())
397 {
398  return closeAtTolerance(l.red(), r.red(), epsilon) &&
399  closeAtTolerance(l.green(), r.green(), epsilon) &&
400  closeAtTolerance(l.blue(), r.blue(), epsilon);
401 }
402 
403 
404 //@}
405 
406 /********************************************************/
407 /* */
408 /* RGBValue-Traits */
409 /* */
410 /********************************************************/
411 
412 /** \page RGBValueTraits Numeric and Promote Traits of RGBValue
413  The numeric and promote traits for RGBValues follow
414  the general specifications for \ref NumericPromotionTraits.
415  They are implemented in terms of the traits of the basic types by
416  partial template specialization. Note that PromoteTraits are only defined
417  for the case that the color indices are the same in both RGBValues.
418 
419  \code
420 
421  template <class T, unsigned int R, unsigned int G, unsigned int B>
422  struct NumericTraits<RGBValue<T, R, G, B> >
423  {
424  typedef RGBValue<T, R, G, B> Type;
425  typedef RGBValue<typename NumericTraits<T>::Promote, R, G, B> Promote;
426  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> RealPromote;
427  typedef RGBValue<typename NumericTraits<T>::ComplexPromote, R, G, B> ComplexPromote;
428  typedef T ValueType;
429 
430  typedef typename NumericTraits<T>::isIntegral isIntegral;
431  typedef VigraFalseType isScalar;
432  typedef typename NumericTraits<T>::isSigned isSigned;
433 
434  // etc.
435  };
436 
437  template <class T, unsigned int R, unsigned int G, unsigned int B>
438  struct NormTraits<RGBValue<T, R, G, B> >
439  {
440  typedef RGBValue<T, R, G, B> Type;
441  typedef typename Type::SquaredNormType SquaredNormType;
442  typedef typename Type::NormType NormType;
443  };
444 
445  template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2>
446  struct PromoteTraits<RGBValue<T1, R, G, B>, RGBValue<T2, R, G, B> >
447  {
448  typedef RGBValue<typename PromoteTraits<T1, T2>::Promote, R, G, B> Promote;
449  };
450 
451  template <class T, unsigned int R, unsigned int G, unsigned int B>
452  struct PromoteTraits<RGBValue<T, R, G, B>, double >
453  {
454  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
455  };
456 
457  template <class T, unsigned int R, unsigned int G, unsigned int B>
458  struct PromoteTraits<double, RGBValue<T, R, G, B> >
459  {
460  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
461  };
462  \endcode
463 
464  <b>\#include</b> <vigra/rgbvalue.hxx><br>
465  Namespace: vigra
466 
467 */
468 
469 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
470 
471 template <class T, unsigned int R, unsigned int G, unsigned int B>
472 struct NumericTraits<RGBValue<T, R, G, B> >
473 {
474  typedef RGBValue<T, R, G, B> Type;
475  typedef RGBValue<typename NumericTraits<T>::Promote, R, G, B> Promote;
476  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> RealPromote;
477  typedef RGBValue<typename NumericTraits<T>::ComplexPromote, R, G, B> ComplexPromote;
478  typedef T ValueType;
479 
480  typedef typename NumericTraits<T>::isIntegral isIntegral;
481  typedef VigraFalseType isScalar;
482  typedef typename NumericTraits<T>::isSigned isSigned;
483  typedef VigraTrueType isOrdered;
484  typedef VigraFalseType isComplex;
485 
486  static Type zero()
487  {
488  return Type(NumericTraits<T>::zero());
489  }
490  static Type one()
491  {
492  return Type(NumericTraits<T>::one());
493  }
494  static Type nonZero()
495  {
496  return Type(NumericTraits<T>::nonZero());
497  }
498 
499  static Type min()
500  {
501  return Type(NumericTraits<T>::min());
502  }
503  static Type max()
504  {
505  return Type(NumericTraits<T>::max());
506  }
507 
508  static Promote toPromote(Type const & v)
509  {
510  return Promote(v);
511  }
512  static RealPromote toRealPromote(Type const & v)
513  {
514  return RealPromote(v);
515  }
516  static Type fromPromote(Promote const & v)
517  {
518  return Type(NumericTraits<T>::fromPromote(v.red()),
519  NumericTraits<T>::fromPromote(v.green()),
520  NumericTraits<T>::fromPromote(v.blue()));
521  }
522  static Type fromRealPromote(RealPromote const & v)
523  {
524  return Type(NumericTraits<T>::fromRealPromote(v.red()),
525  NumericTraits<T>::fromRealPromote(v.green()),
526  NumericTraits<T>::fromRealPromote(v.blue()));
527  }
528 };
529 
530 template <class T, unsigned int R, unsigned int G, unsigned int B>
531 struct NormTraits<RGBValue<T, R, G, B> >
532 {
533  typedef RGBValue<T, R, G, B> Type;
534  typedef typename Type::SquaredNormType SquaredNormType;
535  typedef typename Type::NormType NormType;
536 };
537 
538 template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2>
539 struct PromoteTraits<RGBValue<T1, R, G, B>, RGBValue<T2, R, G, B> >
540 {
541  typedef RGBValue<typename PromoteTraits<T1, T2>::Promote, R, G, B> Promote;
542 };
543 
544 template <class T, unsigned int R, unsigned int G, unsigned int B>
545 struct PromoteTraits<RGBValue<T, R, G, B>, double >
546 {
547  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
548 };
549 
550 template <class T, unsigned int R, unsigned int G, unsigned int B>
551 struct PromoteTraits<double, RGBValue<T, R, G, B> >
552 {
553  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
554 };
555 
556 template<class T, unsigned int R, unsigned int G, unsigned int B>
557 struct CanSkipInitialization<RGBValue<T, R, G, B> >
558 {
559  typedef typename CanSkipInitialization<T>::type type;
560  static const bool value = type::asBool;
561 };
562 
563 
564 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
565 
566 #define RGBVALUE_NUMTRAITS(T) \
567 template<>\
568 struct NumericTraits<RGBValue<T, 0, 1, 2> >\
569 {\
570  typedef RGBValue<T> Type; \
571  typedef RGBValue<NumericTraits<T>::Promote> Promote; \
572  typedef RGBValue<NumericTraits<T>::RealPromote> RealPromote; \
573  typedef RGBValue<NumericTraits<T>::ComplexPromote> ComplexPromote; \
574  typedef T ValueType; \
575  \
576  typedef NumericTraits<T>::isIntegral isIntegral; \
577  typedef VigraFalseType isScalar; \
578  typedef NumericTraits<T>::isSigned isSigned; \
579  typedef VigraFalseType isOrdered; \
580  typedef VigraFalseType isComplex; \
581  \
582  static RGBValue<T> zero() { \
583  return RGBValue<T>(NumericTraits<T>::zero()); \
584  }\
585  static RGBValue<T> one() { \
586  return RGBValue<T>(NumericTraits<T>::one()); \
587  }\
588  static RGBValue<T> nonZero() { \
589  return RGBValue<T>(NumericTraits<T>::nonZero()); \
590  }\
591  \
592  static Promote toPromote(RGBValue<T> const & v) { \
593  return Promote(v); \
594  }\
595  static RealPromote toRealPromote(RGBValue<T> const & v) { \
596  return RealPromote(v); \
597  }\
598  static RGBValue<T> fromPromote(Promote const & v) { \
599  RGBValue<T> res;\
600  RGBValue<T>::iterator d = res.begin();\
601  Promote::const_iterator s = v.begin();\
602  for(; d != res.end(); ++d, ++s)\
603  *d = NumericTraits<T>::fromPromote(*s);\
604  return res;\
605  }\
606  static RGBValue<T> fromRealPromote(RealPromote const & v) {\
607  RGBValue<T> res;\
608  RGBValue<T>::iterator d = res.begin();\
609  RealPromote::const_iterator s = v.begin();\
610  for(; d != res.end(); ++d, ++s)\
611  *d = NumericTraits<T>::fromRealPromote(*s);\
612  return res;\
613  }\
614 }; \
615 template<>\
616 struct NormTraits<RGBValue<T, 0, 1, 2> >\
617 {\
618  typedef RGBValue<T> Type;\
619  typedef Type::SquaredNormType SquaredNormType; \
620  typedef Type::NormType NormType; \
621 };
622 
623 #define RGBVALUE_PROMTRAITS1(type1) \
624 template<> \
625 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, RGBValue<type1, 0, 1, 2> > \
626 { \
627  typedef RGBValue<PromoteTraits<type1, type1>::Promote> Promote; \
628  static Promote toPromote(RGBValue<type1> const & v) { \
629  return static_cast<Promote>(v); } \
630 }; \
631 template <> \
632 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, double > \
633 { \
634  typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \
635 }; \
636 template <> \
637 struct PromoteTraits<double, RGBValue<type1, 0, 1, 2> > \
638 { \
639  typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \
640 };
641 
642 #define RGBVALUE_PROMTRAITS2(type1, type2) \
643 template<> \
644 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, RGBValue<type2, 0, 1, 2> > \
645 { \
646  typedef RGBValue<PromoteTraits<type1, type2>::Promote> Promote; \
647  static Promote toPromote(RGBValue<type1> const & v) { \
648  return static_cast<Promote>(v); } \
649  static Promote toPromote(RGBValue<type2> const & v) { \
650  return static_cast<Promote>(v); } \
651 };
652 
653 RGBVALUE_NUMTRAITS(unsigned char)
654 RGBVALUE_NUMTRAITS(int)
655 RGBVALUE_NUMTRAITS(float)
656 RGBVALUE_NUMTRAITS(double)
657 RGBVALUE_PROMTRAITS1(unsigned char)
658 RGBVALUE_PROMTRAITS1(int)
659 RGBVALUE_PROMTRAITS1(float)
660 RGBVALUE_PROMTRAITS1(double)
661 RGBVALUE_PROMTRAITS2(float, unsigned char)
662 RGBVALUE_PROMTRAITS2(unsigned char, float)
663 RGBVALUE_PROMTRAITS2(int, unsigned char)
664 RGBVALUE_PROMTRAITS2(unsigned char, int)
665 RGBVALUE_PROMTRAITS2(int, float)
666 RGBVALUE_PROMTRAITS2(float, int)
667 RGBVALUE_PROMTRAITS2(double, unsigned char)
668 RGBVALUE_PROMTRAITS2(unsigned char, double)
669 RGBVALUE_PROMTRAITS2(int, double)
670 RGBVALUE_PROMTRAITS2(double, int)
671 RGBVALUE_PROMTRAITS2(double, float)
672 RGBVALUE_PROMTRAITS2(float, double)
673 
674 #undef RGBVALUE_NUMTRAITS
675 #undef RGBVALUE_PROMTRAITS1
676 #undef RGBVALUE_PROMTRAITS2
677 
678 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
679 
680 
681 /********************************************************/
682 /* */
683 /* RGBValue-Arithmetic */
684 /* */
685 /********************************************************/
686 
687 /** \addtogroup RGBValueOperators
688  */
689 //@{
690  /// componentwise add-assignment
691 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
692  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
693 inline
694 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
695 operator+=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
696  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
697 {
698  l.red() += r.red();
699  l.green() += r.green();
700  l.blue() += r.blue();
701  return l;
702 }
703 
704  /// componentwise subtract-assignment
705 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
706  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
707 inline
708 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
709 operator-=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
710  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
711 {
712  l.red() -= r.red();
713  l.green() -= r.green();
714  l.blue() -= r.blue();
715  return l;
716 }
717 
718  /// componentwise multiply-assignment
719 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
720  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
721 inline
722 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
723 operator*=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
724  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
725 {
726  l.red() = V1(l.red() * r.red());
727  l.green() = V1(l.green() * r.green());
728  l.blue() = V1(l.blue() * r.blue());
729  return l;
730 }
731 
732  /// componentwise scalar multiply-assignment
733 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
734 inline
735 RGBValue<V, RIDX, GIDX, BIDX> &
736 operator*=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
737 {
738  l.red() = V(l.red() * r);
739  l.green() = V(l.green() * r);
740  l.blue() = V(l.blue() * r);
741  return l;
742 }
743 
744  /// componentwise divide-assignment
745 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
746  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
747 inline
748 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
749 operator/=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
750  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
751 {
752  l.red() = V1(l.red() / r.red());
753  l.green() = V1(l.green() / r.green());
754  l.blue() = V1(l.blue() / r.blue());
755  return l;
756 }
757 
758  /// componentwise scalar divide-assignment
759 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
760 inline
761 RGBValue<V, RIDX, GIDX, BIDX> &
762 operator/=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
763 {
764  l.red() = V(l.red() / r);
765  l.green() = V(l.green() / r);
766  l.blue() = V(l.blue() / r);
767  return l;
768 }
769 
770 using VIGRA_CSTD::abs;
771 
772  /// component-wise absolute value
773 template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
774 inline
775 RGBValue<T, RIDX, GIDX, BIDX>
776 abs(RGBValue<T, RIDX, GIDX, BIDX> const & v)
777 {
778  return RGBValue<T, RIDX, GIDX, BIDX>(abs(v.red()), abs(v.green()), abs(v.blue()));
779 }
780 
781  /// component-wise addition
782 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
783 inline
784 typename PromoteTraits<RGBValue<V1, R, G, B>,
785  RGBValue<V2, R, G, B> >::Promote
786 operator+(RGBValue<V1, R, G, B> const & r1,
787  RGBValue<V2, R, G, B> const & r2)
788 {
789  typename PromoteTraits<RGBValue<V1, R, G, B>,
790  RGBValue<V2, R, G, B> >::Promote res(r1);
791 
792  res += r2;
793 
794  return res;
795 }
796 
797  /// component-wise subtraction
798 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
799 inline
800 typename PromoteTraits<RGBValue<V1, R, G, B>,
801  RGBValue<V2, R, G, B> >::Promote
802 operator-(RGBValue<V1, R, G, B> const & r1,
803  RGBValue<V2, R, G, B> const & r2)
804 {
805  typename PromoteTraits<RGBValue<V1, R, G, B>,
806  RGBValue<V2, R, G, B> >::Promote res(r1);
807 
808  res -= r2;
809 
810  return res;
811 }
812 
813  /// component-wise multiplication
814 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
815 inline
816 typename PromoteTraits<RGBValue<V1, R, G, B>,
817  RGBValue<V2, R, G, B> >::Promote
818 operator*(RGBValue<V1, R, G, B> const & r1,
819  RGBValue<V2, R, G, B> const & r2)
820 {
821  typename PromoteTraits<RGBValue<V1, R, G, B>,
822  RGBValue<V2, R, G, B> >::Promote res(r1);
823 
824  res *= r2;
825 
826  return res;
827 }
828 
829  /// component-wise left scalar multiplication
830 template <class V, unsigned int R, unsigned int G, unsigned int B>
831 inline
832 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
833 operator*(double v, RGBValue<V, R, G, B> const & r)
834 {
835  typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
836 
837  res *= v;
838 
839  return res;
840 }
841 
842  /// component-wise right scalar multiplication
843 template <class V, unsigned int R, unsigned int G, unsigned int B>
844 inline
845 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
846 operator*(RGBValue<V, R, G, B> const & r, double v)
847 {
848  typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
849 
850  res *= v;
851 
852  return res;
853 }
854 
855  /// component-wise division
856 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
857 inline
858 typename PromoteTraits<RGBValue<V1, R, G, B>,
859  RGBValue<V2, R, G, B> >::Promote
860 operator/(RGBValue<V1, R, G, B> const & r1,
861  RGBValue<V2, R, G, B> const & r2)
862 {
863  typename PromoteTraits<RGBValue<V1, R, G, B>,
864  RGBValue<V2, R, G, B> >::Promote res(r1);
865 
866  res /= r2;
867 
868  return res;
869 }
870 
871  /// component-wise scalar division
872 template <class V, unsigned int R, unsigned int G, unsigned int B>
873 inline
874 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
875 operator/(RGBValue<V, R, G, B> const & r, double v)
876 {
877  typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
878 
879  res /= v;
880 
881  return res;
882 }
883 
884  /// cross product
885 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
886 inline
887 typename PromoteTraits<RGBValue<V1, R, G, B>,
888  RGBValue<V2, R, G, B> >::Promote
889 cross(RGBValue<V1, R, G, B> const & r1,
890  RGBValue<V2, R, G, B> const & r2)
891 {
892  typedef typename PromoteTraits<RGBValue<V1, R, G, B>,
893  RGBValue<V2, R, G, B> >::Promote
894  Res;
895 
896  return Res(r1.green()*r2.blue() - r1.blue()*r2.green(),
897  r1.blue()*r2.red() - r1.red()*r2.blue(),
898  r1.red()*r2.green() - r1.green()*r2.red());
899 }
900 
901  /// dot product
902 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
903  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
904 inline
905 typename PromoteTraits<V1, V2>::Promote
906 dot(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & r1,
907  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r2)
908 {
909  return r1.red()*r2.red() + r1.green()*r2.green() + r1.blue()*r2.blue();
910 }
911 
912 using VIGRA_CSTD::ceil;
913 
914  /** Apply ceil() function to each RGB component.
915  */
916 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
917 inline
918 RGBValue<V, RIDX, GIDX, BIDX>
919 ceil(RGBValue<V, RIDX, GIDX, BIDX> const & r)
920 {
921  return RGBValue<V, RIDX, GIDX, BIDX>(ceil(r.red()),
922  ceil(r.green()),
923  ceil(r.blue()));
924 }
925 
926 using VIGRA_CSTD::floor;
927 
928  /** Apply floor() function to each RGB component.
929  */
930 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
931 inline
932 RGBValue<V, RIDX, GIDX, BIDX>
933 floor(RGBValue<V, RIDX, GIDX, BIDX> const & r)
934 {
935  return RGBValue<V, RIDX, GIDX, BIDX>(floor(r.red()),
936  floor(r.green()),
937  floor(r.blue()));
938 }
939 
940 // overload min and max to avoid that std:min() and std::max() match
941 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
942 inline
943 RGBValue<V, RIDX, GIDX, BIDX>
944 min(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::min(res.begin(), r.begin());
950  return res;
951 }
952 
953 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
954 inline
955 RGBValue<V, RIDX, GIDX, BIDX>
956 max(RGBValue<V, RIDX, GIDX, BIDX> const & l,
957  RGBValue<V, RIDX, GIDX, BIDX> const & r)
958 {
959  typedef typename detail::LoopType<3>::type ltype;
960  RGBValue<V, RIDX, GIDX, BIDX> res(l);
961  ltype::max(res.begin(), r.begin());
962  return res;
963 }
964 
965 
966 //@}
967 
968 /********************************************************/
969 /* */
970 /* RGBValue-Accessors */
971 /* */
972 /********************************************************/
973 
974 /** \addtogroup DataAccessors
975 */
976 //@{
977 /** \defgroup RGBValueAccessors Accessors for RGBValue */
978 //@{
979  /** Encapsulate access to rgb values.
980 
981  <b>\#include</b> <vigra/rgbvalue.hxx><br>
982  Namespace: vigra
983  */
984 template <class RGBVALUE>
985 class RGBAccessor
986 : public VectorAccessor<RGBVALUE>
987 {
988  public:
989 
990  typedef typename RGBVALUE::value_type component_type;
991 
992  /** Get value of the red component
993  */
994  template <class RGBIterator>
995  component_type const & red(RGBIterator const & rgb) const
996  {
997  return (*rgb).red();
998  }
999 
1000  template <class V, class RGBIterator>
1001  void setRGB(V r, V g, V b, RGBIterator const & rgb) const
1002  {
1003  (*rgb).setRGB( r, g, b );
1004  }
1005 
1006 
1007  /** Set value of the red component. The type <TT>V</TT> of the passed
1008  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1009  */
1010  template <class V, class RGBIterator>
1011  void setRed(V value, RGBIterator const & rgb) const
1012  {
1013  (*rgb).setRed(value);
1014  }
1015 
1016  /** Get value of the red component at an offset
1017  */
1018  template <class RGBIterator, class DIFFERENCE>
1019  component_type const & red(RGBIterator const & rgb, DIFFERENCE diff) const
1020  {
1021  return rgb[diff].red();
1022  }
1023 
1024  /** Set value of the red component at an offset. The type <TT>V</TT> of the passed
1025  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1026  */
1027  template <class V, class RGBIterator, class DIFFERENCE>
1028  void setRed(V value, RGBIterator const & rgb, DIFFERENCE diff) const
1029  {
1030  rgb[diff].setRed(value);
1031  }
1032 
1033  /** Get value of the green component
1034  */
1035  template <class RGBIterator>
1036  component_type const & green(RGBIterator const & rgb) const
1037  {
1038  return (*rgb).green();
1039  }
1040 
1041  /** Set value of the green component. The type <TT>V</TT> of the passed
1042  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1043  */
1044  template <class V, class RGBIterator>
1045  void setGreen(V value, RGBIterator const & rgb) const
1046  {
1047  (*rgb).setGreen(value);
1048  }
1049 
1050  /** Get value of the green component at an offset
1051  */
1052  template <class RGBIterator, class DIFFERENCE>
1053  component_type const & green(RGBIterator const & rgb, DIFFERENCE d) const
1054  {
1055  return rgb[d].green();
1056  }
1057 
1058  /** Set value of the green component at an offset. The type <TT>V</TT> of the passed
1059  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1060  */
1061  template <class V, class RGBIterator, class DIFFERENCE>
1062  void setGreen(V value, RGBIterator const & rgb, DIFFERENCE d) const
1063  {
1064  rgb[d].setGreen(value);
1065  }
1066 
1067  /** Get value of the blue component
1068  */
1069  template <class RGBIterator>
1070  component_type const & blue(RGBIterator const & rgb) const
1071  {
1072  return (*rgb).blue();
1073  }
1074 
1075  /** Set value of the blue component. The type <TT>V</TT> of the passed
1076  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1077  */
1078  template <class V, class RGBIterator>
1079  void setBlue(V value, RGBIterator const & rgb) const
1080  {
1081  (*rgb).setBlue(value);
1082  }
1083 
1084  /** Get value of the blue component at an offset
1085  */
1086  template <class RGBIterator, class DIFFERENCE>
1087  component_type const & blue(RGBIterator const & rgb, DIFFERENCE d) const
1088  {
1089  return rgb[d].blue();
1090  }
1091 
1092  /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed
1093  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1094  */
1095  template <class V, class RGBIterator, class DIFFERENCE>
1096  void setBlue(V value, RGBIterator const & rgb, DIFFERENCE d) const
1097  {
1098  rgb[d].setBlue(value);
1099  }
1100 
1101 };
1102 
1103 
1104 /********************************************************/
1105 /* */
1106 /* RedAccessor */
1107 /* */
1108 /********************************************************/
1109 
1110  /** Encapsulate access to red band of an rgb value.
1111 
1112  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1113  Namespace: vigra
1114  */
1115 template <class RGBVALUE>
1116 class RedAccessor
1117 {
1118  public:
1119  typedef typename RGBVALUE::value_type value_type;
1120 
1121  /** Get value of the red component
1122  */
1123  template <class ITERATOR>
1124  value_type const & operator()(ITERATOR const & i) const {
1125  return (*i).red();
1126  }
1127 
1128  /** Get value of the red component at an offset
1129  */
1130  template <class ITERATOR, class DIFFERENCE>
1131  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1132  {
1133  return i[d].red();
1134  }
1135 
1136  /** Set value of the red component. The type <TT>V</TT> of the passed
1137  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1138  */
1139  template <class V, class ITERATOR>
1140  void set(V value, ITERATOR const & i) const {
1141  (*i).setRed(value);
1142  }
1143 
1144 
1145  /** Set value of the red component at an offset. The type <TT>V</TT> of the passed
1146  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1147  */
1148  template <class V, class ITERATOR, class DIFFERENCE>
1149  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1150  {
1151  i[d].setRed(value);
1152  }
1153 };
1154 
1155 /********************************************************/
1156 /* */
1157 /* GreenAccessor */
1158 /* */
1159 /********************************************************/
1160 
1161  /** Encapsulate access to green band of an rgb value.
1162 
1163  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1164  Namespace: vigra
1165  */
1166 template <class RGBVALUE>
1167 class GreenAccessor
1168 {
1169  public:
1170  typedef typename RGBVALUE::value_type value_type;
1171 
1172  /** Get value of the green component
1173  */
1174  template <class ITERATOR>
1175  value_type const & operator()(ITERATOR const & i) const {
1176  return (*i).green();
1177  }
1178 
1179  /** Get value of the green component at an offset
1180  */
1181  template <class ITERATOR, class DIFFERENCE>
1182  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1183  {
1184  return i[d].green();
1185  }
1186 
1187  /** Set value of the green component. The type <TT>V</TT> of the passed
1188  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1189  */
1190  template <class V, class ITERATOR>
1191  void set(V value, ITERATOR const & i) const {
1192  (*i).setGreen(value);
1193  }
1194 
1195 
1196  /** Set value of the green component at an offset. The type <TT>V</TT> of the passed
1197  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1198  */
1199  template <class V, class ITERATOR, class DIFFERENCE>
1200  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1201  {
1202  i[d].setGreen(value);
1203  }
1204 };
1205 
1206 /********************************************************/
1207 /* */
1208 /* BlueAccessor */
1209 /* */
1210 /********************************************************/
1211 
1212  /** Encapsulate access to blue band of an rgb value.
1213 
1214  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1215  Namespace: vigra
1216  */
1217 template <class RGBVALUE>
1218 class BlueAccessor
1219 {
1220  public:
1221  typedef typename RGBVALUE::value_type value_type;
1222 
1223  /** Get value of the blue component
1224  */
1225  template <class ITERATOR>
1226  value_type const & operator()(ITERATOR const & i) const {
1227  return (*i).blue();
1228  }
1229 
1230  /** Get value of the blue component at an offset
1231  */
1232  template <class ITERATOR, class DIFFERENCE>
1233  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1234  {
1235  return i[d].blue();
1236  }
1237 
1238  /** Set value of the blue component. The type <TT>V</TT> of the passed
1239  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1240  */
1241  template <class V, class ITERATOR>
1242  void set(V value, ITERATOR const & i) const {
1243  (*i).setBlue(value);
1244  }
1245 
1246 
1247  /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed
1248  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1249  */
1250  template <class V, class ITERATOR, class DIFFERENCE>
1251  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1252  {
1253  i[d].setBlue(value);
1254  }
1255 };
1256 
1257 /********************************************************/
1258 /* */
1259 /* RGBToGrayAccessor */
1260 /* */
1261 /********************************************************/
1262 
1263  /** Encapsulate access to luminance of an rgb value.
1264 
1265  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1266  Namespace: vigra
1267  */
1268 template <class RGBVALUE>
1269 class RGBToGrayAccessor
1270 {
1271  public:
1272  typedef typename RGBVALUE::value_type value_type;
1273 
1274  /** Get value of the luminance
1275  */
1276  template <class ITERATOR>
1277  value_type operator()(ITERATOR const & i) const {
1278  return (*i).luminance(); }
1279 
1280  /** Get value of the luminance at an offset
1281  */
1282  template <class ITERATOR, class DIFFERENCE>
1283  value_type operator()(ITERATOR const & i, DIFFERENCE d) const
1284  {
1285  return i[d].luminance();
1286  }
1287 };
1288 
1289 
1290 /********************************************************/
1291 /* */
1292 /* GrayToRGBAccessor */
1293 /* */
1294 /********************************************************/
1295 
1296  /** Create an RGB view for a grayscale image by making all three channels
1297  equal.
1298 
1299  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1300  Namespace: vigra
1301  */
1302 template <class VALUETYPE>
1303 class GrayToRGBAccessor
1304 {
1305  public:
1306  typedef typename vigra::RGBValue<VALUETYPE> value_type;
1307 
1308  /** Get RGB value for the given pixel.
1309  */
1310  template <class ITERATOR>
1311  value_type operator()(ITERATOR const & i) const {
1312  return value_type(*i,*i,*i); }
1313 
1314  /** Get RGB value at an offset
1315  */
1316  template <class ITERATOR, class DIFFERENCE>
1317  value_type operator()(ITERATOR const & i, DIFFERENCE d) const
1318  {
1319  return value_type(i[d],i[d],i[d]);
1320  }
1321 };
1322 
1323 
1324 //@}
1325 //@}
1326 
1327 
1328 } // namespace vigra
1329 
1330 #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.11.1 (Fri May 19 2017)