]>
Commit | Line | Data |
---|---|---|
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 | |
21 | namespace 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 | |
32 | Example: | |
33 | \code | |
92f5a8d4 TL |
34 | static_assert(size<rgb8_pixel_t>::value == 3, ""); |
35 | static_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 |
41 | template <typename ColorBase> | |
92f5a8d4 | 42 | struct 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 | ||
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 | |
92f5a8d4 | 60 | using 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 | 63 | using red_channel_reference_t = kth_semantic_element_reference_type<bgr432_pixel_t, 0>::type; |
7c673cae FG |
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); | |
92f5a8d4 | 70 | red_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 |
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; | |
7c673cae FG |
85 | }; |
86 | ||
87 | /// \brief Specifies the return type of the mutable semantic_at_c<K>(color_base); | |
88 | /// \ingroup ColorBaseAlgorithmSemanticAtC | |
92f5a8d4 TL |
89 | template <typename ColorBase, int K> |
90 | struct kth_semantic_element_reference_type | |
91 | { | |
92 | using channel_mapping_t = typename ColorBase::layout_t::channel_mapping_t; | |
93 | static_assert(K < mp11::mp_size<channel_mapping_t>::value, | |
94 | "K index should be less than size of channel_mapping_t sequence"); | |
95 | ||
96 | static constexpr int semantic_index = mp11::mp_at_c<channel_mapping_t, K>::type::value; | |
97 | using type = typename kth_element_reference_type<ColorBase, semantic_index>::type; | |
98 | static type get(ColorBase& cb) { return gil::at_c<semantic_index>(cb); } | |
7c673cae FG |
99 | }; |
100 | ||
101 | /// \brief Specifies the return type of the constant semantic_at_c<K>(color_base); | |
102 | /// \ingroup ColorBaseAlgorithmSemanticAtC | |
92f5a8d4 TL |
103 | template <typename ColorBase, int K> |
104 | struct kth_semantic_element_const_reference_type | |
105 | { | |
106 | using channel_mapping_t = typename ColorBase::layout_t::channel_mapping_t; | |
107 | static_assert(K < mp11::mp_size<channel_mapping_t>::value, | |
108 | "K index should be less than size of channel_mapping_t sequence"); | |
109 | ||
110 | static constexpr int semantic_index = mp11::mp_at_c<channel_mapping_t, K>::type::value; | |
111 | using type = typename kth_element_const_reference_type<ColorBase,semantic_index>::type; | |
112 | static type get(const ColorBase& cb) { return gil::at_c<semantic_index>(cb); } | |
7c673cae FG |
113 | }; |
114 | ||
115 | /// \brief A mutable accessor to the K-th semantic element of a color base | |
116 | /// \ingroup ColorBaseAlgorithmSemanticAtC | |
92f5a8d4 TL |
117 | template <int K, typename ColorBase> |
118 | inline | |
119 | auto semantic_at_c(ColorBase& p) | |
120 | -> typename std::enable_if | |
121 | < | |
122 | !std::is_const<ColorBase>::value, | |
123 | typename kth_semantic_element_reference_type<ColorBase, K>::type | |
124 | >::type | |
125 | { | |
126 | return kth_semantic_element_reference_type<ColorBase, K>::get(p); | |
7c673cae FG |
127 | } |
128 | ||
129 | /// \brief A constant accessor to the K-th semantic element of a color base | |
130 | /// \ingroup ColorBaseAlgorithmSemanticAtC | |
92f5a8d4 TL |
131 | template <int K, typename ColorBase> |
132 | inline | |
133 | auto semantic_at_c(ColorBase const& p) | |
134 | -> typename kth_semantic_element_const_reference_type<ColorBase, K>::type | |
135 | { | |
136 | return kth_semantic_element_const_reference_type<ColorBase, K>::get(p); | |
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 | ||
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> >(); | |
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 | |
164 | template <typename ColorBase, typename Color> | |
92f5a8d4 TL |
165 | struct contains_color |
166 | : mp11::mp_contains<typename ColorBase::layout_t::color_space_t, Color> | |
167 | {}; | |
7c673cae FG |
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 | |
92f5a8d4 | 189 | template <typename ColorBase, typename Color> |
7c673cae FG |
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 | |
92f5a8d4 | 196 | template <typename ColorBase, typename Color> |
7c673cae FG |
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 | |
92f5a8d4 TL |
214 | using element_t = element_type<rgb8c_planar_ptr_t>::type; |
215 | static_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 | |
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> | |
92f5a8d4 TL |
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 | ||
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 | |
407 | template<> struct element_recursion<0> { | |
408 | //static_equal | |
409 | template <typename P1,typename P2> | |
410 | static bool static_equal(const P1&, const P2&) { return true; } | |
411 | //static_copy | |
412 | template <typename P1,typename P2> | |
413 | static void static_copy(const P1&, const P2&) {} | |
414 | //static_fill | |
415 | template <typename P, typename T2> | |
416 | static void static_fill(const P&, T2) {} | |
417 | //static_generate | |
418 | template <typename Dst,typename Op> | |
419 | static void static_generate(const Dst&,Op){} | |
420 | //static_for_each with one source | |
421 | template <typename P1,typename Op> | |
422 | static Op static_for_each(const P1&,Op op){return op;} | |
423 | //static_for_each with two sources | |
424 | template <typename P1,typename P2,typename Op> | |
425 | static Op static_for_each(const P1&,const P2&,Op op){return op;} | |
426 | //static_for_each with three sources | |
427 | template <typename P1,typename P2,typename P3,typename Op> | |
428 | static Op static_for_each(const P1&,const P2&,const P3&,Op op){return op;} | |
429 | //static_transform with one source | |
430 | template <typename P1,typename Dst,typename Op> | |
431 | static Op static_transform(const P1&,const Dst&,Op op){return op;} | |
432 | //static_transform with two sources | |
433 | template <typename P1,typename P2,typename Dst,typename Op> | |
434 | static Op static_transform(const P1&,const P2&,const Dst&,Op op){return op;} | |
435 | }; | |
436 | ||
437 | // std::min and std::max don't have the mutable overloads... | |
438 | template <typename Q> inline const Q& mutable_min(const Q& x, const Q& y) { return x<y ? x : y; } | |
439 | template <typename Q> inline Q& mutable_min( Q& x, Q& y) { return x<y ? x : y; } | |
440 | template <typename Q> inline const Q& mutable_max(const Q& x, const Q& y) { return x<y ? y : x; } | |
441 | template <typename Q> inline Q& mutable_max( Q& x, Q& y) { return x<y ? y : x; } | |
442 | ||
443 | ||
444 | // compile-time recursion for min/max element | |
445 | template <int N> | |
446 | struct min_max_recur { | |
447 | template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) { | |
448 | return mutable_max(min_max_recur<N-1>::max_(p),semantic_at_c<N-1>(p)); | |
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 | |
462 | template <> | |
463 | struct min_max_recur<1> { | |
464 | template <typename P> static typename element_const_reference_type<P>::type max_(const P& p) { return semantic_at_c<0>(p); } | |
465 | template <typename P> static typename element_reference_type<P>::type max_( P& p) { return semantic_at_c<0>(p); } | |
466 | template <typename P> static typename element_const_reference_type<P>::type min_(const P& p) { return semantic_at_c<0>(p); } | |
467 | template <typename P> static typename element_reference_type<P>::type min_( P& p) { return semantic_at_c<0>(p); } | |
468 | }; | |
469 | } // namespace detail | |
470 | ||
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 | |
484 | template <typename P> | |
92f5a8d4 | 485 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 489 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 493 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 497 | BOOST_FORCEINLINE |
7c673cae FG |
498 | typename 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 | |
516 | template <typename P1,typename P2> | |
92f5a8d4 | 517 | BOOST_FORCEINLINE |
7c673cae FG |
518 | bool 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 | |
537 | template <typename Src,typename Dst> | |
92f5a8d4 TL |
538 | BOOST_FORCEINLINE |
539 | void static_copy(const Src& src, Dst& dst) | |
540 | { | |
541 | detail::element_recursion<size<Dst>::value>::static_copy(src, dst); | |
542 | } | |
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 | 558 | template <typename P,typename V> |
92f5a8d4 TL |
559 | BOOST_FORCEINLINE |
560 | void static_fill(P& p, const V& v) | |
561 | { | |
562 | detail::element_recursion<size<P>::value>::static_fill(p,v); | |
563 | } | |
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 | |
586 | template <typename P1,typename Op> | |
92f5a8d4 | 587 | BOOST_FORCEINLINE |
7c673cae FG |
588 | void 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 | |
618 | template <typename Src,typename Dst,typename Op> | |
92f5a8d4 | 619 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 622 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 626 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 629 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 632 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 635 | BOOST_FORCEINLINE |
7c673cae FG |
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 | ||
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 | |
665 | template <typename P1,typename Op> | |
92f5a8d4 | 666 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 669 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 673 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 676 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 679 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 682 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 686 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 689 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 692 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 695 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 698 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 701 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 704 | BOOST_FORCEINLINE |
7c673cae FG |
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> | |
92f5a8d4 | 707 | BOOST_FORCEINLINE |
7c673cae FG |
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 |