1/*
2 Copyright 2005-2007 Adobe Systems Incorporated
3
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).
7
8 See http://opensource.adobe.com/gil for most recent version including documentation.
9*/
10
11/*************************************************************************************************/
12
13#ifndef GIL_COLOR_BASE_ALGORITHM_HPP
14#define GIL_COLOR_BASE_ALGORITHM_HPP
15
16////////////////////////////////////////////////////////////////////////////////////////
17/// \file
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
22///
23////////////////////////////////////////////////////////////////////////////////////////
24
25#include <algorithm>
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"
33
34namespace boost { namespace gil {
35
36
37///////////////////////////////////////
38///
39/// size: Semantic channel size
40///
41///////////////////////////////////////
42
43/**
44\defgroup ColorBaseAlgorithmSize size
45\ingroup ColorBaseAlgorithm
46\brief Returns an MPL integral type specifying the number of elements in a color base
47
48Example:
49\code
50BOOST_STATIC_ASSERT((size<rgb8_pixel_t>::value == 3));
51BOOST_STATIC_ASSERT((size<cmyk8_planar_ptr_t>::value == 4));
52\endcode
53*/
54
55/// \brief Returns an MPL integral type specifying the number of elements in a color base
56/// \ingroup ColorBaseAlgorithmSize
57template <typename ColorBase>
58struct size : public mpl::size<typename ColorBase::layout_t::color_space_t> {};
59
60///////////////////////////////////////
61///
62/// semantic_at_c: Semantic channel accessors
63///
64///////////////////////////////////////
65
66/**
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
70
71The 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
72independent 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.
73All GIL color base algorithms taking multiple color bases use semantic indexing to access their elements.
74
75Example:
76\code
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
78typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,4,3,2>, bgr_layout_t>::type bgr432_pixel_t;
79
80// A reference to its red channel. Although the red channel is the third, its semantic index is 0 in the RGB color space
81typedef kth_semantic_element_reference_type<bgr432_pixel_t, 0>::type red_channel_reference_t;
82
83// Initialize the pixel to black
84bgr432_pixel_t red_pixel(0,0,0);
85
86// Set the red channel to 100%
87red_channel_reference_t red_channel = semantic_at_c<0>(red_pixel);
88red_channel = channel_traits<red_channel_reference_t>::max_value();
89
90\endcode
91*/
92/// \brief Specifies the type of the K-th semantic element of a color base
93/// \ingroup ColorBaseAlgorithmSemanticAtC
94template <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;
97};
98
99/// \brief Specifies the return type of the mutable semantic_at_c<K>(color_base);
100/// \ingroup ColorBaseAlgorithmSemanticAtC
101template <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); }
105};
106
107/// \brief Specifies the return type of the constant semantic_at_c<K>(color_base);
108/// \ingroup ColorBaseAlgorithmSemanticAtC
109template <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); }
113};
114
115/// \brief A mutable accessor to the K-th semantic element of a color base
116/// \ingroup ColorBaseAlgorithmSemanticAtC
117template <int K, typename ColorBase> inline
118typename disable_if<is_const<ColorBase>,typename kth_semantic_element_reference_type<ColorBase,K>::type>::type
119semantic_at_c(ColorBase& p) {
120 return kth_semantic_element_reference_type<ColorBase,K>::get(p);
121}
122
123/// \brief A constant accessor to the K-th semantic element of a color base
124/// \ingroup ColorBaseAlgorithmSemanticAtC
125template <int K, typename ColorBase> inline
126typename kth_semantic_element_const_reference_type<ColorBase,K>::type
127semantic_at_c(const ColorBase& p) {
128 return kth_semantic_element_const_reference_type<ColorBase,K>::get(p);
129}
130
131///////////////////////////////////////
132///
133/// get_color: Named channel accessors
134///
135///////////////////////////////////////
136
137/**
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
141
142Example: A function that takes a generic pixel containing a red channel and sets it to 100%:
143
144\code
145template <typename Pixel>
146void set_red_to_max(Pixel& pixel) {
147 boost::function_requires<MutablePixelConcept<Pixel> >();
148 BOOST_STATIC_ASSERT((contains_color<Pixel, red_t>::value));
149
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();
152}
153\endcode
154*/
155
156/// \brief A predicate metafunction determining whether a given color base contains a given color
157/// \ingroup ColorBaseAlgorithmColor
158template <typename ColorBase, typename Color>
159struct contains_color : public mpl::contains<typename ColorBase::layout_t::color_space_t,Color> {};
160
161template <typename ColorBase, typename Color>
162struct color_index_type : public detail::type_to_index<typename ColorBase::layout_t::color_space_t,Color> {};
163
164/// \brief Specifies the type of the element associated with a given color tag
165/// \ingroup ColorBaseAlgorithmColor
166template <typename ColorBase, typename Color>
167struct color_element_type : public kth_semantic_element_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
168
169/// \brief Specifies the return type of the mutable element accessor by color name, get_color(color_base, Color());
170/// \ingroup ColorBaseAlgorithmColor
171template <typename ColorBase, typename Color>
172struct color_element_reference_type : public kth_semantic_element_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
173
174/// \brief Specifies the return type of the constant element accessor by color name, get_color(color_base, Color());
175/// \ingroup ColorBaseAlgorithmColor
176template <typename ColorBase, typename Color>
177struct color_element_const_reference_type : public kth_semantic_element_const_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
178
179/// \brief Mutable accessor to the element associated with a given color name
180/// \ingroup ColorBaseAlgorithmColor
181template <typename ColorBase, typename Color>
182typename color_element_reference_type<ColorBase,Color>::type get_color(ColorBase& cb, Color=Color()) {
183 return color_element_reference_type<ColorBase,Color>::get(cb);
184}
185
186/// \brief Constant accessor to the element associated with a given color name
187/// \ingroup ColorBaseAlgorithmColor
188template <typename ColorBase, typename Color>
189typename 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);
191}
192
193///////////////////////////////////////
194///
195/// element_type, element_reference_type, element_const_reference_type: Support for homogeneous color bases
196///
197///////////////////////////////////////
198
199/**
200\defgroup ColorBaseAlgorithmHomogeneous element_type, element_reference_type, element_const_reference_type
201\ingroup ColorBaseAlgorithm
202\brief Types for homogeneous color bases
203
204Example:
205\code
206typedef element_type<rgb8c_planar_ptr_t>::type element_t;
207BOOST_STATIC_ASSERT((boost::is_same<element_t, const bits8*>::value));
208\endcode
209*/
210/// \brief Specifies the element type of a homogeneous color base
211/// \ingroup ColorBaseAlgorithmHomogeneous
212template <typename ColorBase>
213struct element_type : public kth_element_type<ColorBase, 0> {};
214
215/// \brief Specifies the return type of the mutable element accessor at_c of a homogeneous color base
216/// \ingroup ColorBaseAlgorithmHomogeneous
217template <typename ColorBase>
218struct element_reference_type : public kth_element_reference_type<ColorBase, 0> {};
219
220/// \brief Specifies the return type of the constant element accessor at_c of a homogeneous color base
221/// \ingroup ColorBaseAlgorithmHomogeneous
222template <typename ColorBase>
223struct element_const_reference_type : public kth_element_const_reference_type<ColorBase, 0> {};
224
225
226namespace detail {
227
228// compile-time recursion for per-element operations on color bases
229template <int N>
230struct element_recursion {
231 //static_equal
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);
236 }
237 //static_copy
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);
242 }
243 //static_fill
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;
248 }
249 //static_generate
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();
254 }
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));
260 return op2;
261 }
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));
266 return op2;
267 }
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));
273 return op2;
274 }
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));
279 return op2;
280 }
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));
285 return op2;
286 }
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));
291 return op2;
292 }
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));
298 return op2;
299 }
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));
304 return op2;
305 }
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));
310 return op2;
311 }
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));
316 return op2;
317 }
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));
322 return op2;
323 }
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));
328 return op2;
329 }
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));
334 return op2;
335 }
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));
340 return op2;
341 }
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));
347 return op2;
348 }
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));
353 return op2;
354 }
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));
360 return op2;
361 }
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));
366 return op2;
367 }
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));
372 return op2;
373 }
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));
378 return op2;
379 }
380};
381
382// Termination condition of the compile-time recursion for element operations on a color base
383template<> struct element_recursion<0> {
384 //static_equal
385 template <typename P1,typename P2>
386 static bool static_equal(const P1&, const P2&) { return true; }
387 //static_copy
388 template <typename P1,typename P2>
389 static void static_copy(const P1&, const P2&) {}
390 //static_fill
391 template <typename P, typename T2>
392 static void static_fill(const P&, T2) {}
393 //static_generate
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;}
411};
412
413// std::min and std::max don't have the mutable overloads...
414template <typename Q> inline const Q& mutable_min(const Q& x, const Q& y) { return x<y ? x : y; }
415template <typename Q> inline Q& mutable_min( Q& x, Q& y) { return x<y ? x : y; }
416template <typename Q> inline const Q& mutable_max(const Q& x, const Q& y) { return x<y ? y : x; }
417template <typename Q> inline Q& mutable_max( Q& x, Q& y) { return x<y ? y : x; }
418
419
420// compile-time recursion for min/max element
421template <int N>
422struct 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));
425 }
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));
428 }
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));
431 }
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));
434 }
435};
436
437// termination condition of the compile-time recursion for min/max element
438template <>
439struct 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); }
444};
445} // namespace detail
446
447
448/**
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
452
453Example:
454\code
455rgb8_pixel_t pixel(10,20,30);
456assert(pixel[2] == 30);
457static_max(pixel) = static_min(pixel);
458assert(pixel[2] == 10);
459\endcode
460\{
461*/
462
463template <typename P>
464GIL_FORCEINLINE
465typename element_const_reference_type<P>::type static_max(const P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
466
467template <typename P>
468GIL_FORCEINLINE
469typename element_reference_type<P>::type static_max( P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
470
471template <typename P>
472GIL_FORCEINLINE
473typename element_const_reference_type<P>::type static_min(const P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
474
475template <typename P>
476GIL_FORCEINLINE
477typename element_reference_type<P>::type static_min( P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
478/// \}
479
480/**
481\defgroup ColorBaseAlgorithmEqual static_equal
482\ingroup ColorBaseAlgorithm
483\brief Equivalent to std::equal. Pairs the elements semantically
484
485Example:
486\code
487rgb8_pixel_t rgb_red(255,0,0);
488bgr8_pixel_t bgr_red(0,0,255);
489assert(rgb_red[0]==255 && bgr_red[0]==0);
490
491assert(static_equal(rgb_red,bgr_red));
492assert(rgb_red==bgr_red); // operator== invokes static_equal
493\endcode
494\{
495*/
496
497template <typename P1,typename P2>
498GIL_FORCEINLINE
499bool static_equal(const P1& p1, const P2& p2) { return detail::element_recursion<size<P1>::value>::static_equal(p1,p2); }
500
501/// \}
502
503/**
504\defgroup ColorBaseAlgorithmCopy static_copy
505\ingroup ColorBaseAlgorithm
506\brief Equivalent to std::copy. Pairs the elements semantically
507
508Example:
509\code
510rgb8_pixel_t rgb_red(255,0,0);
511bgr8_pixel_t bgr_red;
512static_copy(rgb_red, bgr_red); // same as bgr_red = rgb_red
513
514assert(rgb_red[0] == 255 && bgr_red[0] == 0);
515assert(rgb_red == bgr_red);
516\endcode
517\{
518*/
519
520template <typename Src,typename Dst>
521GIL_FORCEINLINE
522void static_copy(const Src& src, Dst& dst) { detail::element_recursion<size<Dst>::value>::static_copy(src,dst); }
523
524/// \}
525
526/**
527\defgroup ColorBaseAlgorithmFill static_fill
528\ingroup ColorBaseAlgorithm
529\brief Equivalent to std::fill.
530
531Example:
532\code
533rgb8_pixel_t p;
534static_fill(p, 10);
535assert(p == rgb8_pixel_t(10,10,10));
536\endcode
537\{
538*/
539template <typename P,typename V>
540GIL_FORCEINLINE
541void static_fill(P& p, const V& v) { detail::element_recursion<size<P>::value>::static_fill(p,v); }
542/// \}
543
544/**
545\defgroup ColorBaseAlgorithmGenerate static_generate
546\ingroup ColorBaseAlgorithm
547\brief Equivalent to std::generate.
548
549Example: Set each channel of a pixel to its semantic index. The channels must be assignable from an integer.
550\code
551struct consecutive_fn {
552 int& _current;
553 consecutive_fn(int& start) : _current(start) {}
554 int operator()() { return _current++; }
555};
556rgb8_pixel_t p;
557int start=0;
558static_generate(p, consecutive_fn(start));
559assert(p == rgb8_pixel_t(0,1,2));
560\endcode
561
562\{
563*/
564
565template <typename P1,typename Op>
566GIL_FORCEINLINE
567void static_generate(P1& dst,Op op) { detail::element_recursion<size<P1>::value>::static_generate(dst,op); }
568/// \}
569
570/**
571\defgroup ColorBaseAlgorithmTransform static_transform
572\ingroup ColorBaseAlgorithm
573\brief Equivalent to std::transform. Pairs the elements semantically
574
575Example: Write a generic function that adds two pixels into a homogeneous result pixel.
576\code
577template <typename Result>
578struct my_plus {
579 template <typename T1, typename T2>
580 Result operator()(T1 f1, T2 f2) const { return f1+f2; }
581};
582
583template <typename Pixel1, typename Pixel2, typename Pixel3>
584void 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>());
587}
588
589rgb8_pixel_t p1(1,2,3);
590bgr8_pixel_t p2(3,2,1);
591rgb8_pixel_t result;
592sum_channels(p1,p2,result);
593assert(result == rgb8_pixel_t(2,4,6));
594\endcode
595\{
596*/
597
598//static_transform with one source
599template <typename Src,typename Dst,typename Op>
600GIL_FORCEINLINE
601Op static_transform(Src& src,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(src,dst,op); }
602template <typename Src,typename Dst,typename Op>
603GIL_FORCEINLINE
604Op 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
606template <typename P2,typename P3,typename Dst,typename Op>
607GIL_FORCEINLINE
608Op static_transform(P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
609template <typename P2,typename P3,typename Dst,typename Op>
610GIL_FORCEINLINE
611Op static_transform(P2& p2,const P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
612template <typename P2,typename P3,typename Dst,typename Op>
613GIL_FORCEINLINE
614Op static_transform(const P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
615template <typename P2,typename P3,typename Dst,typename Op>
616GIL_FORCEINLINE
617Op 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); }
618/// \}
619
620/**
621\defgroup ColorBaseAlgorithmForEach static_for_each
622\ingroup ColorBaseAlgorithm
623\brief Equivalent to std::for_each. Pairs the elements semantically
624
625Example: Use static_for_each to increment a planar pixel iterator
626\code
627struct increment {
628 template <typename Incrementable>
629 void operator()(Incrementable& x) const { ++x; }
630};
631
632template <typename ColorBase>
633void increment_elements(ColorBase& cb) {
634 static_for_each(cb, increment());
635}
636
637bits8 red[2], green[2], blue[2];
638rgb8c_planar_ptr_t p1(red,green,blue);
639rgb8c_planar_ptr_t p2=p1;
640increment_elements(p1);
641++p2;
642assert(p1 == p2);
643\endcode
644\{
645*/
646
647//static_for_each with one source
648template <typename P1,typename Op>
649GIL_FORCEINLINE
650Op static_for_each( P1& p1, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); }
651template <typename P1,typename Op>
652GIL_FORCEINLINE
653Op 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
655template <typename P1,typename P2,typename Op>
656GIL_FORCEINLINE
657Op static_for_each(P1& p1, P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
658template <typename P1,typename P2,typename Op>
659GIL_FORCEINLINE
660Op static_for_each(P1& p1,const P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
661template <typename P1,typename P2,typename Op>
662GIL_FORCEINLINE
663Op static_for_each(const P1& p1, P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
664template <typename P1,typename P2,typename Op>
665GIL_FORCEINLINE
666Op 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
668template <typename P1,typename P2,typename P3,typename Op>
669GIL_FORCEINLINE
670Op 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); }
671template <typename P1,typename P2,typename P3,typename Op>
672GIL_FORCEINLINE
673Op 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); }
674template <typename P1,typename P2,typename P3,typename Op>
675GIL_FORCEINLINE
676Op 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); }
677template <typename P1,typename P2,typename P3,typename Op>
678GIL_FORCEINLINE
679Op 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); }
680template <typename P1,typename P2,typename P3,typename Op>
681GIL_FORCEINLINE
682Op 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); }
683template <typename P1,typename P2,typename P3,typename Op>
684GIL_FORCEINLINE
685Op 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); }
686template <typename P1,typename P2,typename P3,typename Op>
687GIL_FORCEINLINE
688Op 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); }
689template <typename P1,typename P2,typename P3,typename Op>
690GIL_FORCEINLINE
691Op 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); }
692///\}
693
694} } // namespace boost::gil
695
696#endif
697

source code of boost/boost/gil/color_base_algorithm.hpp