[ 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  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 template <class V, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
392  unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
393 inline
394 bool
395 closeAtTolerance(RGBValue<V, RIDX1, GIDX1, BIDX1> const & l,
396  RGBValue<V, RIDX2, GIDX2, BIDX2> const & r,
397  V epsilon = NumericTraits<V>::epsilon())
398 {
399  return closeAtTolerance(l.red(), r.red(), epsilon) &&
400  closeAtTolerance(l.green(), r.green(), epsilon) &&
401  closeAtTolerance(l.blue(), r.blue(), epsilon);
402 }
403 
404 
405 //@}
406 
407 /********************************************************/
408 /* */
409 /* RGBValue-Traits */
410 /* */
411 /********************************************************/
412 
413 /** \page RGBValueTraits Numeric and Promote Traits of RGBValue
414  The numeric and promote traits for RGBValues follow
415  the general specifications for \ref NumericPromotionTraits.
416  They are implemented in terms of the traits of the basic types by
417  partial template specialization. Note that PromoteTraits are only defined
418  for the case that the color indices are the same in both RGBValues.
419 
420  \code
421 
422  template <class T, unsigned int R, unsigned int G, unsigned int B>
423  struct NumericTraits<RGBValue<T, R, G, B> >
424  {
425  typedef RGBValue<T, R, G, B> Type;
426  typedef RGBValue<typename NumericTraits<T>::Promote, R, G, B> Promote;
427  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> RealPromote;
428  typedef RGBValue<typename NumericTraits<T>::ComplexPromote, R, G, B> ComplexPromote;
429  typedef T ValueType;
430 
431  typedef typename NumericTraits<T>::isIntegral isIntegral;
432  typedef VigraFalseType isScalar;
433  typedef typename NumericTraits<T>::isSigned isSigned;
434 
435  // etc.
436  };
437 
438  template <class T, unsigned int R, unsigned int G, unsigned int B>
439  struct NormTraits<RGBValue<T, R, G, B> >
440  {
441  typedef RGBValue<T, R, G, B> Type;
442  typedef typename Type::SquaredNormType SquaredNormType;
443  typedef typename Type::NormType NormType;
444  };
445 
446  template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2>
447  struct PromoteTraits<RGBValue<T1, R, G, B>, RGBValue<T2, R, G, B> >
448  {
449  typedef RGBValue<typename PromoteTraits<T1, T2>::Promote, R, G, B> Promote;
450  };
451 
452  template <class T, unsigned int R, unsigned int G, unsigned int B>
453  struct PromoteTraits<RGBValue<T, R, G, B>, double >
454  {
455  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
456  };
457 
458  template <class T, unsigned int R, unsigned int G, unsigned int B>
459  struct PromoteTraits<double, RGBValue<T, R, G, B> >
460  {
461  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
462  };
463  \endcode
464 
465  <b>\#include</b> <vigra/rgbvalue.hxx><br>
466  Namespace: vigra
467 
468 */
469 
470 #if !defined(NO_PARTIAL_TEMPLATE_SPECIALIZATION)
471 
472 template <class T, unsigned int R, unsigned int G, unsigned int B>
473 struct NumericTraits<RGBValue<T, R, G, B> >
474 {
475  typedef RGBValue<T, R, G, B> Type;
476  typedef RGBValue<typename NumericTraits<T>::Promote, R, G, B> Promote;
477  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> RealPromote;
478  typedef RGBValue<typename NumericTraits<T>::ComplexPromote, R, G, B> ComplexPromote;
479  typedef T ValueType;
480 
481  typedef typename NumericTraits<T>::isIntegral isIntegral;
482  typedef VigraFalseType isScalar;
483  typedef typename NumericTraits<T>::isSigned isSigned;
484  typedef VigraTrueType isOrdered;
485  typedef VigraFalseType isComplex;
486 
487  static Type zero()
488  {
489  return Type(NumericTraits<T>::zero());
490  }
491  static Type one()
492  {
493  return Type(NumericTraits<T>::one());
494  }
495  static Type nonZero()
496  {
497  return Type(NumericTraits<T>::nonZero());
498  }
499 
500  static Type min()
501  {
502  return Type(NumericTraits<T>::min());
503  }
504  static Type max()
505  {
506  return Type(NumericTraits<T>::max());
507  }
508 
509  static Promote toPromote(Type const & v)
510  {
511  return Promote(v);
512  }
513  static RealPromote toRealPromote(Type const & v)
514  {
515  return RealPromote(v);
516  }
517  static Type fromPromote(Promote const & v)
518  {
519  return Type(NumericTraits<T>::fromPromote(v.red()),
520  NumericTraits<T>::fromPromote(v.green()),
521  NumericTraits<T>::fromPromote(v.blue()));
522  }
523  static Type fromRealPromote(RealPromote const & v)
524  {
525  return Type(NumericTraits<T>::fromRealPromote(v.red()),
526  NumericTraits<T>::fromRealPromote(v.green()),
527  NumericTraits<T>::fromRealPromote(v.blue()));
528  }
529 };
530 
531 template <class T, unsigned int R, unsigned int G, unsigned int B>
532 struct NormTraits<RGBValue<T, R, G, B> >
533 {
534  typedef RGBValue<T, R, G, B> Type;
535  typedef typename Type::SquaredNormType SquaredNormType;
536  typedef typename Type::NormType NormType;
537 };
538 
539 template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2>
540 struct PromoteTraits<RGBValue<T1, R, G, B>, RGBValue<T2, R, G, B> >
541 {
542  typedef RGBValue<typename PromoteTraits<T1, T2>::Promote, R, G, B> Promote;
543 };
544 
545 template <class T, unsigned int R, unsigned int G, unsigned int B>
546 struct PromoteTraits<RGBValue<T, R, G, B>, double >
547 {
548  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
549 };
550 
551 template <class T, unsigned int R, unsigned int G, unsigned int B>
552 struct PromoteTraits<double, RGBValue<T, R, G, B> >
553 {
554  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
555 };
556 
557 template<class T, unsigned int R, unsigned int G, unsigned int B>
558 struct CanSkipInitialization<RGBValue<T, R, G, B> >
559 {
560  typedef typename CanSkipInitialization<T>::type type;
561  static const bool value = type::asBool;
562 };
563 
564 
565 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
566 
567 #define RGBVALUE_NUMTRAITS(T) \
568 template<>\
569 struct NumericTraits<RGBValue<T, 0, 1, 2> >\
570 {\
571  typedef RGBValue<T> Type; \
572  typedef RGBValue<NumericTraits<T>::Promote> Promote; \
573  typedef RGBValue<NumericTraits<T>::RealPromote> RealPromote; \
574  typedef RGBValue<NumericTraits<T>::ComplexPromote> ComplexPromote; \
575  typedef T ValueType; \
576  \
577  typedef NumericTraits<T>::isIntegral isIntegral; \
578  typedef VigraFalseType isScalar; \
579  typedef NumericTraits<T>::isSigned isSigned; \
580  typedef VigraFalseType isOrdered; \
581  typedef VigraFalseType isComplex; \
582  \
583  static RGBValue<T> zero() { \
584  return RGBValue<T>(NumericTraits<T>::zero()); \
585  }\
586  static RGBValue<T> one() { \
587  return RGBValue<T>(NumericTraits<T>::one()); \
588  }\
589  static RGBValue<T> nonZero() { \
590  return RGBValue<T>(NumericTraits<T>::nonZero()); \
591  }\
592  \
593  static Promote toPromote(RGBValue<T> const & v) { \
594  return Promote(v); \
595  }\
596  static RealPromote toRealPromote(RGBValue<T> const & v) { \
597  return RealPromote(v); \
598  }\
599  static RGBValue<T> fromPromote(Promote const & v) { \
600  RGBValue<T> res;\
601  RGBValue<T>::iterator d = res.begin();\
602  Promote::const_iterator s = v.begin();\
603  for(; d != res.end(); ++d, ++s)\
604  *d = NumericTraits<T>::fromPromote(*s);\
605  return res;\
606  }\
607  static RGBValue<T> fromRealPromote(RealPromote const & v) {\
608  RGBValue<T> res;\
609  RGBValue<T>::iterator d = res.begin();\
610  RealPromote::const_iterator s = v.begin();\
611  for(; d != res.end(); ++d, ++s)\
612  *d = NumericTraits<T>::fromRealPromote(*s);\
613  return res;\
614  }\
615 }; \
616 template<>\
617 struct NormTraits<RGBValue<T, 0, 1, 2> >\
618 {\
619  typedef RGBValue<T> Type;\
620  typedef Type::SquaredNormType SquaredNormType; \
621  typedef Type::NormType NormType; \
622 };
623 
624 #define RGBVALUE_PROMTRAITS1(type1) \
625 template<> \
626 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, RGBValue<type1, 0, 1, 2> > \
627 { \
628  typedef RGBValue<PromoteTraits<type1, type1>::Promote> Promote; \
629  static Promote toPromote(RGBValue<type1> const & v) { \
630  return static_cast<Promote>(v); } \
631 }; \
632 template <> \
633 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, double > \
634 { \
635  typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \
636 }; \
637 template <> \
638 struct PromoteTraits<double, RGBValue<type1, 0, 1, 2> > \
639 { \
640  typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \
641 };
642 
643 #define RGBVALUE_PROMTRAITS2(type1, type2) \
644 template<> \
645 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, RGBValue<type2, 0, 1, 2> > \
646 { \
647  typedef RGBValue<PromoteTraits<type1, type2>::Promote> Promote; \
648  static Promote toPromote(RGBValue<type1> const & v) { \
649  return static_cast<Promote>(v); } \
650  static Promote toPromote(RGBValue<type2> const & v) { \
651  return static_cast<Promote>(v); } \
652 };
653 
654 RGBVALUE_NUMTRAITS(unsigned char)
655 RGBVALUE_NUMTRAITS(int)
656 RGBVALUE_NUMTRAITS(float)
657 RGBVALUE_NUMTRAITS(double)
658 RGBVALUE_PROMTRAITS1(unsigned char)
659 RGBVALUE_PROMTRAITS1(int)
660 RGBVALUE_PROMTRAITS1(float)
661 RGBVALUE_PROMTRAITS1(double)
662 RGBVALUE_PROMTRAITS2(float, unsigned char)
663 RGBVALUE_PROMTRAITS2(unsigned char, float)
664 RGBVALUE_PROMTRAITS2(int, unsigned char)
665 RGBVALUE_PROMTRAITS2(unsigned char, int)
666 RGBVALUE_PROMTRAITS2(int, float)
667 RGBVALUE_PROMTRAITS2(float, int)
668 RGBVALUE_PROMTRAITS2(double, unsigned char)
669 RGBVALUE_PROMTRAITS2(unsigned char, double)
670 RGBVALUE_PROMTRAITS2(int, double)
671 RGBVALUE_PROMTRAITS2(double, int)
672 RGBVALUE_PROMTRAITS2(double, float)
673 RGBVALUE_PROMTRAITS2(float, double)
674 
675 #undef RGBVALUE_NUMTRAITS
676 #undef RGBVALUE_PROMTRAITS1
677 #undef RGBVALUE_PROMTRAITS2
678 
679 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
680 
681 
682 /********************************************************/
683 /* */
684 /* RGBValue-Arithmetic */
685 /* */
686 /********************************************************/
687 
688 /** \addtogroup RGBValueOperators
689  */
690 //@{
691  /// componentwise add-assignment
692 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
693  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
694 inline
695 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
696 operator+=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
697  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
698 {
699  l.red() += r.red();
700  l.green() += r.green();
701  l.blue() += r.blue();
702  return l;
703 }
704 
705  /// componentwise subtract-assignment
706 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
707  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
708 inline
709 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
710 operator-=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
711  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
712 {
713  l.red() -= r.red();
714  l.green() -= r.green();
715  l.blue() -= r.blue();
716  return l;
717 }
718 
719  /// componentwise multiply-assignment
720 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
721  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
722 inline
723 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
724 operator*=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
725  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
726 {
727  l.red() = V1(l.red() * r.red());
728  l.green() = V1(l.green() * r.green());
729  l.blue() = V1(l.blue() * r.blue());
730  return l;
731 }
732 
733  /// componentwise scalar multiply-assignment
734 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
735 inline
736 RGBValue<V, RIDX, GIDX, BIDX> &
737 operator*=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
738 {
739  l.red() = V(l.red() * r);
740  l.green() = V(l.green() * r);
741  l.blue() = V(l.blue() * r);
742  return l;
743 }
744 
745  /// componentwise divide-assignment
746 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
747  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
748 inline
749 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
750 operator/=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
751  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
752 {
753  l.red() = V1(l.red() / r.red());
754  l.green() = V1(l.green() / r.green());
755  l.blue() = V1(l.blue() / r.blue());
756  return l;
757 }
758 
759  /// componentwise scalar divide-assignment
760 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
761 inline
762 RGBValue<V, RIDX, GIDX, BIDX> &
763 operator/=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
764 {
765  l.red() = V(l.red() / r);
766  l.green() = V(l.green() / r);
767  l.blue() = V(l.blue() / r);
768  return l;
769 }
770 
771 using VIGRA_CSTD::abs;
772 
773  /// component-wise absolute value
774 template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
775 inline
776 RGBValue<T, RIDX, GIDX, BIDX>
777 abs(RGBValue<T, RIDX, GIDX, BIDX> const & v)
778 {
779  return RGBValue<T, RIDX, GIDX, BIDX>(abs(v.red()), abs(v.green()), abs(v.blue()));
780 }
781 
782  /// component-wise addition
783 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
784 inline
785 typename PromoteTraits<RGBValue<V1, R, G, B>,
786  RGBValue<V2, R, G, B> >::Promote
787 operator+(RGBValue<V1, R, G, B> const & r1,
788  RGBValue<V2, R, G, B> const & r2)
789 {
790  typename PromoteTraits<RGBValue<V1, R, G, B>,
791  RGBValue<V2, R, G, B> >::Promote res(r1);
792 
793  res += r2;
794 
795  return res;
796 }
797 
798  /// component-wise subtraction
799 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
800 inline
801 typename PromoteTraits<RGBValue<V1, R, G, B>,
802  RGBValue<V2, R, G, B> >::Promote
803 operator-(RGBValue<V1, R, G, B> const & r1,
804  RGBValue<V2, R, G, B> const & r2)
805 {
806  typename PromoteTraits<RGBValue<V1, R, G, B>,
807  RGBValue<V2, R, G, B> >::Promote res(r1);
808 
809  res -= r2;
810 
811  return res;
812 }
813 
814  /// component-wise multiplication
815 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
816 inline
817 typename PromoteTraits<RGBValue<V1, R, G, B>,
818  RGBValue<V2, R, G, B> >::Promote
819 operator*(RGBValue<V1, R, G, B> const & r1,
820  RGBValue<V2, R, G, B> const & r2)
821 {
822  typename PromoteTraits<RGBValue<V1, R, G, B>,
823  RGBValue<V2, R, G, B> >::Promote res(r1);
824 
825  res *= r2;
826 
827  return res;
828 }
829 
830  /// component-wise left 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*(double v, RGBValue<V, R, G, B> const & r)
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 right scalar multiplication
844 template <class V, unsigned int R, unsigned int G, unsigned int B>
845 inline
846 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
847 operator*(RGBValue<V, R, G, B> const & r, double v)
848 {
849  typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
850 
851  res *= v;
852 
853  return res;
854 }
855 
856  /// component-wise division
857 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
858 inline
859 typename PromoteTraits<RGBValue<V1, R, G, B>,
860  RGBValue<V2, R, G, B> >::Promote
861 operator/(RGBValue<V1, R, G, B> const & r1,
862  RGBValue<V2, R, G, B> const & r2)
863 {
864  typename PromoteTraits<RGBValue<V1, R, G, B>,
865  RGBValue<V2, R, G, B> >::Promote res(r1);
866 
867  res /= r2;
868 
869  return res;
870 }
871 
872  /// component-wise scalar division
873 template <class V, unsigned int R, unsigned int G, unsigned int B>
874 inline
875 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
876 operator/(RGBValue<V, R, G, B> const & r, double v)
877 {
878  typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
879 
880  res /= v;
881 
882  return res;
883 }
884 
885  /// cross product
886 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
887 inline
888 typename PromoteTraits<RGBValue<V1, R, G, B>,
889  RGBValue<V2, R, G, B> >::Promote
890 cross(RGBValue<V1, R, G, B> const & r1,
891  RGBValue<V2, R, G, B> const & r2)
892 {
893  typedef typename PromoteTraits<RGBValue<V1, R, G, B>,
894  RGBValue<V2, R, G, B> >::Promote
895  Res;
896 
897  return Res(r1.green()*r2.blue() - r1.blue()*r2.green(),
898  r1.blue()*r2.red() - r1.red()*r2.blue(),
899  r1.red()*r2.green() - r1.green()*r2.red());
900 }
901 
902  /// dot product
903 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
904  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
905 inline
906 typename PromoteTraits<V1, V2>::Promote
907 dot(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & r1,
908  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r2)
909 {
910  return r1.red()*r2.red() + r1.green()*r2.green() + r1.blue()*r2.blue();
911 }
912 
913 using VIGRA_CSTD::ceil;
914 
915  /** Apply ceil() function to each RGB component.
916  */
917 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
918 inline
919 RGBValue<V, RIDX, GIDX, BIDX>
920 ceil(RGBValue<V, RIDX, GIDX, BIDX> const & r)
921 {
922  return RGBValue<V, RIDX, GIDX, BIDX>(ceil(r.red()),
923  ceil(r.green()),
924  ceil(r.blue()));
925 }
926 
927 using VIGRA_CSTD::floor;
928 
929  /** Apply floor() function to each RGB component.
930  */
931 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
932 inline
933 RGBValue<V, RIDX, GIDX, BIDX>
934 floor(RGBValue<V, RIDX, GIDX, BIDX> const & r)
935 {
936  return RGBValue<V, RIDX, GIDX, BIDX>(floor(r.red()),
937  floor(r.green()),
938  floor(r.blue()));
939 }
940 
941 // overload min and max to avoid that std:min() and std::max() match
942 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
943 inline
944 RGBValue<V, RIDX, GIDX, BIDX>
945 min(RGBValue<V, RIDX, GIDX, BIDX> const & l,
946  RGBValue<V, RIDX, GIDX, BIDX> const & r)
947 {
948  typedef typename detail::LoopType<3>::type ltype;
949  RGBValue<V, RIDX, GIDX, BIDX> res(l);
950  ltype::min(res.begin(), r.begin());
951  return res;
952 }
953 
954 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
955 inline
956 RGBValue<V, RIDX, GIDX, BIDX>
957 max(RGBValue<V, RIDX, GIDX, BIDX> const & l,
958  RGBValue<V, RIDX, GIDX, BIDX> const & r)
959 {
960  typedef typename detail::LoopType<3>::type ltype;
961  RGBValue<V, RIDX, GIDX, BIDX> res(l);
962  ltype::max(res.begin(), r.begin());
963  return res;
964 }
965 
966 
967 //@}
968 
969 /********************************************************/
970 /* */
971 /* RGBValue-Accessors */
972 /* */
973 /********************************************************/
974 
975 /** \addtogroup DataAccessors
976 */
977 //@{
978 /** \defgroup RGBValueAccessors Accessors for RGBValue */
979 //@{
980  /** Encapsulate access to rgb values.
981 
982  <b>\#include</b> <vigra/rgbvalue.hxx><br>
983  Namespace: vigra
984  */
985 template <class RGBVALUE>
986 class RGBAccessor
987 : public VectorAccessor<RGBVALUE>
988 {
989  public:
990 
991  typedef typename RGBVALUE::value_type component_type;
992 
993  /** Get value of the red component
994  */
995  template <class RGBIterator>
996  component_type const & red(RGBIterator const & rgb) const
997  {
998  return (*rgb).red();
999  }
1000 
1001  template <class V, class RGBIterator>
1002  void setRGB(V r, V g, V b, RGBIterator const & rgb) const
1003  {
1004  (*rgb).setRGB( r, g, b );
1005  }
1006 
1007 
1008  /** Set value of the red component. The type <TT>V</TT> of the passed
1009  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1010  */
1011  template <class V, class RGBIterator>
1012  void setRed(V value, RGBIterator const & rgb) const
1013  {
1014  (*rgb).setRed(value);
1015  }
1016 
1017  /** Get value of the red component at an offset
1018  */
1019  template <class RGBIterator, class DIFFERENCE>
1020  component_type const & red(RGBIterator const & rgb, DIFFERENCE diff) const
1021  {
1022  return rgb[diff].red();
1023  }
1024 
1025  /** Set value of the red component at an offset. The type <TT>V</TT> of the passed
1026  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1027  */
1028  template <class V, class RGBIterator, class DIFFERENCE>
1029  void setRed(V value, RGBIterator const & rgb, DIFFERENCE diff) const
1030  {
1031  rgb[diff].setRed(value);
1032  }
1033 
1034  /** Get value of the green component
1035  */
1036  template <class RGBIterator>
1037  component_type const & green(RGBIterator const & rgb) const
1038  {
1039  return (*rgb).green();
1040  }
1041 
1042  /** Set value of the green component. The type <TT>V</TT> of the passed
1043  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1044  */
1045  template <class V, class RGBIterator>
1046  void setGreen(V value, RGBIterator const & rgb) const
1047  {
1048  (*rgb).setGreen(value);
1049  }
1050 
1051  /** Get value of the green component at an offset
1052  */
1053  template <class RGBIterator, class DIFFERENCE>
1054  component_type const & green(RGBIterator const & rgb, DIFFERENCE d) const
1055  {
1056  return rgb[d].green();
1057  }
1058 
1059  /** Set value of the green component at an offset. The type <TT>V</TT> of the passed
1060  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1061  */
1062  template <class V, class RGBIterator, class DIFFERENCE>
1063  void setGreen(V value, RGBIterator const & rgb, DIFFERENCE d) const
1064  {
1065  rgb[d].setGreen(value);
1066  }
1067 
1068  /** Get value of the blue component
1069  */
1070  template <class RGBIterator>
1071  component_type const & blue(RGBIterator const & rgb) const
1072  {
1073  return (*rgb).blue();
1074  }
1075 
1076  /** Set value of the blue component. The type <TT>V</TT> of the passed
1077  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1078  */
1079  template <class V, class RGBIterator>
1080  void setBlue(V value, RGBIterator const & rgb) const
1081  {
1082  (*rgb).setBlue(value);
1083  }
1084 
1085  /** Get value of the blue component at an offset
1086  */
1087  template <class RGBIterator, class DIFFERENCE>
1088  component_type const & blue(RGBIterator const & rgb, DIFFERENCE d) const
1089  {
1090  return rgb[d].blue();
1091  }
1092 
1093  /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed
1094  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1095  */
1096  template <class V, class RGBIterator, class DIFFERENCE>
1097  void setBlue(V value, RGBIterator const & rgb, DIFFERENCE d) const
1098  {
1099  rgb[d].setBlue(value);
1100  }
1101 
1102 };
1103 
1104 
1105 /********************************************************/
1106 /* */
1107 /* RedAccessor */
1108 /* */
1109 /********************************************************/
1110 
1111  /** Encapsulate access to red band of an rgb value.
1112 
1113  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1114  Namespace: vigra
1115  */
1116 template <class RGBVALUE>
1117 class RedAccessor
1118 {
1119  public:
1120  typedef typename RGBVALUE::value_type value_type;
1121 
1122  /** Get value of the red component
1123  */
1124  template <class ITERATOR>
1125  value_type const & operator()(ITERATOR const & i) const {
1126  return (*i).red();
1127  }
1128 
1129  /** Get value of the red component at an offset
1130  */
1131  template <class ITERATOR, class DIFFERENCE>
1132  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1133  {
1134  return i[d].red();
1135  }
1136 
1137  /** Set value of the red component. The type <TT>V</TT> of the passed
1138  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1139  */
1140  template <class V, class ITERATOR>
1141  void set(V value, ITERATOR const & i) const {
1142  (*i).setRed(value);
1143  }
1144 
1145 
1146  /** Set value of the red component at an offset. The type <TT>V</TT> of the passed
1147  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1148  */
1149  template <class V, class ITERATOR, class DIFFERENCE>
1150  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1151  {
1152  i[d].setRed(value);
1153  }
1154 };
1155 
1156 /********************************************************/
1157 /* */
1158 /* GreenAccessor */
1159 /* */
1160 /********************************************************/
1161 
1162  /** Encapsulate access to green band of an rgb value.
1163 
1164  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1165  Namespace: vigra
1166  */
1167 template <class RGBVALUE>
1168 class GreenAccessor
1169 {
1170  public:
1171  typedef typename RGBVALUE::value_type value_type;
1172 
1173  /** Get value of the green component
1174  */
1175  template <class ITERATOR>
1176  value_type const & operator()(ITERATOR const & i) const {
1177  return (*i).green();
1178  }
1179 
1180  /** Get value of the green component at an offset
1181  */
1182  template <class ITERATOR, class DIFFERENCE>
1183  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1184  {
1185  return i[d].green();
1186  }
1187 
1188  /** Set value of the green component. The type <TT>V</TT> of the passed
1189  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1190  */
1191  template <class V, class ITERATOR>
1192  void set(V value, ITERATOR const & i) const {
1193  (*i).setGreen(value);
1194  }
1195 
1196 
1197  /** Set value of the green component at an offset. The type <TT>V</TT> of the passed
1198  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1199  */
1200  template <class V, class ITERATOR, class DIFFERENCE>
1201  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1202  {
1203  i[d].setGreen(value);
1204  }
1205 };
1206 
1207 /********************************************************/
1208 /* */
1209 /* BlueAccessor */
1210 /* */
1211 /********************************************************/
1212 
1213  /** Encapsulate access to blue band of an rgb value.
1214 
1215  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1216  Namespace: vigra
1217  */
1218 template <class RGBVALUE>
1219 class BlueAccessor
1220 {
1221  public:
1222  typedef typename RGBVALUE::value_type value_type;
1223 
1224  /** Get value of the blue component
1225  */
1226  template <class ITERATOR>
1227  value_type const & operator()(ITERATOR const & i) const {
1228  return (*i).blue();
1229  }
1230 
1231  /** Get value of the blue component at an offset
1232  */
1233  template <class ITERATOR, class DIFFERENCE>
1234  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1235  {
1236  return i[d].blue();
1237  }
1238 
1239  /** Set value of the blue component. The type <TT>V</TT> of the passed
1240  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1241  */
1242  template <class V, class ITERATOR>
1243  void set(V value, ITERATOR const & i) const {
1244  (*i).setBlue(value);
1245  }
1246 
1247 
1248  /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed
1249  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1250  */
1251  template <class V, class ITERATOR, class DIFFERENCE>
1252  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1253  {
1254  i[d].setBlue(value);
1255  }
1256 };
1257 
1258 /********************************************************/
1259 /* */
1260 /* RGBToGrayAccessor */
1261 /* */
1262 /********************************************************/
1263 
1264  /** Encapsulate access to luminance of an rgb value.
1265 
1266  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1267  Namespace: vigra
1268  */
1269 template <class RGBVALUE>
1270 class RGBToGrayAccessor
1271 {
1272  public:
1273  typedef typename RGBVALUE::value_type value_type;
1274 
1275  /** Get value of the luminance
1276  */
1277  template <class ITERATOR>
1278  value_type operator()(ITERATOR const & i) const {
1279  return (*i).luminance(); }
1280 
1281  /** Get value of the luminance at an offset
1282  */
1283  template <class ITERATOR, class DIFFERENCE>
1284  value_type operator()(ITERATOR const & i, DIFFERENCE d) const
1285  {
1286  return i[d].luminance();
1287  }
1288 };
1289 
1290 
1291 /********************************************************/
1292 /* */
1293 /* GrayToRGBAccessor */
1294 /* */
1295 /********************************************************/
1296 
1297  /** Create an RGB view for a grayscale image by making all three channels
1298  equal.
1299 
1300  <b>\#include</b> <vigra/rgbvalue.hxx><br>
1301  Namespace: vigra
1302  */
1303 template <class VALUETYPE>
1304 class GrayToRGBAccessor
1305 {
1306  public:
1307  typedef typename vigra::RGBValue<VALUETYPE> value_type;
1308 
1309  /** Get RGB value for the given pixel.
1310  */
1311  template <class ITERATOR>
1312  value_type operator()(ITERATOR const & i) const {
1313  return value_type(*i,*i,*i); }
1314 
1315  /** Get RGB value at an offset
1316  */
1317  template <class ITERATOR, class DIFFERENCE>
1318  value_type operator()(ITERATOR const & i, DIFFERENCE d) const
1319  {
1320  return value_type(i[d],i[d],i[d]);
1321  }
1322 };
1323 
1324 
1325 //@}
1326 //@}
1327 
1328 
1329 } // namespace vigra
1330 
1331 #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.10.0 (Tue Dec 31 2013)