2 Copyright 2005-2007 Adobe Systems Incorporated
4 Use, modification and distribution are subject to the Boost Software License,
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt).
8 See http://opensource.adobe.com/gil for most recent version including documentation.
11 /*************************************************************************************************/
13 #ifndef GIL_COLOR_BASE_ALGORITHM_HPP
14 #define GIL_COLOR_BASE_ALGORITHM_HPP
16 ////////////////////////////////////////////////////////////////////////////////////////
18 /// \brief pixel related algorithms
19 /// \author Lubomir Bourdev and Hailin Jin \n
20 /// Adobe Systems Incorporated
21 /// \date 2005-2007 \n Last updated on February 16, 2007
23 ////////////////////////////////////////////////////////////////////////////////////////
26 #include <boost/type_traits.hpp>
27 #include <boost/utility/enable_if.hpp>
28 #include <boost/mpl/contains.hpp>
29 #include <boost/mpl/at.hpp>
30 #include "gil_config.hpp"
31 #include "gil_concept.hpp"
32 #include "utilities.hpp"
34 namespace boost { namespace gil {
37 ///////////////////////////////////////
39 /// size: Semantic channel size
41 ///////////////////////////////////////
44 \defgroup ColorBaseAlgorithmSize size
45 \ingroup ColorBaseAlgorithm
46 \brief Returns an MPL integral type specifying the number of elements in a color base
50 BOOST_STATIC_ASSERT((size<rgb8_pixel_t>::value == 3));
51 BOOST_STATIC_ASSERT((size<cmyk8_planar_ptr_t>::value == 4));
55 /// \brief Returns an MPL integral type specifying the number of elements in a color base
56 /// \ingroup ColorBaseAlgorithmSize
57 template <typename ColorBase>
58 struct size : public mpl::size<typename ColorBase::layout_t::color_space_t> {};
60 ///////////////////////////////////////
62 /// semantic_at_c: Semantic channel accessors
64 ///////////////////////////////////////
67 \defgroup ColorBaseAlgorithmSemanticAtC kth_semantic_element_type, kth_semantic_element_reference_type, kth_semantic_element_const_reference_type, semantic_at_c
68 \ingroup ColorBaseAlgorithm
69 \brief Support for accessing the elements of a color base by semantic index
71 The semantic index of an element is the index of its color in the color space. Semantic indexing allows for proper pairing of elements of color bases
72 independent on their layout. For example, red is the first semantic element of a color base regardless of whether it has an RGB layout or a BGR layout.
73 All GIL color base algorithms taking multiple color bases use semantic indexing to access their elements.
77 // 16-bit BGR pixel, 4 bits for the blue, 3 bits for the green, 2 bits for the red channel and 7 unused bits
78 typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,4,3,2>, bgr_layout_t>::type bgr432_pixel_t;
80 // A reference to its red channel. Although the red channel is the third, its semantic index is 0 in the RGB color space
81 typedef kth_semantic_element_reference_type<bgr432_pixel_t, 0>::type red_channel_reference_t;
83 // Initialize the pixel to black
84 bgr432_pixel_t red_pixel(0,0,0);
86 // Set the red channel to 100%
87 red_channel_reference_t red_channel = semantic_at_c<0>(red_pixel);
88 red_channel = channel_traits<red_channel_reference_t>::max_value();
92 /// \brief Specifies the type of the K-th semantic element of a color base
93 /// \ingroup ColorBaseAlgorithmSemanticAtC
94 template <typename ColorBase, int K> struct kth_semantic_element_type {
95 BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value));
96 typedef typename kth_element_type<ColorBase, semantic_index>::type type;
99 /// \brief Specifies the return type of the mutable semantic_at_c<K>(color_base);
100 /// \ingroup ColorBaseAlgorithmSemanticAtC
101 template <typename ColorBase, int K> struct kth_semantic_element_reference_type {
102 BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value));
103 typedef typename kth_element_reference_type<ColorBase,semantic_index>::type type;
104 static type get(ColorBase& cb) { return gil::at_c<semantic_index>(cb); }
107 /// \brief Specifies the return type of the constant semantic_at_c<K>(color_base);
108 /// \ingroup ColorBaseAlgorithmSemanticAtC
109 template <typename ColorBase, int K> struct kth_semantic_element_const_reference_type {
110 BOOST_STATIC_CONSTANT(int, semantic_index = (mpl::at_c<typename ColorBase::layout_t::channel_mapping_t,K>::type::value));
111 typedef typename kth_element_const_reference_type<ColorBase,semantic_index>::type type;
112 static type get(const ColorBase& cb) { return gil::at_c<semantic_index>(cb); }
115 /// \brief A mutable accessor to the K-th semantic element of a color base
116 /// \ingroup ColorBaseAlgorithmSemanticAtC
117 template <int K, typename ColorBase> inline
118 typename disable_if<is_const<ColorBase>,typename kth_semantic_element_reference_type<ColorBase,K>::type>::type
119 semantic_at_c(ColorBase& p) {
120 return kth_semantic_element_reference_type<ColorBase,K>::get(p);
123 /// \brief A constant accessor to the K-th semantic element of a color base
124 /// \ingroup ColorBaseAlgorithmSemanticAtC
125 template <int K, typename ColorBase> inline
126 typename kth_semantic_element_const_reference_type<ColorBase,K>::type
127 semantic_at_c(const ColorBase& p) {
128 return kth_semantic_element_const_reference_type<ColorBase,K>::get(p);
131 ///////////////////////////////////////
133 /// get_color: Named channel accessors
135 ///////////////////////////////////////
138 \defgroup ColorBaseAlgorithmColor color_element_type, color_element_reference_type, color_element_const_reference_type, get_color, contains_color
139 \ingroup ColorBaseAlgorithm
140 \brief Support for accessing the elements of a color base by color name
142 Example: A function that takes a generic pixel containing a red channel and sets it to 100%:
145 template <typename Pixel>
146 void set_red_to_max(Pixel& pixel) {
147 boost::function_requires<MutablePixelConcept<Pixel> >();
148 BOOST_STATIC_ASSERT((contains_color<Pixel, red_t>::value));
150 typedef typename color_element_type<Pixel, red_t>::type red_channel_t;
151 get_color(pixel, red_t()) = channel_traits<red_channel_t>::max_value();
156 /// \brief A predicate metafunction determining whether a given color base contains a given color
157 /// \ingroup ColorBaseAlgorithmColor
158 template <typename ColorBase, typename Color>
159 struct contains_color : public mpl::contains<typename ColorBase::layout_t::color_space_t,Color> {};
161 template <typename ColorBase, typename Color>
162 struct color_index_type : public detail::type_to_index<typename ColorBase::layout_t::color_space_t,Color> {};
164 /// \brief Specifies the type of the element associated with a given color tag
165 /// \ingroup ColorBaseAlgorithmColor
166 template <typename ColorBase, typename Color>
167 struct color_element_type : public kth_semantic_element_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
169 /// \brief Specifies the return type of the mutable element accessor by color name, get_color(color_base, Color());
170 /// \ingroup ColorBaseAlgorithmColor
171 template <typename ColorBase, typename Color>
172 struct color_element_reference_type : public kth_semantic_element_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
174 /// \brief Specifies the return type of the constant element accessor by color name, get_color(color_base, Color());
175 /// \ingroup ColorBaseAlgorithmColor
176 template <typename ColorBase, typename Color>
177 struct color_element_const_reference_type : public kth_semantic_element_const_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
179 /// \brief Mutable accessor to the element associated with a given color name
180 /// \ingroup ColorBaseAlgorithmColor
181 template <typename ColorBase, typename Color>
182 typename color_element_reference_type<ColorBase,Color>::type get_color(ColorBase& cb, Color=Color()) {
183 return color_element_reference_type<ColorBase,Color>::get(cb);
186 /// \brief Constant accessor to the element associated with a given color name
187 /// \ingroup ColorBaseAlgorithmColor
188 template <typename ColorBase, typename Color>
189 typename color_element_const_reference_type<ColorBase,Color>::type get_color(const ColorBase& cb, Color=Color()) {
190 return color_element_const_reference_type<ColorBase,Color>::get(cb);
193 ///////////////////////////////////////
195 /// element_type, element_reference_type, element_const_reference_type: Support for homogeneous color bases
197 ///////////////////////////////////////
200 \defgroup ColorBaseAlgorithmHomogeneous element_type, element_reference_type, element_const_reference_type
201 \ingroup ColorBaseAlgorithm
202 \brief Types for homogeneous color bases
206 typedef element_type<rgb8c_planar_ptr_t>::type element_t;
207 BOOST_STATIC_ASSERT((boost::is_same<element_t, const bits8*>::value));
210 /// \brief Specifies the element type of a homogeneous color base
211 /// \ingroup ColorBaseAlgorithmHomogeneous
212 template <typename ColorBase>
213 struct element_type : public kth_element_type<ColorBase, 0> {};
215 /// \brief Specifies the return type of the mutable element accessor at_c of a homogeneous color base
216 /// \ingroup ColorBaseAlgorithmHomogeneous
217 template <typename ColorBase>
218 struct element_reference_type : public kth_element_reference_type<ColorBase, 0> {};
220 /// \brief Specifies the return type of the constant element accessor at_c of a homogeneous color base
221 /// \ingroup ColorBaseAlgorithmHomogeneous
222 template <typename ColorBase>
223 struct element_const_reference_type : public kth_element_const_reference_type<ColorBase, 0> {};
228 // compile-time recursion for per-element operations on color bases
230 struct element_recursion {
232 template <typename P1,typename P2>
233 static bool static_equal(const P1& p1, const P2& p2) {
234 return element_recursion<N-1>::static_equal(p1,p2) &&
235 semantic_at_c<N-1>(p1)==semantic_at_c<N-1>(p2);
238 template <typename P1,typename P2>
239 static void static_copy(const P1& p1, P2& p2) {
240 element_recursion<N-1>::static_copy(p1,p2);
241 semantic_at_c<N-1>(p2)=semantic_at_c<N-1>(p1);
244 template <typename P,typename T2>
245 static void static_fill(P& p, T2 v) {
246 element_recursion<N-1>::static_fill(p,v);
247 semantic_at_c<N-1>(p)=v;
250 template <typename Dst,typename Op>
251 static void static_generate(Dst& dst, Op op) {
252 element_recursion<N-1>::static_generate(dst,op);
253 semantic_at_c<N-1>(dst)=op();
255 //static_for_each with one source
256 template <typename P1,typename Op>
257 static Op static_for_each(P1& p1, Op op) {
258 Op op2(element_recursion<N-1>::static_for_each(p1,op));
259 op2(semantic_at_c<N-1>(p1));
262 template <typename P1,typename Op>
263 static Op static_for_each(const P1& p1, Op op) {
264 Op op2(element_recursion<N-1>::static_for_each(p1,op));
265 op2(semantic_at_c<N-1>(p1));
268 //static_for_each with two sources
269 template <typename P1,typename P2,typename Op>
270 static Op static_for_each(P1& p1, P2& p2, Op op) {
271 Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
272 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
275 template <typename P1,typename P2,typename Op>
276 static Op static_for_each(P1& p1, const P2& p2, Op op) {
277 Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
278 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
281 template <typename P1,typename P2,typename Op>
282 static Op static_for_each(const P1& p1, P2& p2, Op op) {
283 Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
284 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
287 template <typename P1,typename P2,typename Op>
288 static Op static_for_each(const P1& p1, const P2& p2, Op op) {
289 Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
290 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
293 //static_for_each with three sources
294 template <typename P1,typename P2,typename P3,typename Op>
295 static Op static_for_each(P1& p1, P2& p2, P3& p3, Op op) {
296 Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
297 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
300 template <typename P1,typename P2,typename P3,typename Op>
301 static Op static_for_each(P1& p1, P2& p2, const P3& p3, Op op) {
302 Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
303 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
306 template <typename P1,typename P2,typename P3,typename Op>
307 static Op static_for_each(P1& p1, const P2& p2, P3& p3, Op op) {
308 Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
309 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
312 template <typename P1,typename P2,typename P3,typename Op>
313 static Op static_for_each(P1& p1, const P2& p2, const P3& p3, Op op) {
314 Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
315 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
318 template <typename P1,typename P2,typename P3,typename Op>
319 static Op static_for_each(const P1& p1, P2& p2, P3& p3, Op op) {
320 Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
321 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
324 template <typename P1,typename P2,typename P3,typename Op>
325 static Op static_for_each(const P1& p1, P2& p2, const P3& p3, Op op) {
326 Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
327 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
330 template <typename P1,typename P2,typename P3,typename Op>
331 static Op static_for_each(const P1& p1, const P2& p2, P3& p3, Op op) {
332 Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
333 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
336 template <typename P1,typename P2,typename P3,typename Op>
337 static Op static_for_each(const P1& p1, const P2& p2, const P3& p3, Op op) {
338 Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
339 op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
342 //static_transform with one source
343 template <typename P1,typename Dst,typename Op>
344 static Op static_transform(P1& src, Dst& dst, Op op) {
345 Op op2(element_recursion<N-1>::static_transform(src,dst,op));
346 semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src));
349 template <typename P1,typename Dst,typename Op>
350 static Op static_transform(const P1& src, Dst& dst, Op op) {
351 Op op2(element_recursion<N-1>::static_transform(src,dst,op));
352 semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src));
355 //static_transform with two sources
356 template <typename P1,typename P2,typename Dst,typename Op>
357 static Op static_transform(P1& src1, P2& src2, Dst& dst, Op op) {
358 Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
359 semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
362 template <typename P1,typename P2,typename Dst,typename Op>
363 static Op static_transform(P1& src1, const P2& src2, Dst& dst, Op op) {
364 Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
365 semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
368 template <typename P1,typename P2,typename Dst,typename Op>
369 static Op static_transform(const P1& src1, P2& src2, Dst& dst, Op op) {
370 Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
371 semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
374 template <typename P1,typename P2,typename Dst,typename Op>
375 static Op static_transform(const P1& src1, const P2& src2, Dst& dst, Op op) {
376 Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
377 semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
382 // Termination condition of the compile-time recursion for element operations on a color base
383 template<> struct element_recursion<0> {
385 template <typename P1,typename P2>
386 static bool static_equal(const P1&, const P2&) { return true; }
388 template <typename P1,typename P2>
389 static void static_copy(const P1&, const P2&) {}
391 template <typename P, typename T2>
392 static void static_fill(const P&, T2) {}
394 template <typename Dst,typename Op>
395 static void static_generate(const Dst&,Op){}
396 //static_for_each with one source
397 template <typename P1,typename Op>
398 static Op static_for_each(const P1&,Op op){return op;}
399 //static_for_each with two sources
400 template <typename P1,typename P2,typename Op>
401 static Op static_for_each(const P1&,const P2&,Op op){return op;}
402 //static_for_each with three sources
403 template <typename P1,typename P2,typename P3,typename Op>
404 static Op static_for_each(const P1&,const P2&,const P3&,Op op){return op;}
405 //static_transform with one source
406 template <typename P1,typename Dst,typename Op>
407 static Op static_transform(const P1&,const Dst&,Op op){return op;}
408 //static_transform with two sources
409 template <typename P1,typename P2,typename Dst,typename Op>
410 static Op static_transform(const P1&,const P2&,const Dst&,Op op){return op;}
413 // std::min and std::max don't have the mutable overloads...
414 template <typename Q> inline const Q& mutable_min(const Q& x, const Q& y) { return x<y ? x : y; }
415 template <typename Q> inline Q& mutable_min( Q& x, Q& y) { return x<y ? x : y; }
416 template <typename Q> inline const Q& mutable_max(const Q& x, const Q& y) { return x<y ? y : x; }
417 template <typename Q> inline Q& mutable_max( Q& x, Q& y) { return x<y ? y : x; }
420 // compile-time recursion for min/max element
422 struct min_max_recur {
423 template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) {
424 return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p));
426 template <typename P> static typename element_reference_type<P>::type max_( P& p) {
427 return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p));
429 template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) {
430 return mutable_min(min_max_recur<N-1>::min_(p),semantic_at_c<N-1>(p));
432 template <typename P> static typename element_reference_type<P>::type min_( P& p) {
433 return mutable_min(min_max_recur<N-1>::min_(p),semantic_at_c<N-1>(p));
437 // termination condition of the compile-time recursion for min/max element
439 struct min_max_recur<1> {
440 template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) { return semantic_at_c<0>(p); }
441 template <typename P> static typename element_reference_type<P>::type max_( P& p) { return semantic_at_c<0>(p); }
442 template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) { return semantic_at_c<0>(p); }
443 template <typename P> static typename element_reference_type<P>::type min_( P& p) { return semantic_at_c<0>(p); }
445 } // namespace detail
449 \defgroup ColorBaseAlgorithmMinMax static_min, static_max
450 \ingroup ColorBaseAlgorithm
451 \brief Equivalents to std::min_element and std::max_element for homogeneous color bases
455 rgb8_pixel_t pixel(10,20,30);
456 assert(pixel[2] == 30);
457 static_max(pixel) = static_min(pixel);
458 assert(pixel[2] == 10);
463 template <typename P>
465 typename element_const_reference_type<P>::type static_max(const P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
467 template <typename P>
469 typename element_reference_type<P>::type static_max( P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
471 template <typename P>
473 typename element_const_reference_type<P>::type static_min(const P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
475 template <typename P>
477 typename element_reference_type<P>::type static_min( P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
481 \defgroup ColorBaseAlgorithmEqual static_equal
482 \ingroup ColorBaseAlgorithm
483 \brief Equivalent to std::equal. Pairs the elements semantically
487 rgb8_pixel_t rgb_red(255,0,0);
488 bgr8_pixel_t bgr_red(0,0,255);
489 assert(rgb_red[0]==255 && bgr_red[0]==0);
491 assert(static_equal(rgb_red,bgr_red));
492 assert(rgb_red==bgr_red); // operator== invokes static_equal
497 template <typename P1,typename P2>
499 bool static_equal(const P1& p1, const P2& p2) { return detail::element_recursion<size<P1>::value>::static_equal(p1,p2); }
504 \defgroup ColorBaseAlgorithmCopy static_copy
505 \ingroup ColorBaseAlgorithm
506 \brief Equivalent to std::copy. Pairs the elements semantically
510 rgb8_pixel_t rgb_red(255,0,0);
511 bgr8_pixel_t bgr_red;
512 static_copy(rgb_red, bgr_red); // same as bgr_red = rgb_red
514 assert(rgb_red[0] == 255 && bgr_red[0] == 0);
515 assert(rgb_red == bgr_red);
520 template <typename Src,typename Dst>
522 void static_copy(const Src& src, Dst& dst) { detail::element_recursion<size<Dst>::value>::static_copy(src,dst); }
527 \defgroup ColorBaseAlgorithmFill static_fill
528 \ingroup ColorBaseAlgorithm
529 \brief Equivalent to std::fill.
535 assert(p == rgb8_pixel_t(10,10,10));
539 template <typename P,typename V>
541 void static_fill(P& p, const V& v) { detail::element_recursion<size<P>::value>::static_fill(p,v); }
545 \defgroup ColorBaseAlgorithmGenerate static_generate
546 \ingroup ColorBaseAlgorithm
547 \brief Equivalent to std::generate.
549 Example: Set each channel of a pixel to its semantic index. The channels must be assignable from an integer.
551 struct consecutive_fn {
553 consecutive_fn(int& start) : _current(start) {}
554 int operator()() { return _current++; }
558 static_generate(p, consecutive_fn(start));
559 assert(p == rgb8_pixel_t(0,1,2));
565 template <typename P1,typename Op>
567 void static_generate(P1& dst,Op op) { detail::element_recursion<size<P1>::value>::static_generate(dst,op); }
571 \defgroup ColorBaseAlgorithmTransform static_transform
572 \ingroup ColorBaseAlgorithm
573 \brief Equivalent to std::transform. Pairs the elements semantically
575 Example: Write a generic function that adds two pixels into a homogeneous result pixel.
577 template <typename Result>
579 template <typename T1, typename T2>
580 Result operator()(T1 f1, T2 f2) const { return f1+f2; }
583 template <typename Pixel1, typename Pixel2, typename Pixel3>
584 void sum_channels(const Pixel1& p1, const Pixel2& p2, Pixel3& result) {
585 typedef typename channel_type<Pixel3>::type result_channel_t;
586 static_transform(p1,p2,result,my_plus<result_channel_t>());
589 rgb8_pixel_t p1(1,2,3);
590 bgr8_pixel_t p2(3,2,1);
592 sum_channels(p1,p2,result);
593 assert(result == rgb8_pixel_t(2,4,6));
598 //static_transform with one source
599 template <typename Src,typename Dst,typename Op>
601 Op static_transform(Src& src,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(src,dst,op); }
602 template <typename Src,typename Dst,typename Op>
604 Op static_transform(const Src& src,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(src,dst,op); }
605 //static_transform with two sources
606 template <typename P2,typename P3,typename Dst,typename Op>
608 Op static_transform(P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
609 template <typename P2,typename P3,typename Dst,typename Op>
611 Op static_transform(P2& p2,const P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
612 template <typename P2,typename P3,typename Dst,typename Op>
614 Op static_transform(const P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
615 template <typename P2,typename P3,typename Dst,typename Op>
617 Op static_transform(const P2& p2,const P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
621 \defgroup ColorBaseAlgorithmForEach static_for_each
622 \ingroup ColorBaseAlgorithm
623 \brief Equivalent to std::for_each. Pairs the elements semantically
625 Example: Use static_for_each to increment a planar pixel iterator
628 template <typename Incrementable>
629 void operator()(Incrementable& x) const { ++x; }
632 template <typename ColorBase>
633 void increment_elements(ColorBase& cb) {
634 static_for_each(cb, increment());
637 bits8 red[2], green[2], blue[2];
638 rgb8c_planar_ptr_t p1(red,green,blue);
639 rgb8c_planar_ptr_t p2=p1;
640 increment_elements(p1);
647 //static_for_each with one source
648 template <typename P1,typename Op>
650 Op static_for_each( P1& p1, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); }
651 template <typename P1,typename Op>
653 Op static_for_each(const P1& p1, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); }
654 //static_for_each with two sources
655 template <typename P1,typename P2,typename Op>
657 Op static_for_each(P1& p1, P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
658 template <typename P1,typename P2,typename Op>
660 Op static_for_each(P1& p1,const P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
661 template <typename P1,typename P2,typename Op>
663 Op static_for_each(const P1& p1, P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
664 template <typename P1,typename P2,typename Op>
666 Op static_for_each(const P1& p1,const P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
667 //static_for_each with three sources
668 template <typename P1,typename P2,typename P3,typename Op>
670 Op static_for_each(P1& p1,P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
671 template <typename P1,typename P2,typename P3,typename Op>
673 Op static_for_each(P1& p1,P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
674 template <typename P1,typename P2,typename P3,typename Op>
676 Op static_for_each(P1& p1,const P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
677 template <typename P1,typename P2,typename P3,typename Op>
679 Op static_for_each(P1& p1,const P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
680 template <typename P1,typename P2,typename P3,typename Op>
682 Op static_for_each(const P1& p1,P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
683 template <typename P1,typename P2,typename P3,typename Op>
685 Op static_for_each(const P1& p1,P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
686 template <typename P1,typename P2,typename P3,typename Op>
688 Op static_for_each(const P1& p1,const P2& p2,P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
689 template <typename P1,typename P2,typename P3,typename Op>
691 Op static_for_each(const P1& p1,const P2& p2,const P3& p3,Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,p3,op); }
694 } } // namespace boost::gil