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

rgbvalue.hxx
1/************************************************************************/
2/* */
3/* Copyright 1998-2002 by Ullrich Koethe */
4/* */
5/* This file is part of the VIGRA computer vision library. */
6/* The VIGRA Website is */
7/* http://hci.iwr.uni-heidelberg.de/vigra/ */
8/* Please direct questions, bug reports, and contributions to */
9/* ullrich.koethe@iwr.uni-heidelberg.de or */
10/* vigra@informatik.uni-hamburg.de */
11/* */
12/* Permission is hereby granted, free of charge, to any person */
13/* obtaining a copy of this software and associated documentation */
14/* files (the "Software"), to deal in the Software without */
15/* restriction, including without limitation the rights to use, */
16/* copy, modify, merge, publish, distribute, sublicense, and/or */
17/* sell copies of the Software, and to permit persons to whom the */
18/* Software is furnished to do so, subject to the following */
19/* conditions: */
20/* */
21/* The above copyright notice and this permission notice shall be */
22/* included in all copies or substantial portions of the */
23/* Software. */
24/* */
25/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29/* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30/* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31/* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32/* OTHER DEALINGS IN THE SOFTWARE. */
33/* */
34/************************************************************************/
35
36
37#ifndef VIGRA_RGBVALUE_HXX
38#define VIGRA_RGBVALUE_HXX
39
40#include <cmath> // abs(double)
41#include <cstdlib> // abs(int)
42#include "config.hxx"
43#include "numerictraits.hxx"
44#include "accessor.hxx"
45#include "tinyvector.hxx"
46#include "static_assert.hxx"
47
48 namespace vigra {
49
50 namespace detail {
51
52 template <unsigned int I, unsigned int R, unsigned int G, unsigned int B>
53 struct SelectColorIndexRHS;
54
55 template <unsigned int R, unsigned int G, unsigned int B>
56 struct SelectColorIndexRHS<0, R, G, B>
57{
58 enum { res = R };
59};
60
61 template <unsigned int R, unsigned int G, unsigned int B>
62 struct SelectColorIndexRHS<1, R, G, B>
63{
64 enum { res = G };
65};
66
67 template <unsigned int R, unsigned int G, unsigned int B>
68 struct SelectColorIndexRHS<2, R, G, B>
69{
70 enum { res = B };
71};
72
73} // namespace detail
74
75#ifndef DOXYGEN
76
77 template <unsigned int R, unsigned int G, unsigned int B>
78 struct RGBValue_bad_color_indices
79: staticAssert::AssertBool<(R < 3 && G < 3 && B < 3 &&
80 ((1 << R) + (1 << G) + (1 << B) == 7))>
81{};
82
83#endif /* DOXYGEN */
84
85
86/********************************************************/
87/* */
88/* RGBValue */
89/* */
90/********************************************************/
91
92/** \brief Class for a single RGB value.
93
94 This class contains three values (of the specified type) that represent
95 red, green, and blue color channels. By means of the template parameters
96 <tt>RED_IDX, GREEN_IDX, BLUE_IDX</tt>, the indices 0, 1, 2 can be assigned to
97 the three colors arbitrarily, so that, for example, a BGR type can be created
98 as
99
100 \code
101 typedef RGBValue<unsigned char, 2,1,0> BGRValue;
102 \endcode
103
104 The standard order red=0, green=1, blue=2 is the default. There are three possibilities
105 to access the color values: accessor functions (\ref red(), \ref green(),
106 \ref blue()), index operator (operator[](dx), where the <tt>rgb[RED_IDX]</tt>
107 returns red etc.) and iterator (STL-compatible random access
108 iterator that references the three colors in turn). The latter two
109 methods, together with the necessary embedded typedefs, ensure
110 compatibility of a RGBValue with a STL vector.
111
112 \ref RGBValueOperators "Arithmetic operations" are defined as component-wise applications of these
113 operations. Addition, subtraction, and multiplication of two RGBValues
114 (+=, -=, *=, +, -, *, unary -), multiplication and division of an
115 RGBValue with a double, and NumericTraits/PromoteTraits are defined,
116 so that RGBValue fulfills the requirements of a \ref LinearAlgebraConcept "Linear Algebra".
117
118 A number of \ref RGBValueAccessors "accessors" are provided
119 that support access to RGBValues as a whole, to a selected
120 color component, or to the luminance value.
121
122 <b>\#include</b> <vigra/rgbvalue.hxx><br>
123 Namespace: vigra
124*/
125template <class VALUETYPE, unsigned int RED_IDX = 0, unsigned int GREEN_IDX = 1, unsigned int BLUE_IDX = 2>
126class 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
365template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
366 class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
367inline
368bool
369operator==(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>
380inline
381bool
382operator!=(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
390template <class V, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
391 unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
392inline
393bool
394closeAtTolerance(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
471template <class T, unsigned int R, unsigned int G, unsigned int B>
472struct 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
530template <class T, unsigned int R, unsigned int G, unsigned int B>
531struct 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
538template <class T1, unsigned int R, unsigned int G, unsigned int B, class T2>
539struct 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
544template <class T, unsigned int R, unsigned int G, unsigned int B>
545struct PromoteTraits<RGBValue<T, R, G, B>, double >
546{
547 typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
548};
549
550template <class T, unsigned int R, unsigned int G, unsigned int B>
551struct PromoteTraits<double, RGBValue<T, R, G, B> >
552{
553 typedef RGBValue<typename NumericTraits<T>::RealPromote, R, G, B> Promote;
554};
555
556template<class T, unsigned int R, unsigned int G, unsigned int B>
557struct 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) \
567template<>\
568struct 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}; \
615template<>\
616struct 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) \
624template<> \
625struct 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}; \
631template <> \
632struct PromoteTraits<RGBValue<type1, 0, 1, 2>, double > \
633{ \
634 typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \
635}; \
636template <> \
637struct PromoteTraits<double, RGBValue<type1, 0, 1, 2> > \
638{ \
639 typedef RGBValue<typename NumericTraits<type1>::RealPromote> Promote; \
640};
641
642#define RGBVALUE_PROMTRAITS2(type1, type2) \
643template<> \
644struct 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
653RGBVALUE_NUMTRAITS(unsigned char)
654RGBVALUE_NUMTRAITS(int)
655RGBVALUE_NUMTRAITS(float)
656RGBVALUE_NUMTRAITS(double)
657RGBVALUE_PROMTRAITS1(unsigned char)
658RGBVALUE_PROMTRAITS1(int)
659RGBVALUE_PROMTRAITS1(float)
660RGBVALUE_PROMTRAITS1(double)
661RGBVALUE_PROMTRAITS2(float, unsigned char)
662RGBVALUE_PROMTRAITS2(unsigned char, float)
663RGBVALUE_PROMTRAITS2(int, unsigned char)
664RGBVALUE_PROMTRAITS2(unsigned char, int)
665RGBVALUE_PROMTRAITS2(int, float)
666RGBVALUE_PROMTRAITS2(float, int)
667RGBVALUE_PROMTRAITS2(double, unsigned char)
668RGBVALUE_PROMTRAITS2(unsigned char, double)
669RGBVALUE_PROMTRAITS2(int, double)
670RGBVALUE_PROMTRAITS2(double, int)
671RGBVALUE_PROMTRAITS2(double, float)
672RGBVALUE_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
691template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
692 class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
693inline
694RGBValue<V1, RIDX1, GIDX1, BIDX1> &
695operator+=(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>
707inline
708RGBValue<V1, RIDX1, GIDX1, BIDX1> &
709operator-=(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>
721inline
722RGBValue<V1, RIDX1, GIDX1, BIDX1> &
723operator*=(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>
734inline
735RGBValue<V, RIDX, GIDX, BIDX> &
736operator*=(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>
747inline
748RGBValue<V1, RIDX1, GIDX1, BIDX1> &
749operator/=(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>
760inline
761RGBValue<V, RIDX, GIDX, BIDX> &
762operator/=(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
770using VIGRA_CSTD::abs;
771
772 /// component-wise absolute value
773 template <class T, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
774inline
775RGBValue<T, RIDX, GIDX, BIDX>
776abs(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>
783inline
784typename PromoteTraits<RGBValue<V1, R, G, B>,
785 RGBValue<V2, R, G, B> >::Promote
786operator+(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>
799inline
800typename PromoteTraits<RGBValue<V1, R, G, B>,
801 RGBValue<V2, R, G, B> >::Promote
802operator-(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>
815inline
816typename PromoteTraits<RGBValue<V1, R, G, B>,
817 RGBValue<V2, R, G, B> >::Promote
818operator*(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>
831inline
832typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
833operator*(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>
844inline
845typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
846operator*(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>
857inline
858typename PromoteTraits<RGBValue<V1, R, G, B>,
859 RGBValue<V2, R, G, B> >::Promote
860operator/(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>
873inline
874typename NumericTraits<RGBValue<V, R, G, B> >::RealPromote
875operator/(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>
886inline
887typename PromoteTraits<RGBValue<V1, R, G, B>,
888 RGBValue<V2, R, G, B> >::Promote
889cross(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>
904inline
905typename PromoteTraits<V1, V2>::Promote
906dot(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
912using VIGRA_CSTD::ceil;
913
914 /** Apply ceil() function to each RGB component.
915 */
916template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
917inline
918RGBValue<V, RIDX, GIDX, BIDX>
919ceil(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
926using VIGRA_CSTD::floor;
927
928 /** Apply floor() function to each RGB component.
929 */
930template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
931inline
932RGBValue<V, RIDX, GIDX, BIDX>
933floor(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
941template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
942inline
943RGBValue<V, RIDX, GIDX, BIDX>
944min(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
953template <class V, unsigned int RIDX, unsigned int GIDX, unsigned int BIDX>
954inline
955RGBValue<V, RIDX, GIDX, BIDX>
956max(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 */
984template <class RGBVALUE>
985class 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 */
1115template <class RGBVALUE>
1116class 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 */
1166template <class RGBVALUE>
1167class 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 */
1217template <class RGBVALUE>
1218class 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 */
1268template <class RGBVALUE>
1269class 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 */
1302template <class VALUETYPE>
1303class 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
vigra

© 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.12.1