[ 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> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><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> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><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> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><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 VigraFalseType isOrdered;
472  typedef VigraFalseType isComplex;
473 
474  static Type zero() {
475  return Type(NumericTraits<T>::zero());
476  }
477  static Type one() {
478  return Type(NumericTraits<T>::one());
479  }
480  static Type nonZero() {
481  return Type(NumericTraits<T>::nonZero());
482  }
483 
484  static Promote toPromote(Type const & v) {
485  return Promote(v);
486  }
487  static RealPromote toRealPromote(Type const & v) {
488  return RealPromote(v);
489  }
490  static Type fromPromote(Promote const & v) {
491  return Type(NumericTraits<T>::fromPromote(v.red()),
492  NumericTraits<T>::fromPromote(v.green()),
493  NumericTraits<T>::fromPromote(v.blue()));
494  }
495  static Type fromRealPromote(RealPromote const & v) {
496  return Type(NumericTraits<T>::fromRealPromote(v.red()),
497  NumericTraits<T>::fromRealPromote(v.green()),
498  NumericTraits<T>::fromRealPromote(v.blue()));
499  }
500 };
501 
502 template <class T, unsigned int R, unsigned int G, unsigned int B>
503 struct NormTraits<RGBValue<T, R, G, B> >
504 {
505  typedef RGBValue<T, R, G, B> Type;
506  typedef typename Type::SquaredNormType SquaredNormType;
507  typedef typename Type::NormType NormType;
508 };
509 
510 template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2>
511 struct PromoteTraits<RGBValue<T1, R, G, B>, RGBValue<T2, R, G, B> >
512 {
513  typedef RGBValue<typename PromoteTraits<T1, T2>::Promote, R, G, B> Promote;
514 };
515 
516 template <class T, unsigned int R, unsigned int G, unsigned int B>
517 struct PromoteTraits<RGBValue<T, R, G, B>, double >
518 {
519  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
520 };
521 
522 template <class T, unsigned int R, unsigned int G, unsigned int B>
523 struct PromoteTraits<double, RGBValue<T, R, G, B> >
524 {
525  typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
526 };
527 
528 template<class T, unsigned int R, unsigned int G, unsigned int B>
529 struct CanSkipInitialization<RGBValue<T, R, G, B> >
530 {
531  typedef typename CanSkipInitialization<T>::type type;
532  static const bool value = type::asBool;
533 };
534 
535 
536 #else // NO_PARTIAL_TEMPLATE_SPECIALIZATION
537 
538 #define RGBVALUE_NUMTRAITS(T) \
539 template<>\
540 struct NumericTraits<RGBValue<T, 0, 1, 2> >\
541 {\
542  typedef RGBValue<T> Type; \
543  typedef RGBValue<NumericTraits<T>::Promote> Promote; \
544  typedef RGBValue<NumericTraits<T>::RealPromote> RealPromote; \
545  typedef RGBValue<NumericTraits<T>::ComplexPromote> ComplexPromote; \
546  typedef T ValueType; \
547  \
548  typedef NumericTraits<T>::isIntegral isIntegral; \
549  typedef VigraFalseType isScalar; \
550  typedef NumericTraits<T>::isSigned isSigned; \
551  typedef VigraFalseType isOrdered; \
552  typedef VigraFalseType isComplex; \
553  \
554  static RGBValue<T> zero() { \
555  return RGBValue<T>(NumericTraits<T>::zero()); \
556  }\
557  static RGBValue<T> one() { \
558  return RGBValue<T>(NumericTraits<T>::one()); \
559  }\
560  static RGBValue<T> nonZero() { \
561  return RGBValue<T>(NumericTraits<T>::nonZero()); \
562  }\
563  \
564  static Promote toPromote(RGBValue<T> const & v) { \
565  return Promote(v); \
566  }\
567  static RealPromote toRealPromote(RGBValue<T> const & v) { \
568  return RealPromote(v); \
569  }\
570  static RGBValue<T> fromPromote(Promote const & v) { \
571  RGBValue<T> res;\
572  RGBValue<T>::iterator d = res.begin();\
573  Promote::const_iterator s = v.begin();\
574  for(; d != res.end(); ++d, ++s)\
575  *d = NumericTraits<T>::fromPromote(*s);\
576  return res;\
577  }\
578  static RGBValue<T> fromRealPromote(RealPromote const & v) {\
579  RGBValue<T> res;\
580  RGBValue<T>::iterator d = res.begin();\
581  RealPromote::const_iterator s = v.begin();\
582  for(; d != res.end(); ++d, ++s)\
583  *d = NumericTraits<T>::fromRealPromote(*s);\
584  return res;\
585  }\
586 }; \
587 template<>\
588 struct NormTraits<RGBValue<T, 0, 1, 2> >\
589 {\
590  typedef RGBValue<T> Type;\
591  typedef Type::SquaredNormType SquaredNormType; \
592  typedef Type::NormType NormType; \
593 };
594 
595 #define RGBVALUE_PROMTRAITS1(type1) \
596 template<> \
597 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, RGBValue<type1, 0, 1, 2> > \
598 { \
599  typedef RGBValue<PromoteTraits<type1, type1>::Promote> Promote; \
600  static Promote toPromote(RGBValue<type1> const & v) { \
601  return static_cast<Promote>(v); } \
602 }; \
603 template <> \
604 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, double > \
605 { \
606  typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \
607 }; \
608 template <> \
609 struct PromoteTraits<double, RGBValue<type1, 0, 1, 2> > \
610 { \
611  typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \
612 };
613 
614 #define RGBVALUE_PROMTRAITS2(type1, type2) \
615 template<> \
616 struct PromoteTraits<RGBValue<type1, 0, 1, 2>, RGBValue<type2, 0, 1, 2> > \
617 { \
618  typedef RGBValue<PromoteTraits<type1, type2>::Promote> Promote; \
619  static Promote toPromote(RGBValue<type1> const & v) { \
620  return static_cast<Promote>(v); } \
621  static Promote toPromote(RGBValue<type2> const & v) { \
622  return static_cast<Promote>(v); } \
623 };
624 
625 RGBVALUE_NUMTRAITS(unsigned char)
626 RGBVALUE_NUMTRAITS(int)
627 RGBVALUE_NUMTRAITS(float)
628 RGBVALUE_NUMTRAITS(double)
629 RGBVALUE_PROMTRAITS1(unsigned char)
630 RGBVALUE_PROMTRAITS1(int)
631 RGBVALUE_PROMTRAITS1(float)
632 RGBVALUE_PROMTRAITS1(double)
633 RGBVALUE_PROMTRAITS2(float, unsigned char)
634 RGBVALUE_PROMTRAITS2(unsigned char, float)
635 RGBVALUE_PROMTRAITS2(int, unsigned char)
636 RGBVALUE_PROMTRAITS2(unsigned char, int)
637 RGBVALUE_PROMTRAITS2(int, float)
638 RGBVALUE_PROMTRAITS2(float, int)
639 RGBVALUE_PROMTRAITS2(double, unsigned char)
640 RGBVALUE_PROMTRAITS2(unsigned char, double)
641 RGBVALUE_PROMTRAITS2(int, double)
642 RGBVALUE_PROMTRAITS2(double, int)
643 RGBVALUE_PROMTRAITS2(double, float)
644 RGBVALUE_PROMTRAITS2(float, double)
645 
646 #undef RGBVALUE_NUMTRAITS
647 #undef RGBVALUE_PROMTRAITS1
648 #undef RGBVALUE_PROMTRAITS2
649 
650 #endif // NO_PARTIAL_TEMPLATE_SPECIALIZATION
651 
652 
653 /********************************************************/
654 /* */
655 /* RGBValue-Arithmetic */
656 /* */
657 /********************************************************/
658 
659 /** \addtogroup RGBValueOperators
660  */
661 //@{
662  /// componentwise add-assignment
663 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
664  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
665 inline
666 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
667 operator+=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
668  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
669 {
670  l.red() += r.red();
671  l.green() += r.green();
672  l.blue() += r.blue();
673  return l;
674 }
675 
676  /// componentwise subtract-assignment
677 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
678  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
679 inline
680 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
681 operator-=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
682  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
683 {
684  l.red() -= r.red();
685  l.green() -= r.green();
686  l.blue() -= r.blue();
687  return l;
688 }
689 
690  /// componentwise multiply-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() = V1(l.red() * r.red());
699  l.green() = V1(l.green() * r.green());
700  l.blue() = V1(l.blue() * r.blue());
701  return l;
702 }
703 
704  /// componentwise scalar multiply-assignment
705 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
706 inline
707 RGBValue<V, RIDX, GIDX, BIDX> &
708 operator*=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
709 {
710  l.red() = V(l.red() * r);
711  l.green() = V(l.green() * r);
712  l.blue() = V(l.blue() * r);
713  return l;
714 }
715 
716  /// componentwise divide-assignment
717 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
718  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
719 inline
720 RGBValue<V1, RIDX1, GIDX1, BIDX1> &
721 operator/=(RGBValue<V1, RIDX1, GIDX1, BIDX1> & l,
722  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
723 {
724  l.red() = V1(l.red() / r.red());
725  l.green() = V1(l.green() / r.green());
726  l.blue() = V1(l.blue() / r.blue());
727  return l;
728 }
729 
730  /// componentwise scalar divide-assignment
731 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
732 inline
733 RGBValue<V, RIDX, GIDX, BIDX> &
734 operator/=(RGBValue<V, RIDX, GIDX, BIDX> & l, double r)
735 {
736  l.red() = V(l.red() / r);
737  l.green() = V(l.green() / r);
738  l.blue() = V(l.blue() / r);
739  return l;
740 }
741 
742 using VIGRA_CSTD::abs;
743 
744  /// component-wise absolute value
745 template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
746 inline
747 RGBValue<T, RIDX, GIDX, BIDX>
748 abs(RGBValue<T, RIDX, GIDX, BIDX> const & v)
749 {
750  return RGBValue<T, RIDX, GIDX, BIDX>(abs(v.red()), abs(v.green()), abs(v.blue()));
751 }
752 
753  /// component-wise addition
754 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
755 inline
756 typename PromoteTraits<RGBValue<V1, R, G, B>,
757  RGBValue<V2, R, G, B> >::Promote
758 operator+(RGBValue<V1, R, G, B> const & r1,
759  RGBValue<V2, R, G, B> const & r2)
760 {
761  typename PromoteTraits<RGBValue<V1, R, G, B>,
762  RGBValue<V2, R, G, B> >::Promote res(r1);
763 
764  res += r2;
765 
766  return res;
767 }
768 
769  /// component-wise subtraction
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 multiplication
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 left scalar multiplication
802 template <class V, unsigned int R, unsigned int G, unsigned int B>
803 inline
804 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
805 operator*(double v, RGBValue<V, R, G, B> const & r)
806 {
807  typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
808 
809  res *= v;
810 
811  return res;
812 }
813 
814  /// component-wise right scalar multiplication
815 template <class V, unsigned int R, unsigned int G, unsigned int B>
816 inline
817 typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
818 operator*(RGBValue<V, R, G, B> const & r, double v)
819 {
820  typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote res(r);
821 
822  res *= v;
823 
824  return res;
825 }
826 
827  /// component-wise division
828 template <class V1, unsigned int R, unsigned int G, unsigned int B, class V2>
829 inline
830 typename PromoteTraits<RGBValue<V1, R, G, B>,
831  RGBValue<V2, R, G, B> >::Promote
832 operator/(RGBValue<V1, R, G, B> const & r1,
833  RGBValue<V2, R, G, B> const & r2)
834 {
835  typename PromoteTraits<RGBValue<V1, R, G, B>,
836  RGBValue<V2, R, G, B> >::Promote res(r1);
837 
838  res /= r2;
839 
840  return res;
841 }
842 
843  /// component-wise scalar division
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  /// cross product
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 cross(RGBValue<V1, R, G, B> const & r1,
862  RGBValue<V2, R, G, B> const & r2)
863 {
864  typedef typename PromoteTraits<RGBValue<V1, R, G, B>,
865  RGBValue<V2, R, G, B> >::Promote
866  Res;
867 
868  return Res(r1.green()*r2.blue() - r1.blue()*r2.green(),
869  r1.blue()*r2.red() - r1.red()*r2.blue(),
870  r1.red()*r2.green() - r1.green()*r2.red());
871 }
872 
873  /// dot product
874 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
875  class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
876 inline
877 typename PromoteTraits<V1, V2>::Promote
878 dot(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & r1,
879  RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r2)
880 {
881  return r1.red()*r2.red() + r1.green()*r2.green() + r1.blue()*r2.blue();
882 }
883 
884 using VIGRA_CSTD::ceil;
885 
886  /** Apply ceil() function to each RGB component.
887  */
888 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
889 inline
890 RGBValue<V, RIDX, GIDX, BIDX>
891 ceil(RGBValue<V, RIDX, GIDX, BIDX> const & r)
892 {
893  return RGBValue<V, RIDX, GIDX, BIDX>(ceil(r.red()),
894  ceil(r.green()),
895  ceil(r.blue()));
896 }
897 
898 using VIGRA_CSTD::floor;
899 
900  /** Apply floor() function to each RGB component.
901  */
902 template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
903 inline
904 RGBValue<V, RIDX, GIDX, BIDX>
905 floor(RGBValue<V, RIDX, GIDX, BIDX> const & r)
906 {
907  return RGBValue<V, RIDX, GIDX, BIDX>(floor(r.red()),
908  floor(r.green()),
909  floor(r.blue()));
910 }
911 
912 //@}
913 
914 /********************************************************/
915 /* */
916 /* RGBValue-Accessors */
917 /* */
918 /********************************************************/
919 
920 /** \addtogroup DataAccessors
921 */
922 //@{
923 /** \defgroup RGBValueAccessors Accessors for RGBValue */
924 //@{
925  /** Encapsulate access to rgb values.
926 
927  <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br>
928  Namespace: vigra
929  */
930 template <class RGBVALUE>
931 class RGBAccessor
932 : public VectorAccessor<RGBVALUE>
933 {
934  public:
935 
936  typedef typename RGBVALUE::value_type component_type;
937 
938  /** Get value of the red component
939  */
940  template <class RGBIterator>
941  component_type const & red(RGBIterator const & rgb) const
942  {
943  return (*rgb).red();
944  }
945 
946  template <class V, class RGBIterator>
947  void setRGB(V r, V g, V b, RGBIterator const & rgb) const
948  {
949  (*rgb).setRGB( r, g, b );
950  }
951 
952 
953  /** Set value of the red component. The type <TT>V</TT> of the passed
954  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
955  */
956  template <class V, class RGBIterator>
957  void setRed(V value, RGBIterator const & rgb) const
958  {
959  (*rgb).setRed(value);
960  }
961 
962  /** Get value of the red component at an offset
963  */
964  template <class RGBIterator, class DIFFERENCE>
965  component_type const & red(RGBIterator const & rgb, DIFFERENCE diff) const
966  {
967  return rgb[diff].red();
968  }
969 
970  /** Set value of the red component at an offset. The type <TT>V</TT> of the passed
971  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
972  */
973  template <class V, class RGBIterator, class DIFFERENCE>
974  void setRed(V value, RGBIterator const & rgb, DIFFERENCE diff) const
975  {
976  rgb[diff].setRed(value);
977  }
978 
979  /** Get value of the green component
980  */
981  template <class RGBIterator>
982  component_type const & green(RGBIterator const & rgb) const
983  {
984  return (*rgb).green();
985  }
986 
987  /** Set value of the green component. The type <TT>V</TT> of the passed
988  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
989  */
990  template <class V, class RGBIterator>
991  void setGreen(V value, RGBIterator const & rgb) const
992  {
993  (*rgb).setGreen(value);
994  }
995 
996  /** Get value of the green component at an offset
997  */
998  template <class RGBIterator, class DIFFERENCE>
999  component_type const & green(RGBIterator const & rgb, DIFFERENCE d) const
1000  {
1001  return rgb[d].green();
1002  }
1003 
1004  /** Set value of the green component at an offset. The type <TT>V</TT> of the passed
1005  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1006  */
1007  template <class V, class RGBIterator, class DIFFERENCE>
1008  void setGreen(V value, RGBIterator const & rgb, DIFFERENCE d) const
1009  {
1010  rgb[d].setGreen(value);
1011  }
1012 
1013  /** Get value of the blue component
1014  */
1015  template <class RGBIterator>
1016  component_type const & blue(RGBIterator const & rgb) const
1017  {
1018  return (*rgb).blue();
1019  }
1020 
1021  /** Set value of the blue component. The type <TT>V</TT> of the passed
1022  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1023  */
1024  template <class V, class RGBIterator>
1025  void setBlue(V value, RGBIterator const & rgb) const
1026  {
1027  (*rgb).setBlue(value);
1028  }
1029 
1030  /** Get value of the blue component at an offset
1031  */
1032  template <class RGBIterator, class DIFFERENCE>
1033  component_type const & blue(RGBIterator const & rgb, DIFFERENCE d) const
1034  {
1035  return rgb[d].blue();
1036  }
1037 
1038  /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed
1039  in <TT>value</TT> is automatically converted to <TT>component_type</TT>.
1040  */
1041  template <class V, class RGBIterator, class DIFFERENCE>
1042  void setBlue(V value, RGBIterator const & rgb, DIFFERENCE d) const
1043  {
1044  rgb[d].setBlue(value);
1045  }
1046 
1047 };
1048 
1049 
1050 /********************************************************/
1051 /* */
1052 /* RedAccessor */
1053 /* */
1054 /********************************************************/
1055 
1056  /** Encapsulate access to red band of an rgb value.
1057 
1058  <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br>
1059  Namespace: vigra
1060  */
1061 template <class RGBVALUE>
1062 class RedAccessor
1063 {
1064  public:
1065  typedef typename RGBVALUE::value_type value_type;
1066 
1067  /** Get value of the red component
1068  */
1069  template <class ITERATOR>
1070  value_type const & operator()(ITERATOR const & i) const {
1071  return (*i).red();
1072  }
1073 
1074  /** Get value of the red component at an offset
1075  */
1076  template <class ITERATOR, class DIFFERENCE>
1077  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1078  {
1079  return i[d].red();
1080  }
1081 
1082  /** Set value of the red component. The type <TT>V</TT> of the passed
1083  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1084  */
1085  template <class V, class ITERATOR>
1086  void set(V value, ITERATOR const & i) const {
1087  (*i).setRed(value);
1088  }
1089 
1090 
1091  /** Set value of the red component at an offset. The type <TT>V</TT> of the passed
1092  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1093  */
1094  template <class V, class ITERATOR, class DIFFERENCE>
1095  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1096  {
1097  i[d].setRed(value);
1098  }
1099 };
1100 
1101 /********************************************************/
1102 /* */
1103 /* GreenAccessor */
1104 /* */
1105 /********************************************************/
1106 
1107  /** Encapsulate access to green band of an rgb value.
1108 
1109  <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br>
1110  Namespace: vigra
1111  */
1112 template <class RGBVALUE>
1113 class GreenAccessor
1114 {
1115  public:
1116  typedef typename RGBVALUE::value_type value_type;
1117 
1118  /** Get value of the green component
1119  */
1120  template <class ITERATOR>
1121  value_type const & operator()(ITERATOR const & i) const {
1122  return (*i).green();
1123  }
1124 
1125  /** Get value of the green component at an offset
1126  */
1127  template <class ITERATOR, class DIFFERENCE>
1128  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1129  {
1130  return i[d].green();
1131  }
1132 
1133  /** Set value of the green component. 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>
1137  void set(V value, ITERATOR const & i) const {
1138  (*i).setGreen(value);
1139  }
1140 
1141 
1142  /** Set value of the green component at an offset. The type <TT>V</TT> of the passed
1143  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1144  */
1145  template <class V, class ITERATOR, class DIFFERENCE>
1146  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1147  {
1148  i[d].setGreen(value);
1149  }
1150 };
1151 
1152 /********************************************************/
1153 /* */
1154 /* BlueAccessor */
1155 /* */
1156 /********************************************************/
1157 
1158  /** Encapsulate access to blue band of an rgb value.
1159 
1160  <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br>
1161  Namespace: vigra
1162  */
1163 template <class RGBVALUE>
1164 class BlueAccessor
1165 {
1166  public:
1167  typedef typename RGBVALUE::value_type value_type;
1168 
1169  /** Get value of the blue component
1170  */
1171  template <class ITERATOR>
1172  value_type const & operator()(ITERATOR const & i) const {
1173  return (*i).blue();
1174  }
1175 
1176  /** Get value of the blue component at an offset
1177  */
1178  template <class ITERATOR, class DIFFERENCE>
1179  value_type const & operator()(ITERATOR const & i, DIFFERENCE d) const
1180  {
1181  return i[d].blue();
1182  }
1183 
1184  /** Set value of the blue component. 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>
1188  void set(V value, ITERATOR const & i) const {
1189  (*i).setBlue(value);
1190  }
1191 
1192 
1193  /** Set value of the blue component at an offset. The type <TT>V</TT> of the passed
1194  in <TT>value</TT> is automatically converted to <TT>value_type</TT>.
1195  */
1196  template <class V, class ITERATOR, class DIFFERENCE>
1197  void set(V value, ITERATOR const & i, DIFFERENCE d) const
1198  {
1199  i[d].setBlue(value);
1200  }
1201 };
1202 
1203 /********************************************************/
1204 /* */
1205 /* RGBToGrayAccessor */
1206 /* */
1207 /********************************************************/
1208 
1209  /** Encapsulate access to luminance of an rgb value.
1210 
1211  <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br>
1212  Namespace: vigra
1213  */
1214 template <class RGBVALUE>
1215 class RGBToGrayAccessor
1216 {
1217  public:
1218  typedef typename RGBVALUE::value_type value_type;
1219 
1220  /** Get value of the luminance
1221  */
1222  template <class ITERATOR>
1223  value_type operator()(ITERATOR const & i) const {
1224  return (*i).luminance(); }
1225 
1226  /** Get value of the luminance at an offset
1227  */
1228  template <class ITERATOR, class DIFFERENCE>
1229  value_type operator()(ITERATOR const & i, DIFFERENCE d) const
1230  {
1231  return i[d].luminance();
1232  }
1233 };
1234 
1235 
1236 /********************************************************/
1237 /* */
1238 /* GrayToRGBAccessor */
1239 /* */
1240 /********************************************************/
1241 
1242  /** Create an RGB view for a grayscale image by making all three channels
1243  equal.
1244 
1245  <b>\#include</b> <<a href="rgbvalue_8hxx-source.html">vigra/rgbvalue.hxx</a>><br>
1246  Namespace: vigra
1247  */
1248 template <class VALUETYPE>
1249 class GrayToRGBAccessor
1250 {
1251  public:
1252  typedef typename vigra::RGBValue<VALUETYPE> value_type;
1253 
1254  /** Get RGB value for the given pixel.
1255  */
1256  template <class ITERATOR>
1257  value_type operator()(ITERATOR const & i) const {
1258  return value_type(*i,*i,*i); }
1259 
1260  /** Get RGB value at an offset
1261  */
1262  template <class ITERATOR, class DIFFERENCE>
1263  value_type operator()(ITERATOR const & i, DIFFERENCE d) const
1264  {
1265  return value_type(i[d],i[d],i[d]);
1266  }
1267 };
1268 
1269 
1270 //@}
1271 //@}
1272 
1273 
1274 } // namespace vigra
1275 
1276 #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.7.1 (Wed Mar 12 2014)