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