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;
getboost::gil::kth_semantic_element_reference_type98 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;
getboost::gil::kth_semantic_element_const_reference_type112 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
semantic_at_c(ColorBase & p)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
semantic_at_c(ColorBase const & p)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>
get_color(ColorBase & cb,Color=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>
get_color(const ColorBase & cb,Color=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>
static_equalboost::gil::detail::element_recursion248 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>
static_copyboost::gil::detail::element_recursion255 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>
static_fillboost::gil::detail::element_recursion262 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>
static_generateboost::gil::detail::element_recursion269 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>
static_for_eachboost::gil::detail::element_recursion281 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>
static_for_eachboost::gil::detail::element_recursion287 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>
static_for_eachboost::gil::detail::element_recursion294 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>
static_for_eachboost::gil::detail::element_recursion300 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>
static_for_eachboost::gil::detail::element_recursion306 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>
static_for_eachboost::gil::detail::element_recursion312 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>
static_for_eachboost::gil::detail::element_recursion319 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>
static_for_eachboost::gil::detail::element_recursion325 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>
static_for_eachboost::gil::detail::element_recursion331 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>
static_for_eachboost::gil::detail::element_recursion337 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>
static_for_eachboost::gil::detail::element_recursion343 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>
static_for_eachboost::gil::detail::element_recursion349 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>
static_for_eachboost::gil::detail::element_recursion355 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>
static_for_eachboost::gil::detail::element_recursion361 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>
static_transformboost::gil::detail::element_recursion368 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>
static_transformboost::gil::detail::element_recursion374 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>
static_transformboost::gil::detail::element_recursion381 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>
static_transformboost::gil::detail::element_recursion387 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>
static_transformboost::gil::detail::element_recursion393 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>
static_transformboost::gil::detail::element_recursion399 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>
static_equalboost::gil::detail::element_recursion410 static bool static_equal(const P1&, const P2&) { return true; }
411 //static_copy
412 template <typename P1,typename P2>
static_copyboost::gil::detail::element_recursion413 static void static_copy(const P1&, const P2&) {}
414 //static_fill
415 template <typename P, typename T2>
static_fillboost::gil::detail::element_recursion416 static void static_fill(const P&, T2) {}
417 //static_generate
418 template <typename Dst,typename Op>
static_generateboost::gil::detail::element_recursion419 static void static_generate(const Dst&,Op){}
420 //static_for_each with one source
421 template <typename P1,typename Op>
static_for_eachboost::gil::detail::element_recursion422 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>
static_for_eachboost::gil::detail::element_recursion425 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>
static_for_eachboost::gil::detail::element_recursion428 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>
static_transformboost::gil::detail::element_recursion431 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>
static_transformboost::gil::detail::element_recursion434 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...
mutable_min(const Q & x,const Q & y)438 template <typename Q> inline const Q& mutable_min(const Q& x, const Q& y) { return x<y ? x : y; }
mutable_min(Q & x,Q & y)439 template <typename Q> inline Q& mutable_min( Q& x, Q& y) { return x<y ? x : y; }
mutable_max(const Q & x,const Q & y)440 template <typename Q> inline const Q& mutable_max(const Q& x, const Q& y) { return x<y ? y : x; }
mutable_max(Q & x,Q & y)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 {
max_boost::gil::detail::min_max_recur447 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 }
max_boost::gil::detail::min_max_recur450 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 }
min_boost::gil::detail::min_max_recur453 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 }
min_boost::gil::detail::min_max_recur456 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> {
max_boost::gil::detail::min_max_recur464 template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) { return semantic_at_c<0>(p); }
max_boost::gil::detail::min_max_recur465 template <typename P> static typename element_reference_type<P>::type max_( P& p) { return semantic_at_c<0>(p); }
min_boost::gil::detail::min_max_recur466 template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) { return semantic_at_c<0>(p); }
min_boost::gil::detail::min_max_recur467 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
static_max(const P & p)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
static_max(P & p)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
static_min(const P & p)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
static_min(P & p)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
static_equal(const P1 & p1,const P2 & p2)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
static_copy(const Src & src,Dst & dst)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
static_fill(P & p,const V & v)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
static_generate(P1 & dst,Op op)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
static_transform(Src & src,Dst & dst,Op op)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
static_transform(const Src & src,Dst & dst,Op op)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
static_transform(P2 & p2,P3 & p3,Dst & dst,Op op)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
static_transform(P2 & p2,const P3 & p3,Dst & dst,Op op)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
static_transform(const P2 & p2,P3 & p3,Dst & dst,Op op)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
static_transform(const P2 & p2,const P3 & p3,Dst & dst,Op op)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
static_for_each(P1 & p1,Op op)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
static_for_each(const P1 & p1,Op op)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
static_for_each(P1 & p1,P2 & p2,Op op)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
static_for_each(P1 & p1,const P2 & p2,Op op)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
static_for_each(const P1 & p1,P2 & p2,Op op)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
static_for_each(const P1 & p1,const P2 & p2,Op op)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
static_for_each(P1 & p1,P2 & p2,P3 & p3,Op op)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
static_for_each(P1 & p1,P2 & p2,const P3 & p3,Op op)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
static_for_each(P1 & p1,const P2 & p2,P3 & p3,Op op)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
static_for_each(P1 & p1,const P2 & p2,const P3 & p3,Op op)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
static_for_each(const P1 & p1,P2 & p2,P3 & p3,Op op)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
static_for_each(const P1 & p1,P2 & p2,const P3 & p3,Op op)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
static_for_each(const P1 & p1,const P2 & p2,P3 & p3,Op op)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
static_for_each(const P1 & p1,const P2 & p2,const P3 & p3,Op op)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
714