Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / gil / color_base_algorithm.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 // Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
4 //
5 // Distributed under the Boost Software License, Version 1.0
6 // See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt
8 //
9 #ifndef BOOST_GIL_COLOR_BASE_ALGORITHM_HPP
10 #define BOOST_GIL_COLOR_BASE_ALGORITHM_HPP
11
12 #include <boost/gil/concepts.hpp>
13 #include <boost/gil/utilities.hpp>
14 #include <boost/gil/detail/mp11.hpp>
15
16 #include <boost/config.hpp>
17
18 #include <algorithm>
19 #include <type_traits>
20
21 namespace boost { namespace gil {
22
23 ///////////////////////////////////////
24 /// size:   Semantic channel size
25 ///////////////////////////////////////
26
27 /**
28 \defgroup ColorBaseAlgorithmSize size
29 \ingroup ColorBaseAlgorithm
30 \brief Returns an integral constant type specifying the number of elements in a color base
31
32 Example:
33 \code
34 static_assert(size<rgb8_pixel_t>::value == 3, "");
35 static_assert(size<cmyk8_planar_ptr_t>::value == 4, "");
36 \endcode
37 */
38
39 /// \brief Returns an integral constant type specifying the number of elements in a color base
40 /// \ingroup ColorBaseAlgorithmSize
41 template <typename ColorBase>
42 struct size : public mp11::mp_size<typename ColorBase::layout_t::color_space_t> {};
43
44 ///////////////////////////////////////
45 /// semantic_at_c:   Semantic channel accessors
46 ///////////////////////////////////////
47
48 /**
49 \defgroup ColorBaseAlgorithmSemanticAtC kth_semantic_element_type, kth_semantic_element_reference_type, kth_semantic_element_const_reference_type, semantic_at_c
50 \ingroup ColorBaseAlgorithm
51 \brief Support for accessing the elements of a color base by semantic index
52
53 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
54 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.
55 All GIL color base algorithms taking multiple color bases use semantic indexing to access their elements.
56
57 Example:
58 \code
59 // 16-bit BGR pixel, 4 bits for the blue, 3 bits for the green, 2 bits for the red channel and 7 unused bits
60 using bgr432_pixel_t = packed_pixel_type<uint16_t, mp11::mp_list_c<unsigned,4,3,2>, bgr_layout_t>::type;
61
62 // A reference to its red channel. Although the red channel is the third, its semantic index is 0 in the RGB color space
63 using red_channel_reference_t = kth_semantic_element_reference_type<bgr432_pixel_t, 0>::type;
64
65 // Initialize the pixel to black
66 bgr432_pixel_t red_pixel(0,0,0);
67
68 // Set the red channel to 100%
69 red_channel_reference_t red_channel = semantic_at_c<0>(red_pixel);
70 red_channel = channel_traits<red_channel_reference_t>::max_value();
71
72 \endcode
73 */
74 /// \brief Specifies the type of the K-th semantic element of a color base
75 /// \ingroup ColorBaseAlgorithmSemanticAtC
76 template <typename ColorBase, int K>
77 struct kth_semantic_element_type
78 {
79     using channel_mapping_t = typename ColorBase::layout_t::channel_mapping_t;
80     static_assert(K < mp11::mp_size<channel_mapping_t>::value,
81         "K index should be less than size of channel_mapping_t sequence");
82
83     static constexpr int semantic_index = mp11::mp_at_c<channel_mapping_t, K>::type::value;
84     using type = typename kth_element_type<ColorBase, semantic_index>::type;
85 };
86
87 /// \brief Specifies the return type of the mutable semantic_at_c<K>(color_base);
88 /// \ingroup ColorBaseAlgorithmSemanticAtC
89 template <typename ColorBase, int K>
90 struct kth_semantic_element_reference_type
91 {
92     using channel_mapping_t = typename ColorBase::layout_t::channel_mapping_t;
93     static_assert(K < mp11::mp_size<channel_mapping_t>::value,
94         "K index should be less than size of channel_mapping_t sequence");
95
96     static constexpr int semantic_index = mp11::mp_at_c<channel_mapping_t, K>::type::value;
97     using type = typename kth_element_reference_type<ColorBase, semantic_index>::type;
98     static type get(ColorBase& cb) { return gil::at_c<semantic_index>(cb); }
99 };
100
101 /// \brief Specifies the return type of the constant semantic_at_c<K>(color_base);
102 /// \ingroup ColorBaseAlgorithmSemanticAtC
103 template <typename ColorBase, int K>
104 struct kth_semantic_element_const_reference_type
105 {
106     using channel_mapping_t = typename ColorBase::layout_t::channel_mapping_t;
107     static_assert(K < mp11::mp_size<channel_mapping_t>::value,
108         "K index should be less than size of channel_mapping_t sequence");
109
110     static constexpr int semantic_index = mp11::mp_at_c<channel_mapping_t, K>::type::value;
111     using type = typename kth_element_const_reference_type<ColorBase,semantic_index>::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
117 template <int K, typename ColorBase>
118 inline
119 auto semantic_at_c(ColorBase& p)
120     -> typename std::enable_if
121     <
122         !std::is_const<ColorBase>::value,
123         typename kth_semantic_element_reference_type<ColorBase, K>::type
124     >::type
125 {
126     return kth_semantic_element_reference_type<ColorBase, K>::get(p);
127 }
128
129 /// \brief A constant accessor to the K-th semantic element of a color base
130 /// \ingroup ColorBaseAlgorithmSemanticAtC
131 template <int K, typename ColorBase>
132 inline
133 auto semantic_at_c(ColorBase const& p)
134     -> typename kth_semantic_element_const_reference_type<ColorBase, K>::type
135 {
136     return kth_semantic_element_const_reference_type<ColorBase, K>::get(p);
137 }
138
139 ///////////////////////////////////////
140 /// get_color:   Named channel accessors
141 ///////////////////////////////////////
142
143 /**
144 \defgroup ColorBaseAlgorithmColor color_element_type, color_element_reference_type, color_element_const_reference_type, get_color, contains_color
145 \ingroup ColorBaseAlgorithm
146 \brief Support for accessing the elements of a color base by color name
147
148 Example: A function that takes a generic pixel containing a red channel and sets it to 100%:
149
150 \code
151 template <typename Pixel>
152 void set_red_to_max(Pixel& pixel) {
153     boost::function_requires<MutablePixelConcept<Pixel> >();
154     static_assert(contains_color<Pixel, red_t>::value, "");
155
156     using red_channel_t = typename color_element_type<Pixel, red_t>::type;
157     get_color(pixel, red_t()) = channel_traits<red_channel_t>::max_value();
158 }
159 \endcode
160 */
161
162 /// \brief A predicate metafunction determining whether a given color base contains a given color
163 /// \ingroup ColorBaseAlgorithmColor
164 template <typename ColorBase, typename Color>
165 struct contains_color
166     : mp11::mp_contains<typename ColorBase::layout_t::color_space_t, Color>
167 {};
168
169 template <typename ColorBase, typename Color>
170 struct color_index_type : public detail::type_to_index<typename ColorBase::layout_t::color_space_t,Color> {};
171
172 /// \brief Specifies the type of the element associated with a given color tag
173 /// \ingroup ColorBaseAlgorithmColor
174 template <typename ColorBase, typename Color>
175 struct color_element_type : public kth_semantic_element_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
176
177 /// \brief Specifies the return type of the mutable element accessor by color name, get_color(color_base, Color());
178 /// \ingroup ColorBaseAlgorithmColor
179 template <typename ColorBase, typename Color>
180 struct color_element_reference_type : public kth_semantic_element_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
181
182 /// \brief Specifies the return type of the constant element accessor by color name, get_color(color_base, Color());
183 /// \ingroup ColorBaseAlgorithmColor
184 template <typename ColorBase, typename Color>
185 struct color_element_const_reference_type : public kth_semantic_element_const_reference_type<ColorBase,color_index_type<ColorBase,Color>::value> {};
186
187 /// \brief Mutable accessor to the element associated with a given color name
188 /// \ingroup ColorBaseAlgorithmColor
189 template <typename ColorBase, typename Color>
190 typename color_element_reference_type<ColorBase,Color>::type get_color(ColorBase& cb, Color=Color()) {
191     return color_element_reference_type<ColorBase,Color>::get(cb);
192 }
193
194 /// \brief Constant accessor to the element associated with a given color name
195 /// \ingroup ColorBaseAlgorithmColor
196 template <typename ColorBase, typename Color>
197 typename color_element_const_reference_type<ColorBase,Color>::type get_color(const ColorBase& cb, Color=Color()) {
198     return color_element_const_reference_type<ColorBase,Color>::get(cb);
199 }
200
201 ///////////////////////////////////////
202 ///
203 /// element_type, element_reference_type, element_const_reference_type: Support for homogeneous color bases
204 ///
205 ///////////////////////////////////////
206
207 /**
208 \defgroup ColorBaseAlgorithmHomogeneous element_type, element_reference_type, element_const_reference_type
209 \ingroup ColorBaseAlgorithm
210 \brief Types for homogeneous color bases
211
212 Example:
213 \code
214 using element_t = element_type<rgb8c_planar_ptr_t>::type;
215 static_assert(std::is_same<element_t, const uint8_t*>::value, "");
216 \endcode
217 */
218 /// \brief Specifies the element type of a homogeneous color base
219 /// \ingroup ColorBaseAlgorithmHomogeneous
220 template <typename ColorBase>
221 struct element_type : public kth_element_type<ColorBase, 0> {};
222
223 /// \brief Specifies the return type of the mutable element accessor at_c of a homogeneous color base
224 /// \ingroup ColorBaseAlgorithmHomogeneous
225 template <typename ColorBase>
226 struct element_reference_type : public kth_element_reference_type<ColorBase, 0> {};
227
228 /// \brief Specifies the return type of the constant element accessor at_c of a homogeneous color base
229 /// \ingroup ColorBaseAlgorithmHomogeneous
230 template <typename ColorBase>
231 struct element_const_reference_type : public kth_element_const_reference_type<ColorBase, 0> {};
232
233
234 namespace detail {
235
236 // compile-time recursion for per-element operations on color bases
237 template <int N>
238 struct element_recursion
239 {
240
241 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
242 #pragma GCC diagnostic push
243 #pragma GCC diagnostic ignored "-Wconversion"
244 #pragma GCC diagnostic ignored "-Wfloat-equal"
245 #endif
246
247     template <typename P1,typename P2>
248     static bool static_equal(const P1& p1, const P2& p2)
249     {
250         return element_recursion<N-1>::static_equal(p1,p2) &&
251                semantic_at_c<N-1>(p1)==semantic_at_c<N-1>(p2);
252     }
253
254     template <typename P1,typename P2>
255     static void static_copy(const P1& p1, P2& p2)
256     {
257         element_recursion<N-1>::static_copy(p1,p2);
258         semantic_at_c<N-1>(p2)=semantic_at_c<N-1>(p1);
259     }
260
261     template <typename P,typename T2>
262     static void static_fill(P& p, T2 v)
263     {
264         element_recursion<N-1>::static_fill(p,v);
265         semantic_at_c<N-1>(p)=v;
266     }
267
268     template <typename Dst,typename Op>
269     static void static_generate(Dst& dst, Op op)
270     {
271         element_recursion<N-1>::static_generate(dst,op);
272         semantic_at_c<N-1>(dst)=op();
273     }
274
275 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
276 #pragma GCC diagnostic pop
277 #endif
278
279     //static_for_each with one source
280     template <typename P1,typename Op>
281     static Op static_for_each(P1& p1, Op op) {
282         Op op2(element_recursion<N-1>::static_for_each(p1,op));
283         op2(semantic_at_c<N-1>(p1));
284         return op2;
285     }
286     template <typename P1,typename Op>
287     static Op static_for_each(const P1& p1, Op op) {
288         Op op2(element_recursion<N-1>::static_for_each(p1,op));
289         op2(semantic_at_c<N-1>(p1));
290         return op2;
291     }
292     //static_for_each with two sources
293     template <typename P1,typename P2,typename Op>
294     static Op static_for_each(P1& p1, P2& p2, Op op) {
295         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
296         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
297         return op2;
298     }
299     template <typename P1,typename P2,typename Op>
300     static Op static_for_each(P1& p1, const P2& p2, Op op) {
301         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
302         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
303         return op2;
304     }
305     template <typename P1,typename P2,typename Op>
306     static Op static_for_each(const P1& p1, P2& p2, Op op) {
307         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
308         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
309         return op2;
310     }
311     template <typename P1,typename P2,typename Op>
312     static Op static_for_each(const P1& p1, const P2& p2, Op op) {
313         Op op2(element_recursion<N-1>::static_for_each(p1,p2,op));
314         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2));
315         return op2;
316     }
317     //static_for_each with three sources
318     template <typename P1,typename P2,typename P3,typename Op>
319     static Op static_for_each(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(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(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(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     template <typename P1,typename P2,typename P3,typename Op>
343     static Op static_for_each(const P1& p1, P2& p2, P3& p3, Op op) {
344         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
345         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
346         return op2;
347     }
348     template <typename P1,typename P2,typename P3,typename Op>
349     static Op static_for_each(const P1& p1, P2& p2, const P3& p3, Op op) {
350         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
351         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
352         return op2;
353     }
354     template <typename P1,typename P2,typename P3,typename Op>
355     static Op static_for_each(const P1& p1, const P2& p2, P3& p3, Op op) {
356         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
357         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
358         return op2;
359     }
360     template <typename P1,typename P2,typename P3,typename Op>
361     static Op static_for_each(const P1& p1, const P2& p2, const P3& p3, Op op) {
362         Op op2(element_recursion<N-1>::static_for_each(p1,p2,p3,op));
363         op2(semantic_at_c<N-1>(p1), semantic_at_c<N-1>(p2), semantic_at_c<N-1>(p3));
364         return op2;
365     }
366     //static_transform with one source
367     template <typename P1,typename Dst,typename Op>
368     static Op static_transform(P1& src, Dst& dst, Op op) {
369         Op op2(element_recursion<N-1>::static_transform(src,dst,op));
370         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src));
371         return op2;
372     }
373     template <typename P1,typename Dst,typename Op>
374     static Op static_transform(const P1& src, Dst& dst, Op op) {
375         Op op2(element_recursion<N-1>::static_transform(src,dst,op));
376         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src));
377         return op2;
378     }
379     //static_transform with two sources
380     template <typename P1,typename P2,typename Dst,typename Op>
381     static Op static_transform(P1& src1, P2& src2, Dst& dst, Op op) {
382         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
383         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
384         return op2;
385     }
386     template <typename P1,typename P2,typename Dst,typename Op>
387     static Op static_transform(P1& src1, const P2& src2, Dst& dst, Op op) {
388         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
389         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
390         return op2;
391     }
392     template <typename P1,typename P2,typename Dst,typename Op>
393     static Op static_transform(const P1& src1, P2& src2, Dst& dst, Op op) {
394         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
395         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
396         return op2;
397     }
398     template <typename P1,typename P2,typename Dst,typename Op>
399     static Op static_transform(const P1& src1, const P2& src2, Dst& dst, Op op) {
400         Op op2(element_recursion<N-1>::static_transform(src1,src2,dst,op));
401         semantic_at_c<N-1>(dst)=op2(semantic_at_c<N-1>(src1), semantic_at_c<N-1>(src2));
402         return op2;
403     }
404 };
405
406 // Termination condition of the compile-time recursion for element operations on a color base
407 template<> struct element_recursion<0> {
408     //static_equal
409     template <typename P1,typename P2>
410     static bool static_equal(const P1&, const P2&) { return true; }
411     //static_copy
412     template <typename P1,typename P2>
413     static void static_copy(const P1&, const P2&) {}
414     //static_fill
415     template <typename P, typename T2>
416     static void static_fill(const P&, T2) {}
417     //static_generate
418     template <typename Dst,typename Op>
419     static void static_generate(const Dst&,Op){}
420     //static_for_each with one source
421     template <typename P1,typename Op>
422     static Op static_for_each(const P1&,Op op){return op;}
423     //static_for_each with two sources
424     template <typename P1,typename P2,typename Op>
425     static Op static_for_each(const P1&,const P2&,Op op){return op;}
426     //static_for_each with three sources
427     template <typename P1,typename P2,typename P3,typename Op>
428     static Op static_for_each(const P1&,const P2&,const P3&,Op op){return op;}
429     //static_transform with one source
430     template <typename P1,typename Dst,typename Op>
431     static Op static_transform(const P1&,const Dst&,Op op){return op;}
432     //static_transform with two sources
433     template <typename P1,typename P2,typename Dst,typename Op>
434     static Op static_transform(const P1&,const P2&,const Dst&,Op op){return op;}
435 };
436
437 // std::min and std::max don't have the mutable overloads...
438 template <typename Q> inline const Q& mutable_min(const Q& x, const Q& y) { return x<y ? x : y; }
439 template <typename Q> inline       Q& mutable_min(      Q& x,       Q& y) { return x<y ? x : y; }
440 template <typename Q> inline const Q& mutable_max(const Q& x, const Q& y) { return x<y ? y : x; }
441 template <typename Q> inline       Q& mutable_max(      Q& x,       Q& y) { return x<y ? y : x; }
442
443
444 // compile-time recursion for min/max element
445 template <int N>
446 struct min_max_recur {
447     template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) {
448         return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p));
449     }
450     template <typename P> static typename element_reference_type<P>::type       max_(      P& p) {
451         return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p));
452     }
453     template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) {
454         return mutable_min(min_max_recur<N-1>::min_(p),semantic_at_c<N-1>(p));
455     }
456     template <typename P> static typename element_reference_type<P>::type       min_(      P& p) {
457         return mutable_min(min_max_recur<N-1>::min_(p),semantic_at_c<N-1>(p));
458     }
459 };
460
461 // termination condition of the compile-time recursion for min/max element
462 template <>
463 struct min_max_recur<1> {
464     template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) { return semantic_at_c<0>(p); }
465     template <typename P> static typename element_reference_type<P>::type       max_(      P& p) { return semantic_at_c<0>(p); }
466     template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) { return semantic_at_c<0>(p); }
467     template <typename P> static typename element_reference_type<P>::type       min_(      P& p) { return semantic_at_c<0>(p); }
468 };
469 }  // namespace detail
470
471 /// \defgroup ColorBaseAlgorithmMinMax static_min, static_max
472 /// \ingroup ColorBaseAlgorithm
473 /// \brief Equivalents to std::min_element and std::max_element for homogeneous color bases
474 ///
475 /// Example:
476 /// \code
477 /// rgb8_pixel_t pixel(10,20,30);
478 /// assert(pixel[2] == 30);
479 /// static_max(pixel) = static_min(pixel);
480 /// assert(pixel[2] == 10);
481 /// \endcode
482 /// \{
483
484 template <typename P>
485 BOOST_FORCEINLINE
486 typename element_const_reference_type<P>::type static_max(const P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
487
488 template <typename P>
489 BOOST_FORCEINLINE
490 typename element_reference_type<P>::type       static_max(      P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
491
492 template <typename P>
493 BOOST_FORCEINLINE
494 typename element_const_reference_type<P>::type static_min(const P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
495
496 template <typename P>
497 BOOST_FORCEINLINE
498 typename element_reference_type<P>::type       static_min(      P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
499 /// \}
500
501 /// \defgroup ColorBaseAlgorithmEqual static_equal
502 /// \ingroup ColorBaseAlgorithm
503 /// \brief Equivalent to std::equal. Pairs the elements semantically
504 ///
505 /// Example:
506 /// \code
507 /// rgb8_pixel_t rgb_red(255,0,0);
508 /// bgr8_pixel_t bgr_red(0,0,255);
509 /// assert(rgb_red[0]==255 && bgr_red[0]==0);
510 ///
511 /// assert(static_equal(rgb_red,bgr_red));
512 /// assert(rgb_red==bgr_red);  // operator== invokes static_equal
513 /// \endcode
514 /// \{
515
516 template <typename P1,typename P2>
517 BOOST_FORCEINLINE
518 bool static_equal(const P1& p1, const P2& p2) { return detail::element_recursion<size<P1>::value>::static_equal(p1,p2); }
519
520 /// \}
521
522 /// \defgroup ColorBaseAlgorithmCopy static_copy
523 /// \ingroup ColorBaseAlgorithm
524 /// \brief Equivalent to std::copy. Pairs the elements semantically
525 ///
526 /// Example:
527 /// \code
528 /// rgb8_pixel_t rgb_red(255,0,0);
529 /// bgr8_pixel_t bgr_red;
530 /// static_copy(rgb_red, bgr_red);  // same as bgr_red = rgb_red
531 ///
532 /// assert(rgb_red[0] == 255 && bgr_red[0] == 0);
533 /// assert(rgb_red == bgr_red);
534 /// \endcode
535 /// \{
536
537 template <typename Src,typename Dst>
538 BOOST_FORCEINLINE
539 void static_copy(const Src& src, Dst& dst)
540 {
541     detail::element_recursion<size<Dst>::value>::static_copy(src, dst);
542 }
543
544 /// \}
545
546 /// \defgroup ColorBaseAlgorithmFill static_fill
547 /// \ingroup ColorBaseAlgorithm
548 /// \brief Equivalent to std::fill.
549 ///
550 /// Example:
551 /// \code
552 /// rgb8_pixel_t p;
553 /// static_fill(p, 10);
554 /// assert(p == rgb8_pixel_t(10,10,10));
555 /// \endcode
556 /// \{
557
558 template <typename P,typename V>
559 BOOST_FORCEINLINE
560 void static_fill(P& p, const V& v)
561 {
562     detail::element_recursion<size<P>::value>::static_fill(p,v);
563 }
564
565 /// \}
566
567 /// \defgroup ColorBaseAlgorithmGenerate static_generate
568 /// \ingroup ColorBaseAlgorithm
569 /// \brief Equivalent to std::generate.
570 ///
571 /// Example: Set each channel of a pixel to its semantic index. The channels must be assignable from an integer.
572 /// \code
573 /// struct consecutive_fn {
574 ///     int& _current;
575 ///     consecutive_fn(int& start) : _current(start) {}
576 ///     int operator()() { return _current++; }
577 /// };
578 /// rgb8_pixel_t p;
579 /// int start=0;
580 /// static_generate(p, consecutive_fn(start));
581 /// assert(p == rgb8_pixel_t(0,1,2));
582 /// \endcode
583 ///
584 /// \{
585
586 template <typename P1,typename Op>
587 BOOST_FORCEINLINE
588 void static_generate(P1& dst,Op op)                      { detail::element_recursion<size<P1>::value>::static_generate(dst,op); }
589 /// \}
590
591 /// \defgroup ColorBaseAlgorithmTransform static_transform
592 /// \ingroup ColorBaseAlgorithm
593 /// \brief Equivalent to std::transform. Pairs the elements semantically
594 ///
595 /// Example: Write a generic function that adds two pixels into a homogeneous result pixel.
596 /// \code
597 /// template <typename Result>
598 /// struct my_plus {
599 ///     template <typename T1, typename T2>
600 ///     Result operator()(T1 f1, T2 f2) const { return f1+f2; }
601 /// };
602 ///
603 /// template <typename Pixel1, typename Pixel2, typename Pixel3>
604 /// void sum_channels(const Pixel1& p1, const Pixel2& p2, Pixel3& result) {
605 ///     using result_channel_t = typename channel_type<Pixel3>::type;
606 ///     static_transform(p1,p2,result,my_plus<result_channel_t>());
607 /// }
608 ///
609 /// rgb8_pixel_t p1(1,2,3);
610 /// bgr8_pixel_t p2(3,2,1);
611 /// rgb8_pixel_t result;
612 /// sum_channels(p1,p2,result);
613 /// assert(result == rgb8_pixel_t(2,4,6));
614 /// \endcode
615 /// \{
616
617 //static_transform with one source
618 template <typename Src,typename Dst,typename Op>
619 BOOST_FORCEINLINE
620 Op static_transform(Src& src,Dst& dst,Op op)              { return detail::element_recursion<size<Dst>::value>::static_transform(src,dst,op); }
621 template <typename Src,typename Dst,typename Op>
622 BOOST_FORCEINLINE
623 Op static_transform(const Src& src,Dst& dst,Op op)              { return detail::element_recursion<size<Dst>::value>::static_transform(src,dst,op); }
624 //static_transform with two sources
625 template <typename P2,typename P3,typename Dst,typename Op>
626 BOOST_FORCEINLINE
627 Op static_transform(P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
628 template <typename P2,typename P3,typename Dst,typename Op>
629 BOOST_FORCEINLINE
630 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); }
631 template <typename P2,typename P3,typename Dst,typename Op>
632 BOOST_FORCEINLINE
633 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); }
634 template <typename P2,typename P3,typename Dst,typename Op>
635 BOOST_FORCEINLINE
636 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); }
637 /// \}
638
639 /// \defgroup ColorBaseAlgorithmForEach static_for_each
640 /// \ingroup ColorBaseAlgorithm
641 /// \brief Equivalent to std::for_each. Pairs the elements semantically
642 ///
643 /// Example: Use static_for_each to increment a planar pixel iterator
644 /// \code
645 /// struct increment {
646 ///     template <typename Incrementable>
647 ///     void operator()(Incrementable& x) const { ++x; }
648 /// };
649 ///
650 /// template <typename ColorBase>
651 /// void increment_elements(ColorBase& cb) {
652 ///     static_for_each(cb, increment());
653 /// }
654 ///
655 /// uint8_t red[2], green[2], blue[2];
656 /// rgb8c_planar_ptr_t p1(red,green,blue);
657 /// rgb8c_planar_ptr_t p2=p1;
658 /// increment_elements(p1);
659 /// ++p2;
660 /// assert(p1 == p2);
661 /// \endcode
662 /// \{
663
664 //static_for_each with one source
665 template <typename P1,typename Op>
666 BOOST_FORCEINLINE
667 Op static_for_each(      P1& p1, Op op)                          { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); }
668 template <typename P1,typename Op>
669 BOOST_FORCEINLINE
670 Op static_for_each(const P1& p1, Op op)                          { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); }
671 //static_for_each with two sources
672 template <typename P1,typename P2,typename Op>
673 BOOST_FORCEINLINE
674 Op static_for_each(P1& p1,      P2& p2, Op op)             { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
675 template <typename P1,typename P2,typename Op>
676 BOOST_FORCEINLINE
677 Op static_for_each(P1& p1,const P2& p2, Op op)             { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
678 template <typename P1,typename P2,typename Op>
679 BOOST_FORCEINLINE
680 Op static_for_each(const P1& p1,      P2& p2, Op op)             { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
681 template <typename P1,typename P2,typename Op>
682 BOOST_FORCEINLINE
683 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); }
684 //static_for_each with three sources
685 template <typename P1,typename P2,typename P3,typename Op>
686 BOOST_FORCEINLINE
687 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); }
688 template <typename P1,typename P2,typename P3,typename Op>
689 BOOST_FORCEINLINE
690 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); }
691 template <typename P1,typename P2,typename P3,typename Op>
692 BOOST_FORCEINLINE
693 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); }
694 template <typename P1,typename P2,typename P3,typename Op>
695 BOOST_FORCEINLINE
696 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); }
697 template <typename P1,typename P2,typename P3,typename Op>
698 BOOST_FORCEINLINE
699 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); }
700 template <typename P1,typename P2,typename P3,typename Op>
701 BOOST_FORCEINLINE
702 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); }
703 template <typename P1,typename P2,typename P3,typename Op>
704 BOOST_FORCEINLINE
705 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); }
706 template <typename P1,typename P2,typename P3,typename Op>
707 BOOST_FORCEINLINE
708 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); }
709 ///\}
710
711 } }  // namespace boost::gil
712
713 #endif