]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/gil/color_base_algorithm.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / gil / color_base_algorithm.hpp
CommitLineData
92f5a8d4
TL
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>
7c673cae
FG
17
18#include <algorithm>
92f5a8d4 19#include <type_traits>
7c673cae
FG
20
21namespace boost { namespace gil {
22
7c673cae 23///////////////////////////////////////
7c673cae 24/// size: Semantic channel size
7c673cae
FG
25///////////////////////////////////////
26
27/**
28\defgroup ColorBaseAlgorithmSize size
29\ingroup ColorBaseAlgorithm
92f5a8d4 30\brief Returns an integral constant type specifying the number of elements in a color base
7c673cae
FG
31
32Example:
33\code
92f5a8d4
TL
34static_assert(size<rgb8_pixel_t>::value == 3, "");
35static_assert(size<cmyk8_planar_ptr_t>::value == 4, "");
7c673cae
FG
36\endcode
37*/
38
92f5a8d4 39/// \brief Returns an integral constant type specifying the number of elements in a color base
7c673cae
FG
40/// \ingroup ColorBaseAlgorithmSize
41template <typename ColorBase>
92f5a8d4 42struct size : public mp11::mp_size<typename ColorBase::layout_t::color_space_t> {};
7c673cae
FG
43
44///////////////////////////////////////
7c673cae 45/// semantic_at_c: Semantic channel accessors
7c673cae
FG
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
53The 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
54independent 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.
55All GIL color base algorithms taking multiple color bases use semantic indexing to access their elements.
56
57Example:
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
92f5a8d4 60using bgr432_pixel_t = packed_pixel_type<uint16_t, mp11::mp_list_c<unsigned,4,3,2>, bgr_layout_t>::type;
7c673cae
FG
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
92f5a8d4 63using red_channel_reference_t = kth_semantic_element_reference_type<bgr432_pixel_t, 0>::type;
7c673cae
FG
64
65// Initialize the pixel to black
66bgr432_pixel_t red_pixel(0,0,0);
67
68// Set the red channel to 100%
69red_channel_reference_t red_channel = semantic_at_c<0>(red_pixel);
92f5a8d4 70red_channel = channel_traits<red_channel_reference_t>::max_value();
7c673cae
FG
71
72\endcode
73*/
74/// \brief Specifies the type of the K-th semantic element of a color base
75/// \ingroup ColorBaseAlgorithmSemanticAtC
92f5a8d4
TL
76template <typename ColorBase, int K>
77struct 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;
7c673cae
FG
85};
86
87/// \brief Specifies the return type of the mutable semantic_at_c<K>(color_base);
88/// \ingroup ColorBaseAlgorithmSemanticAtC
92f5a8d4
TL
89template <typename ColorBase, int K>
90struct 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); }
7c673cae
FG
99};
100
101/// \brief Specifies the return type of the constant semantic_at_c<K>(color_base);
102/// \ingroup ColorBaseAlgorithmSemanticAtC
92f5a8d4
TL
103template <typename ColorBase, int K>
104struct 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); }
7c673cae
FG
113};
114
115/// \brief A mutable accessor to the K-th semantic element of a color base
116/// \ingroup ColorBaseAlgorithmSemanticAtC
92f5a8d4
TL
117template <int K, typename ColorBase>
118inline
119auto 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);
7c673cae
FG
127}
128
129/// \brief A constant accessor to the K-th semantic element of a color base
130/// \ingroup ColorBaseAlgorithmSemanticAtC
92f5a8d4
TL
131template <int K, typename ColorBase>
132inline
133auto 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);
7c673cae
FG
137}
138
139///////////////////////////////////////
7c673cae 140/// get_color: Named channel accessors
7c673cae
FG
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
148Example: A function that takes a generic pixel containing a red channel and sets it to 100%:
149
150\code
151template <typename Pixel>
152void set_red_to_max(Pixel& pixel) {
153 boost::function_requires<MutablePixelConcept<Pixel> >();
92f5a8d4 154 static_assert(contains_color<Pixel, red_t>::value, "");
7c673cae 155
92f5a8d4
TL
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();
7c673cae
FG
158}
159\endcode
160*/
161
162/// \brief A predicate metafunction determining whether a given color base contains a given color
163/// \ingroup ColorBaseAlgorithmColor
164template <typename ColorBase, typename Color>
92f5a8d4
TL
165struct contains_color
166 : mp11::mp_contains<typename ColorBase::layout_t::color_space_t, Color>
167{};
7c673cae
FG
168
169template <typename ColorBase, typename Color>
170struct 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
174template <typename ColorBase, typename Color>
175struct 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
179template <typename ColorBase, typename Color>
180struct 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
184template <typename ColorBase, typename Color>
185struct 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
92f5a8d4 189template <typename ColorBase, typename Color>
7c673cae
FG
190typename 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
92f5a8d4 196template <typename ColorBase, typename Color>
7c673cae
FG
197typename 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
212Example:
213\code
92f5a8d4
TL
214using element_t = element_type<rgb8c_planar_ptr_t>::type;
215static_assert(std::is_same<element_t, const uint8_t*>::value, "");
7c673cae
FG
216\endcode
217*/
218/// \brief Specifies the element type of a homogeneous color base
219/// \ingroup ColorBaseAlgorithmHomogeneous
220template <typename ColorBase>
221struct 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
225template <typename ColorBase>
226struct 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
230template <typename ColorBase>
231struct element_const_reference_type : public kth_element_const_reference_type<ColorBase, 0> {};
232
233
234namespace detail {
235
236// compile-time recursion for per-element operations on color bases
237template <int N>
92f5a8d4
TL
238struct 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
7c673cae 247 template <typename P1,typename P2>
92f5a8d4
TL
248 static bool static_equal(const P1& p1, const P2& p2)
249 {
7c673cae 250 return element_recursion<N-1>::static_equal(p1,p2) &&
92f5a8d4 251 semantic_at_c<N-1>(p1)==semantic_at_c<N-1>(p2);
7c673cae 252 }
92f5a8d4 253
7c673cae 254 template <typename P1,typename P2>
92f5a8d4
TL
255 static void static_copy(const P1& p1, P2& p2)
256 {
7c673cae
FG
257 element_recursion<N-1>::static_copy(p1,p2);
258 semantic_at_c<N-1>(p2)=semantic_at_c<N-1>(p1);
259 }
92f5a8d4 260
7c673cae 261 template <typename P,typename T2>
92f5a8d4
TL
262 static void static_fill(P& p, T2 v)
263 {
7c673cae
FG
264 element_recursion<N-1>::static_fill(p,v);
265 semantic_at_c<N-1>(p)=v;
266 }
92f5a8d4
TL
267
268 template <typename Dst,typename Op>
269 static void static_generate(Dst& dst, Op op)
270 {
7c673cae
FG
271 element_recursion<N-1>::static_generate(dst,op);
272 semantic_at_c<N-1>(dst)=op();
273 }
92f5a8d4
TL
274
275#if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
276#pragma GCC diagnostic pop
277#endif
278
7c673cae 279 //static_for_each with one source
92f5a8d4 280 template <typename P1,typename Op>
7c673cae
FG
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 }
92f5a8d4 286 template <typename P1,typename Op>
7c673cae
FG
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
92f5a8d4 293 template <typename P1,typename P2,typename Op>
7c673cae
FG
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 }
92f5a8d4 299 template <typename P1,typename P2,typename Op>
7c673cae
FG
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 }
92f5a8d4 305 template <typename P1,typename P2,typename Op>
7c673cae
FG
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 }
92f5a8d4 311 template <typename P1,typename P2,typename Op>
7c673cae
FG
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
92f5a8d4 367 template <typename P1,typename Dst,typename Op>
7c673cae
FG
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 }
92f5a8d4 373 template <typename P1,typename Dst,typename Op>
7c673cae
FG
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
407template<> 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...
438template <typename Q> inline const Q& mutable_min(const Q& x, const Q& y) { return x<y ? x : y; }
439template <typename Q> inline Q& mutable_min( Q& x, Q& y) { return x<y ? x : y; }
440template <typename Q> inline const Q& mutable_max(const Q& x, const Q& y) { return x<y ? y : x; }
441template <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
445template <int N>
446struct 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));
92f5a8d4 449 }
7c673cae
FG
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));
92f5a8d4 452 }
7c673cae
FG
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));
92f5a8d4 455 }
7c673cae
FG
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));
92f5a8d4 458 }
7c673cae
FG
459};
460
461// termination condition of the compile-time recursion for min/max element
462template <>
463struct 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
92f5a8d4
TL
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/// \{
7c673cae
FG
483
484template <typename P>
92f5a8d4 485BOOST_FORCEINLINE
7c673cae
FG
486typename element_const_reference_type<P>::type static_max(const P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
487
488template <typename P>
92f5a8d4 489BOOST_FORCEINLINE
7c673cae
FG
490typename element_reference_type<P>::type static_max( P& p) { return detail::min_max_recur<size<P>::value>::max_(p); }
491
492template <typename P>
92f5a8d4 493BOOST_FORCEINLINE
7c673cae
FG
494typename element_const_reference_type<P>::type static_min(const P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
495
496template <typename P>
92f5a8d4 497BOOST_FORCEINLINE
7c673cae
FG
498typename element_reference_type<P>::type static_min( P& p) { return detail::min_max_recur<size<P>::value>::min_(p); }
499/// \}
500
92f5a8d4
TL
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/// \{
7c673cae
FG
515
516template <typename P1,typename P2>
92f5a8d4 517BOOST_FORCEINLINE
7c673cae
FG
518bool static_equal(const P1& p1, const P2& p2) { return detail::element_recursion<size<P1>::value>::static_equal(p1,p2); }
519
520/// \}
521
92f5a8d4
TL
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/// \{
7c673cae
FG
536
537template <typename Src,typename Dst>
92f5a8d4
TL
538BOOST_FORCEINLINE
539void static_copy(const Src& src, Dst& dst)
540{
541 detail::element_recursion<size<Dst>::value>::static_copy(src, dst);
542}
7c673cae
FG
543
544/// \}
545
92f5a8d4
TL
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/// \{
7c673cae 557
7c673cae 558template <typename P,typename V>
92f5a8d4
TL
559BOOST_FORCEINLINE
560void static_fill(P& p, const V& v)
561{
562 detail::element_recursion<size<P>::value>::static_fill(p,v);
563}
7c673cae 564
92f5a8d4 565/// \}
7c673cae 566
92f5a8d4
TL
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/// \{
7c673cae
FG
585
586template <typename P1,typename Op>
92f5a8d4 587BOOST_FORCEINLINE
7c673cae
FG
588void static_generate(P1& dst,Op op) { detail::element_recursion<size<P1>::value>::static_generate(dst,op); }
589/// \}
590
92f5a8d4
TL
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/// \{
7c673cae
FG
616
617//static_transform with one source
618template <typename Src,typename Dst,typename Op>
92f5a8d4 619BOOST_FORCEINLINE
7c673cae
FG
620Op static_transform(Src& src,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(src,dst,op); }
621template <typename Src,typename Dst,typename Op>
92f5a8d4 622BOOST_FORCEINLINE
7c673cae
FG
623Op 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
625template <typename P2,typename P3,typename Dst,typename Op>
92f5a8d4 626BOOST_FORCEINLINE
7c673cae
FG
627Op static_transform(P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
628template <typename P2,typename P3,typename Dst,typename Op>
92f5a8d4 629BOOST_FORCEINLINE
7c673cae
FG
630Op static_transform(P2& p2,const P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
631template <typename P2,typename P3,typename Dst,typename Op>
92f5a8d4 632BOOST_FORCEINLINE
7c673cae
FG
633Op static_transform(const P2& p2,P3& p3,Dst& dst,Op op) { return detail::element_recursion<size<Dst>::value>::static_transform(p2,p3,dst,op); }
634template <typename P2,typename P3,typename Dst,typename Op>
92f5a8d4 635BOOST_FORCEINLINE
7c673cae
FG
636Op 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
92f5a8d4
TL
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/// \{
7c673cae
FG
663
664//static_for_each with one source
665template <typename P1,typename Op>
92f5a8d4 666BOOST_FORCEINLINE
7c673cae
FG
667Op static_for_each( P1& p1, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,op); }
668template <typename P1,typename Op>
92f5a8d4 669BOOST_FORCEINLINE
7c673cae
FG
670Op 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
672template <typename P1,typename P2,typename Op>
92f5a8d4 673BOOST_FORCEINLINE
7c673cae
FG
674Op static_for_each(P1& p1, P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
675template <typename P1,typename P2,typename Op>
92f5a8d4 676BOOST_FORCEINLINE
7c673cae
FG
677Op static_for_each(P1& p1,const P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
678template <typename P1,typename P2,typename Op>
92f5a8d4 679BOOST_FORCEINLINE
7c673cae
FG
680Op static_for_each(const P1& p1, P2& p2, Op op) { return detail::element_recursion<size<P1>::value>::static_for_each(p1,p2,op); }
681template <typename P1,typename P2,typename Op>
92f5a8d4 682BOOST_FORCEINLINE
7c673cae
FG
683Op 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
685template <typename P1,typename P2,typename P3,typename Op>
92f5a8d4 686BOOST_FORCEINLINE
7c673cae
FG
687Op 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); }
688template <typename P1,typename P2,typename P3,typename Op>
92f5a8d4 689BOOST_FORCEINLINE
7c673cae
FG
690Op 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); }
691template <typename P1,typename P2,typename P3,typename Op>
92f5a8d4 692BOOST_FORCEINLINE
7c673cae
FG
693Op 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); }
694template <typename P1,typename P2,typename P3,typename Op>
92f5a8d4 695BOOST_FORCEINLINE
7c673cae
FG
696Op 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); }
697template <typename P1,typename P2,typename P3,typename Op>
92f5a8d4 698BOOST_FORCEINLINE
7c673cae
FG
699Op 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); }
700template <typename P1,typename P2,typename P3,typename Op>
92f5a8d4 701BOOST_FORCEINLINE
7c673cae
FG
702Op 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); }
703template <typename P1,typename P2,typename P3,typename Op>
92f5a8d4 704BOOST_FORCEINLINE
7c673cae
FG
705Op 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); }
706template <typename P1,typename P2,typename P3,typename Op>
92f5a8d4 707BOOST_FORCEINLINE
7c673cae
FG
708Op 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