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

rgbvalue.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 1998-2002 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35
36
37 #ifndef VIGRA_RGBVALUE_HXX
38 #define VIGRA_RGBVALUE_HXX
39
40 #include <cmath> // abs(double)
41 #include <cstdlib> // abs(int)
42 #include "config.hxx"
43 #include "numerictraits.hxx"
44 #include "accessor.hxx"
45 #include "tinyvector.hxx"
46 #include "static_assert.hxx"
47
48 namespace vigra {
49
50 namespace detail {
51
52 template <unsigned int I, unsigned int R, unsigned int G, unsigned int B>
53 struct SelectColorIndexRHS;
54
55 template <unsigned int R, unsigned int G, unsigned int B>
56 struct SelectColorIndexRHS<0, R, G, B>
57 {
58 enum { res = R };
59 };
60
61 template <unsigned int R, unsigned int G, unsigned int B>
62 struct SelectColorIndexRHS<1, R, G, B>
63 {
64 enum { res = G };
65 };
66
67 template <unsigned int R, unsigned int G, unsigned int B>
68 struct SelectColorIndexRHS<2, R, G, B>
69 {
70 enum { res = B };
71 };
72
73 } // namespace detail
74
75 #ifndef DOXYGEN
76
77 template <unsigned int R, unsigned int G, unsigned int B>
78 struct RGBValue_bad_color_indices
79 : staticAssert::AssertBool<(R < 3 && G < 3 && B < 3 &&
80 ((1 << R) + (1 << G) + (1 << B) == 7))>
81 {};
82
83 #endif /* DOXYGEN */
84
85
86 /********************************************************/
87 /* */
88 /* RGBValue */
89 /* */
90 /********************************************************/
91
92 /** \brief Class for a single RGB value.
93
94 This class contains three values (of the specified type) that represent
95 red, green, and blue color channels. By means of the template parameters
96 <tt>RED_IDX, GREEN_IDX, BLUE_IDX</tt>, the indices 0, 1, 2 can be assigned to
97 the three colors arbitrarily, so that, for example, a BGR type can be created
98 as
99
100 \code
101 typedef RGBValue<unsigned char, 2,1,0> BGRValue;
102 \endcode
103
104 The standard order red=0, green=1, blue=2 is the default. There are three possibilities
105 to access the color values: accessor functions (\ref red(), \ref green(),
106 \ref blue()), index operator (operator[](dx), where the <tt>rgb[RED_IDX]</tt>
107 returns red etc.) and iterator (STL-compatible random access
108 iterator that references the three colors in turn). The latter two
109 methods, together with the necessary embedded typedefs, ensure
110 compatibility of a RGBValue with a STL vector.
111
112 \ref RGBValueOperators "Arithmetic operations" are defined as component-wise applications of these
113 operations. Addition, subtraction, and multiplication of two RGBValues
114 (+=, -=, *=, +, -, *, unary -), multiplication and division of an
115 RGBValue with a double, and NumericTraits/PromoteTraits are defined,
116 so that RGBValue fulfills the requirements of a \ref LinearAlgebraConcept "Linear Algebra".
117
118 A number of \ref RGBValueAccessors "accessors" are provided
119 that support access to RGBValues as a whole, to a selected
120 color component, or to the luminance value.
121
122 <b>\#include</b> <vigra/rgbvalue.hxx><br>
123 Namespace: vigra
124 */
125 template <class VALUETYPE, unsigned int RED_IDX = 0, unsigned int GREEN_IDX = 1, unsigned int BLUE_IDX = 2>
126 class RGBValue
127 : public TinyVector<VALUETYPE, 3>
128 {
129 typedef TinyVector<VALUETYPE, 3> Base;
130
131 // inverse mapping from index to color
132 enum {
133 IDX0 = (RED_IDX == 0) ? 0 : (GREEN_IDX == 0) ? 1 : 2,
134 IDX1 = (RED_IDX == 1) ? 0 : (GREEN_IDX == 1) ? 1 : 2,
135 IDX2 = (RED_IDX == 2) ? 0 : (GREEN_IDX == 2) ? 1 : 2
136 };
137
138 public:
139 /** STL-compatible definition of valuetype
140 */
141 typedef typename Base::value_type value_type;
142 /** STL-compatible definition of iterator
143 */
144 typedef typename Base::iterator iterator;
145 /** STL-compatible definition of const iterator
146 */
147 typedef typename Base::const_iterator const_iterator;
148 /** squared norm type (result of squaredManitude())
149 */
150 typedef typename Base::SquaredNormType SquaredNormType;
151 /** norm type (result of magnitude())
152 */
153 typedef typename Base::NormType NormType;
154
155 typedef typename Base::reference reference;
156 typedef typename Base::const_reference const_reference;
157 typedef typename Base::pointer pointer;
158 typedef typename Base::const_pointer const_pointer;
159 typedef typename Base::size_type size_type;
160 typedef typename Base::difference_type difference_type;
161 typedef typename Base::scalar_multiplier scalar_multiplier;
162 typedef typename Base::ReverseCopyTag ReverseCopyTag;
163
164 /** Color index positions
165 */
166 enum
167 {
168 RedIdx = RED_IDX,
169 GreenIdx = GREEN_IDX,
170 BlueIdx = BLUE_IDX
171 };
172
173 /** Construct from explicit color values.
174 \a first, \a second, \a third are written in this order,
175 irrespective of how the color indices are specified.
176 */
177 RGBValue(value_type first, value_type second, value_type third)
178 : Base(first, second, third)
179 {
180 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
181 }
182
183 /** Construct gray value.
184 */
185 RGBValue(value_type gray)
186 : Base(gray, gray, gray)
187 {
188 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
189 }
190
191 /** Copy from raw memory. The order is preserved,
192 irrespective of how the color indices are specified.
193 */
194 explicit RGBValue(const_pointer i)
195 : Base(i)
196 {
197 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
198 }
199
200 /** Construct by reverse copying from raw memory.
201 */
202 RGBValue(const_pointer i, ReverseCopyTag reverse)
203 : Base(i, reverse)
204 {
205 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
206 }
207
208 /** Default constructor (sets all components to 0)
209 */
210 RGBValue()
211 : Base(0, 0, 0)
212 {
213 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
214 }
215
216 #if !defined(TEMPLATE_COPY_CONSTRUCTOR_BUG)
217
218 RGBValue(RGBValue const & r)
219 : Base((Base const &)r)
220 {
221 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
222 }
223
224 RGBValue & operator=(RGBValue const & r)
225 {
226 Base::operator=(r);
227 return *this;
228 }
229
230 #endif // TEMPLATE_COPY_CONSTRUCTOR_BUG
231
232 /** Copy constructor.
233 */
234 template <class U, unsigned int R, unsigned int G, unsigned int B>
235 RGBValue(RGBValue<U, R, G, B> const & r)
236 : Base(detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX0, R, G, B>::res]),
237 detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX1, R, G, B>::res]),
238 detail::RequiresExplicitCast<value_type>::cast(r[detail::SelectColorIndexRHS<IDX2, R, G, B>::res]))
239 {
240 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
241 }
242
243 /** Copy assignment.
244 */
245 template <class U, unsigned int R, unsigned int G, unsigned int B>
246 RGBValue & operator=(RGBValue<U, R, G, B> const & r)
247 {
248 setRed(detail::RequiresExplicitCast<value_type>::cast(r.red()));
249 setGreen(detail::RequiresExplicitCast<value_type>::cast(r.green()));
250 setBlue(detail::RequiresExplicitCast<value_type>::cast(r.blue()));
251 return *this;
252 }
253
254 /** construct from TinyVector
255 */
256 RGBValue(TinyVector<value_type, 3> const & r)
257 : Base(r)
258 {
259 VIGRA_STATIC_ASSERT((RGBValue_bad_color_indices<RED_IDX, GREEN_IDX, BLUE_IDX>));
260 }
261
262 /** assign TinyVector.
263 */
264 RGBValue & operator=(TinyVector<value_type, 3> const & r)
265 {
266 Base::operator=(r);
267 return *this;
268 }
269
270 /** Unary negation (construct RGBValue with negative values)
271 */
272 RGBValue operator-() const
273 {
274 return RGBValue(-(*this)[0], -(*this)[1], -(*this)[2]);
275 }
276
277 /** Access red component.
278 */
279 value_type & red() { return (*this)[RED_IDX]; }
280
281 /** Access green component.
282 */
283 value_type & green() { return (*this)[GREEN_IDX]; }
284
285 /** Access blue component.
286 */
287 value_type & blue() { return (*this)[BLUE_IDX]; }
288
289 /** Get red component.
290 */
291 value_type const & red() const { return (*this)[RED_IDX]; }
292
293 /** Get green component.
294 */
295 value_type const & green() const { return (*this)[GREEN_IDX]; }
296
297 /** Get blue component.
298 */
299 value_type const & blue() const { return (*this)[BLUE_IDX]; }
300
301 /** Calculate luminance.
302 */
303 value_type luminance() const {
304 return detail::RequiresExplicitCast<value_type>::cast(0.3*red() + 0.59*green() + 0.11*blue()); }
305
306 /** Calculate magnitude.
307 */
308 NormType magnitude() const {
309 return Base::magnitude();
310 }
311
312 /** Calculate squared magnitude.
313 */
314 SquaredNormType squaredMagnitude() const {
315 return Base::squaredMagnitude();
316 }
317
318 /** Set red component. The type <TT>V</TT> of the passed
319 in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
320 */
321 template <class V>
322 void setRed(V value) { (*this)[RED_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); }
323
324 /** Set green component.The type <TT>V</TT> of the passed
325 in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
326 */
327 template <class V>
328 void setGreen(V value) { (*this)[GREEN_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); }
329
330 /** Set blue component.The type <TT>V</TT> of the passed
331 in <TT>value</TT> is automatically converted to <TT>VALUETYPE</TT>.
332 */
333 template <class V>
334 void setBlue(V value) { (*this)[BLUE_IDX] = detail::RequiresExplicitCast<value_type>::cast(value); }
335
336
337 template <class V>
338 void setRGB(V r, V g, V b)
339 {
340 (*this)[RED_IDX] = detail::RequiresExplicitCast<value_type>::cast(r);
341 (*this)[GREEN_IDX] = detail::RequiresExplicitCast<value_type>::cast(g);
342 (*this)[BLUE_IDX] = detail::RequiresExplicitCast<value_type>::cast(b);
343 }
344 };
345
346 /********************************************************/
347 /* */
348 /* RGBValue Comparison */
349 /* */
350 /********************************************************/
351
352 /** \addtogroup RGBValueOperators Functions for RGBValue
353
354 \brief Implement basic arithmetic and equality for RGBValue.
355
356 These functions fulfill the requirements of a Linear Algebra.
357 Return types are determined according to \ref RGBValueTraits.
358
359 <b>\#include</b> <vigra/rgbvalue.hxx><br>
360 Namespace: vigra
361 <p>
362
363 */
364 //@{
365 /// component-wise equal
366 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
367 class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
368 inline
369 bool
370 operator==(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & l,
371 RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
372 {
373 return (l.red() == r.red()) &&
374 (l.green() == r.green()) &&
375 (l.blue() == r.blue());
376 }
377
378 /// component-wise not equal
379 template <class V1, unsigned int RIDX1, unsigned int GIDX1, unsigned int BIDX1,
380 class V2, unsigned int RIDX2, unsigned int GIDX2, unsigned int BIDX2>
381 inline
382 bool
383 operator!=(RGBValue<V1, RIDX1, GIDX1, BIDX1> const & l,
384 RGBValue<V2, RIDX2, GIDX2, BIDX2> const & r)
385 {
386 return (l.red() != r.red()) ||
387 (l.green() != r.green()) ||
388 (l.blue() != r.blue());
389 }
390
391 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 (Mon Nov 18 2013)