]>
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_HPP | |
10 | #define BOOST_GIL_COLOR_BASE_HPP | |
11 | ||
12 | #include <boost/gil/utilities.hpp> | |
13 | #include <boost/gil/concepts.hpp> | |
14 | #include <boost/gil/detail/mp11.hpp> | |
15 | ||
16 | #include <boost/assert.hpp> | |
17 | #include <boost/config.hpp> | |
18 | ||
19 | #include <type_traits> | |
7c673cae FG |
20 | |
21 | namespace boost { namespace gil { | |
22 | ||
23 | // Forward-declare | |
24 | template <typename P> P* memunit_advanced(const P* p, std::ptrdiff_t diff); | |
25 | ||
26 | // Forward-declare semantic_at_c | |
27 | template <int K, typename ColorBase> | |
92f5a8d4 TL |
28 | auto semantic_at_c(ColorBase& p) |
29 | -> typename std::enable_if | |
30 | < | |
31 | !std::is_const<ColorBase>::value, | |
32 | typename kth_semantic_element_reference_type<ColorBase, K>::type | |
33 | >::type; | |
34 | ||
35 | ||
7c673cae FG |
36 | template <int K, typename ColorBase> |
37 | typename kth_semantic_element_const_reference_type<ColorBase,K>::type semantic_at_c(const ColorBase& p); | |
38 | ||
39 | // Forward declare element_reference_type | |
40 | template <typename ColorBase> struct element_reference_type; | |
41 | template <typename ColorBase> struct element_const_reference_type; | |
42 | template <typename ColorBase, int K> struct kth_element_type; | |
43 | template <typename ColorBase, int K> struct kth_element_type<const ColorBase,K> : public kth_element_type<ColorBase,K> {}; | |
44 | template <typename ColorBase, int K> struct kth_element_reference_type; | |
45 | template <typename ColorBase, int K> struct kth_element_reference_type<const ColorBase,K> : public kth_element_reference_type<ColorBase,K> {}; | |
46 | template <typename ColorBase, int K> struct kth_element_const_reference_type; | |
47 | template <typename ColorBase, int K> struct kth_element_const_reference_type<const ColorBase,K> : public kth_element_const_reference_type<ColorBase,K> {}; | |
48 | ||
49 | namespace detail { | |
50 | ||
51 | template <typename DstLayout, typename SrcLayout, int K> | |
92f5a8d4 TL |
52 | struct mapping_transform : mp11::mp_at |
53 | < | |
54 | typename SrcLayout::channel_mapping_t, | |
55 | typename detail::type_to_index | |
56 | < | |
57 | typename DstLayout::channel_mapping_t, | |
58 | std::integral_constant<int, K> | |
59 | > | |
60 | >::type | |
61 | {}; | |
62 | ||
63 | /// \defgroup ColorBaseModelHomogeneous detail::homogeneous_color_base | |
7c673cae | 64 | /// \ingroup ColorBaseModel |
92f5a8d4 TL |
65 | /// \brief A homogeneous color base holding one color element. |
66 | /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept | |
7c673cae FG |
67 | /// If the element type models Regular, this class models HomogeneousColorBaseValueConcept. |
68 | ||
92f5a8d4 TL |
69 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) |
70 | #pragma warning(push) | |
71 | #pragma warning(disable:4512) //assignment operator could not be generated | |
72 | #endif | |
7c673cae | 73 | |
92f5a8d4 TL |
74 | /// \brief A homogeneous color base holding one color element. |
75 | /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept | |
7c673cae FG |
76 | /// \ingroup ColorBaseModelHomogeneous |
77 | template <typename Element, typename Layout> | |
92f5a8d4 TL |
78 | struct homogeneous_color_base<Element, Layout, 1> |
79 | { | |
80 | using layout_t = Layout; | |
81 | ||
82 | homogeneous_color_base() = default; | |
83 | homogeneous_color_base(Element v) : v0_(v) {} | |
84 | ||
85 | template <typename E2, typename L2> | |
86 | homogeneous_color_base(homogeneous_color_base<E2, L2, 1> const& c) | |
87 | : v0_(gil::at_c<0>(c)) | |
88 | {} | |
89 | ||
90 | auto at(std::integral_constant<int, 0>) | |
91 | -> typename element_reference_type<homogeneous_color_base>::type | |
92 | { return v0_; } | |
93 | ||
94 | auto at(std::integral_constant<int, 0>) const | |
95 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
96 | { return v0_; } | |
97 | ||
7c673cae | 98 | // grayscale pixel values are convertible to channel type |
92f5a8d4 TL |
99 | // FIXME: explicit? |
100 | operator Element() const { return v0_; } | |
7c673cae | 101 | |
92f5a8d4 TL |
102 | private: |
103 | Element v0_{}; | |
7c673cae FG |
104 | }; |
105 | ||
92f5a8d4 TL |
106 | /// \brief A homogeneous color base holding two color elements |
107 | /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept | |
7c673cae FG |
108 | /// \ingroup ColorBaseModelHomogeneous |
109 | template <typename Element, typename Layout> | |
92f5a8d4 TL |
110 | struct homogeneous_color_base<Element, Layout, 2> |
111 | { | |
112 | using layout_t = Layout; | |
113 | ||
114 | homogeneous_color_base() = default; | |
115 | explicit homogeneous_color_base(Element v) : v0_(v), v1_(v) {} | |
116 | homogeneous_color_base(Element v0, Element v1) : v0_(v0), v1_(v1) {} | |
117 | ||
118 | template <typename E2, typename L2> | |
119 | homogeneous_color_base(homogeneous_color_base<E2, L2, 2> const& c) | |
120 | : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c)) | |
121 | , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c)) | |
122 | {} | |
7c673cae FG |
123 | |
124 | // Support for l-value reference proxy copy construction | |
92f5a8d4 TL |
125 | template <typename E2, typename L2> |
126 | homogeneous_color_base(homogeneous_color_base<E2, L2, 2>& c) | |
127 | : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c)) | |
128 | , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c)) | |
129 | {} | |
7c673cae FG |
130 | |
131 | // Support for planar_pixel_iterator construction and dereferencing | |
92f5a8d4 TL |
132 | template <typename P> |
133 | homogeneous_color_base(P* p, bool) | |
134 | : v0_(&semantic_at_c<0>(*p)) | |
135 | , v1_(&semantic_at_c<1>(*p)) | |
136 | {} | |
7c673cae FG |
137 | |
138 | // Support for planar_pixel_reference offset constructor | |
92f5a8d4 TL |
139 | template <typename Ptr> |
140 | homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff) | |
141 | : v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff)) | |
142 | , v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff)) | |
143 | {} | |
144 | ||
145 | template <typename Ref> | |
146 | Ref deref() const | |
147 | { | |
148 | return Ref(*semantic_at_c<0>(*this), *semantic_at_c<1>(*this)); | |
149 | } | |
150 | ||
151 | auto at(std::integral_constant<int, 0>) | |
152 | -> typename element_reference_type<homogeneous_color_base>::type | |
153 | { return v0_; } | |
154 | ||
155 | auto at(std::integral_constant<int, 0>) const | |
156 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
157 | { return v0_; } | |
158 | ||
159 | auto at(std::integral_constant<int, 1>) | |
160 | -> typename element_reference_type<homogeneous_color_base>::type | |
161 | { return v1_; } | |
162 | ||
163 | auto at(std::integral_constant<int, 1>) const | |
164 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
165 | { return v1_; } | |
7c673cae FG |
166 | |
167 | // Support for planar_pixel_reference operator[] | |
92f5a8d4 TL |
168 | Element at_c_dynamic(std::size_t i) const |
169 | { | |
170 | if (i == 0) | |
171 | return v0_; | |
172 | else | |
173 | return v1_; | |
7c673cae | 174 | } |
92f5a8d4 TL |
175 | |
176 | private: | |
177 | Element v0_{}; | |
178 | Element v1_{}; | |
7c673cae FG |
179 | }; |
180 | ||
92f5a8d4 TL |
181 | /// \brief A homogeneous color base holding three color elements. |
182 | /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept | |
7c673cae FG |
183 | /// \ingroup ColorBaseModelHomogeneous |
184 | template <typename Element, typename Layout> | |
92f5a8d4 TL |
185 | struct homogeneous_color_base<Element, Layout, 3> |
186 | { | |
187 | using layout_t = Layout; | |
188 | ||
189 | homogeneous_color_base() = default; | |
190 | explicit homogeneous_color_base(Element v) : v0_(v), v1_(v), v2_(v) {} | |
191 | homogeneous_color_base(Element v0, Element v1, Element v2) | |
192 | : v0_(v0), v1_(v1), v2_(v2) | |
193 | {} | |
194 | ||
195 | template <typename E2, typename L2> | |
196 | homogeneous_color_base(homogeneous_color_base<E2, L2, 3> const& c) | |
197 | : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c)) | |
198 | , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c)) | |
199 | , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c)) | |
200 | {} | |
7c673cae FG |
201 | |
202 | // Support for l-value reference proxy copy construction | |
92f5a8d4 TL |
203 | template <typename E2, typename L2> |
204 | homogeneous_color_base(homogeneous_color_base<E2, L2, 3>& c) | |
205 | : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c)) | |
206 | , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c)) | |
207 | , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c)) | |
208 | {} | |
7c673cae FG |
209 | |
210 | // Support for planar_pixel_iterator construction and dereferencing | |
92f5a8d4 TL |
211 | template <typename P> |
212 | homogeneous_color_base(P* p, bool) | |
213 | : v0_(&semantic_at_c<0>(*p)) | |
214 | , v1_(&semantic_at_c<1>(*p)) | |
215 | , v2_(&semantic_at_c<2>(*p)) | |
216 | {} | |
7c673cae FG |
217 | |
218 | // Support for planar_pixel_reference offset constructor | |
92f5a8d4 TL |
219 | template <typename Ptr> |
220 | homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff) | |
221 | : v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff)) | |
222 | , v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff)) | |
223 | , v2_(*memunit_advanced(semantic_at_c<2>(ptr), diff)) | |
224 | {} | |
225 | ||
226 | template <typename Ref> | |
227 | Ref deref() const | |
228 | { | |
229 | return Ref( | |
230 | *semantic_at_c<0>(*this), | |
231 | *semantic_at_c<1>(*this), | |
232 | *semantic_at_c<2>(*this)); | |
233 | } | |
234 | ||
235 | auto at(std::integral_constant<int, 0>) | |
236 | -> typename element_reference_type<homogeneous_color_base>::type | |
237 | { return v0_; } | |
238 | ||
239 | auto at(std::integral_constant<int, 0>) const | |
240 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
241 | { return v0_; } | |
242 | ||
243 | auto at(std::integral_constant<int, 1>) | |
244 | -> typename element_reference_type<homogeneous_color_base>::type | |
245 | { return v1_; } | |
246 | ||
247 | auto at(std::integral_constant<int, 1>) const | |
248 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
249 | { return v1_; } | |
250 | ||
251 | auto at(std::integral_constant<int, 2>) | |
252 | -> typename element_reference_type<homogeneous_color_base>::type | |
253 | { return v2_; } | |
254 | ||
255 | auto at(std::integral_constant<int, 2>) const | |
256 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
257 | { return v2_; } | |
7c673cae FG |
258 | |
259 | // Support for planar_pixel_reference operator[] | |
92f5a8d4 TL |
260 | Element at_c_dynamic(std::size_t i) const |
261 | { | |
262 | switch (i) | |
263 | { | |
264 | case 0: return v0_; | |
265 | case 1: return v1_; | |
7c673cae | 266 | } |
92f5a8d4 | 267 | return v2_; |
7c673cae | 268 | } |
92f5a8d4 TL |
269 | |
270 | private: | |
271 | Element v0_{}; | |
272 | Element v1_{}; | |
273 | Element v2_{}; | |
7c673cae FG |
274 | }; |
275 | ||
92f5a8d4 TL |
276 | /// \brief A homogeneous color base holding four color elements. |
277 | /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept | |
7c673cae FG |
278 | /// \ingroup ColorBaseModelHomogeneous |
279 | template <typename Element, typename Layout> | |
92f5a8d4 TL |
280 | struct homogeneous_color_base<Element, Layout, 4> |
281 | { | |
282 | using layout_t = Layout; | |
283 | ||
284 | homogeneous_color_base() = default; | |
285 | explicit homogeneous_color_base(Element v) : v0_(v), v1_(v), v2_(v), v3_(v) {} | |
286 | homogeneous_color_base(Element v0, Element v1, Element v2, Element v3) | |
287 | : v0_(v0), v1_(v1), v2_(v2), v3_(v3) | |
288 | {} | |
289 | ||
290 | template <typename E2, typename L2> | |
291 | homogeneous_color_base(homogeneous_color_base<E2, L2, 4> const& c) | |
292 | : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c)) | |
293 | , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c)) | |
294 | , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c)) | |
295 | , v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c)) | |
296 | {} | |
7c673cae FG |
297 | |
298 | // Support for l-value reference proxy copy construction | |
92f5a8d4 TL |
299 | template <typename E2, typename L2> |
300 | homogeneous_color_base(homogeneous_color_base<E2, L2, 4>& c) | |
301 | : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c)) | |
302 | , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c)) | |
303 | , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c)) | |
304 | , v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c)) | |
305 | {} | |
7c673cae FG |
306 | |
307 | // Support for planar_pixel_iterator construction and dereferencing | |
92f5a8d4 TL |
308 | template <typename P> |
309 | homogeneous_color_base(P * p, bool) | |
310 | : v0_(&semantic_at_c<0>(*p)) | |
311 | , v1_(&semantic_at_c<1>(*p)) | |
312 | , v2_(&semantic_at_c<2>(*p)) | |
313 | , v3_(&semantic_at_c<3>(*p)) | |
314 | {} | |
7c673cae FG |
315 | |
316 | // Support for planar_pixel_reference offset constructor | |
92f5a8d4 TL |
317 | template <typename Ptr> |
318 | homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff) | |
319 | : v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff)) | |
320 | , v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff)) | |
321 | , v2_(*memunit_advanced(semantic_at_c<2>(ptr), diff)) | |
322 | , v3_(*memunit_advanced(semantic_at_c<3>(ptr), diff)) | |
323 | {} | |
324 | ||
325 | template <typename Ref> | |
326 | Ref deref() const | |
327 | { | |
328 | return Ref( | |
329 | *semantic_at_c<0>(*this), | |
330 | *semantic_at_c<1>(*this), | |
331 | *semantic_at_c<2>(*this), | |
332 | *semantic_at_c<3>(*this)); | |
333 | } | |
334 | ||
335 | auto at(std::integral_constant<int, 0>) | |
336 | -> typename element_reference_type<homogeneous_color_base>::type | |
337 | { return v0_; } | |
338 | ||
339 | auto at(std::integral_constant<int, 0>) const | |
340 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
341 | { return v0_; } | |
342 | ||
343 | auto at(std::integral_constant<int, 1>) | |
344 | -> typename element_reference_type<homogeneous_color_base>::type | |
345 | { return v1_; } | |
346 | ||
347 | auto at(std::integral_constant<int, 1>) const | |
348 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
349 | { return v1_; } | |
350 | ||
351 | auto at(std::integral_constant<int, 2>) | |
352 | -> typename element_reference_type<homogeneous_color_base>::type | |
353 | { return v2_; } | |
354 | ||
355 | auto at(std::integral_constant<int, 2>) const | |
356 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
357 | { return v2_; } | |
358 | ||
359 | auto at(std::integral_constant<int, 3>) | |
360 | -> typename element_reference_type<homogeneous_color_base>::type | |
361 | { return v3_; } | |
362 | ||
363 | auto at(std::integral_constant<int, 3>) const | |
364 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
365 | { return v3_; } | |
7c673cae FG |
366 | |
367 | // Support for planar_pixel_reference operator[] | |
92f5a8d4 TL |
368 | Element at_c_dynamic(std::size_t i) const |
369 | { | |
370 | switch (i) | |
371 | { | |
372 | case 0: return v0_; | |
373 | case 1: return v1_; | |
374 | case 2: return v2_; | |
7c673cae | 375 | } |
92f5a8d4 | 376 | return v3_; |
7c673cae | 377 | } |
92f5a8d4 TL |
378 | |
379 | private: | |
380 | Element v0_{}; | |
381 | Element v1_{}; | |
382 | Element v2_{}; | |
383 | Element v3_{}; | |
7c673cae FG |
384 | }; |
385 | ||
92f5a8d4 TL |
386 | /// \brief A homogeneous color base holding five color elements. |
387 | /// Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept | |
7c673cae FG |
388 | /// \ingroup ColorBaseModelHomogeneous |
389 | template <typename Element, typename Layout> | |
92f5a8d4 TL |
390 | struct homogeneous_color_base<Element, Layout, 5> |
391 | { | |
392 | using layout_t = Layout; | |
393 | ||
394 | homogeneous_color_base() = default; | |
395 | explicit homogeneous_color_base(Element v) | |
396 | : v0_(v), v1_(v), v2_(v), v3_(v), v4_(v) | |
397 | {} | |
398 | ||
399 | homogeneous_color_base(Element v0, Element v1, Element v2, Element v3, Element v4) | |
400 | : v0_(v0), v1_(v1), v2_(v2), v3_(v3), v4_(v4) | |
401 | {} | |
402 | ||
403 | template <typename E2, typename L2> | |
404 | homogeneous_color_base(homogeneous_color_base<E2, L2, 5> const& c) | |
405 | : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c)) | |
406 | , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c)) | |
407 | , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c)) | |
408 | , v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c)) | |
409 | , v4_(gil::at_c<mapping_transform<Layout, L2, 4>::value>(c)) | |
410 | {} | |
7c673cae FG |
411 | |
412 | // Support for l-value reference proxy copy construction | |
92f5a8d4 TL |
413 | template <typename E2, typename L2> |
414 | homogeneous_color_base(homogeneous_color_base<E2, L2, 5>& c) | |
415 | : v0_(gil::at_c<mapping_transform<Layout, L2, 0>::value>(c)) | |
416 | , v1_(gil::at_c<mapping_transform<Layout, L2, 1>::value>(c)) | |
417 | , v2_(gil::at_c<mapping_transform<Layout, L2, 2>::value>(c)) | |
418 | , v3_(gil::at_c<mapping_transform<Layout, L2, 3>::value>(c)) | |
419 | , v4_(gil::at_c<mapping_transform<Layout, L2, 4>::value>(c)) | |
420 | {} | |
7c673cae FG |
421 | |
422 | // Support for planar_pixel_iterator construction and dereferencing | |
92f5a8d4 TL |
423 | template <typename P> |
424 | homogeneous_color_base(P* p, bool) | |
425 | : v0_(&semantic_at_c<0>(*p)) | |
426 | , v1_(&semantic_at_c<1>(*p)) | |
427 | , v2_(&semantic_at_c<2>(*p)) | |
428 | , v3_(&semantic_at_c<3>(*p)) | |
429 | , v4_(&semantic_at_c<4>(*p)) | |
430 | {} | |
7c673cae FG |
431 | |
432 | // Support for planar_pixel_reference offset constructor | |
92f5a8d4 TL |
433 | template <typename Ptr> |
434 | homogeneous_color_base(Ptr const& ptr, std::ptrdiff_t diff) | |
435 | : v0_(*memunit_advanced(semantic_at_c<0>(ptr), diff)) | |
436 | , v1_(*memunit_advanced(semantic_at_c<1>(ptr), diff)) | |
437 | , v2_(*memunit_advanced(semantic_at_c<2>(ptr), diff)) | |
438 | , v3_(*memunit_advanced(semantic_at_c<3>(ptr), diff)) | |
439 | , v4_(*memunit_advanced(semantic_at_c<4>(ptr), diff)) | |
440 | {} | |
441 | ||
442 | ||
443 | auto at(std::integral_constant<int, 0>) | |
444 | -> typename element_reference_type<homogeneous_color_base>::type | |
445 | { return v0_; } | |
446 | ||
447 | auto at(std::integral_constant<int, 0>) const | |
448 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
449 | { return v0_; } | |
450 | ||
451 | auto at(std::integral_constant<int, 1>) | |
452 | -> typename element_reference_type<homogeneous_color_base>::type | |
453 | { return v1_; } | |
454 | ||
455 | auto at(std::integral_constant<int, 1>) const | |
456 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
457 | { return v1_; } | |
458 | ||
459 | auto at(std::integral_constant<int, 2>) | |
460 | -> typename element_reference_type<homogeneous_color_base>::type | |
461 | { return v2_; } | |
462 | ||
463 | auto at(std::integral_constant<int, 2>) const | |
464 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
465 | { return v2_; } | |
466 | ||
467 | auto at(std::integral_constant<int, 3>) | |
468 | -> typename element_reference_type<homogeneous_color_base>::type | |
469 | { return v3_; } | |
470 | ||
471 | auto at(std::integral_constant<int, 3>) const | |
472 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
473 | { return v3_; } | |
474 | ||
475 | auto at(std::integral_constant<int, 4>) | |
476 | -> typename element_reference_type<homogeneous_color_base>::type | |
477 | { return v4_; } | |
478 | ||
479 | auto at(std::integral_constant<int, 4>) const | |
480 | -> typename element_const_reference_type<homogeneous_color_base>::type | |
481 | { return v4_; } | |
482 | ||
483 | template <typename Ref> | |
484 | Ref deref() const | |
485 | { | |
486 | return Ref( | |
487 | *semantic_at_c<0>(*this), | |
488 | *semantic_at_c<1>(*this), | |
489 | *semantic_at_c<2>(*this), | |
490 | *semantic_at_c<3>(*this), | |
491 | *semantic_at_c<4>(*this)); | |
492 | } | |
7c673cae FG |
493 | |
494 | // Support for planar_pixel_reference operator[] | |
92f5a8d4 TL |
495 | Element at_c_dynamic(std::size_t i) const |
496 | { | |
497 | switch (i) | |
498 | { | |
499 | case 0: return v0_; | |
500 | case 1: return v1_; | |
501 | case 2: return v2_; | |
502 | case 3: return v3_; | |
7c673cae | 503 | } |
92f5a8d4 | 504 | return v4_; |
7c673cae | 505 | } |
92f5a8d4 TL |
506 | |
507 | private: | |
508 | Element v0_{}; | |
509 | Element v1_{}; | |
510 | Element v2_{}; | |
511 | Element v3_{}; | |
512 | Element v4_{}; | |
7c673cae FG |
513 | }; |
514 | ||
92f5a8d4 TL |
515 | #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) |
516 | #pragma warning(pop) | |
517 | #endif | |
518 | ||
7c673cae FG |
519 | // The following way of casting adjacent channels (the contents of color_base) into an array appears to be unsafe |
520 | // -- there is no guarantee that the compiler won't add any padding between adjacent channels. | |
521 | // Note, however, that GIL _must_ be compiled with compiler settings ensuring there is no padding in the color base structs. | |
522 | // This is because the color base structs must model the interleaved organization in memory. In other words, the client may | |
523 | // have existing RGB image in the form "RGBRGBRGB..." and we must be able to represent it with an array of RGB color bases (i.e. RGB pixels) | |
524 | // with no padding. We have tested with char/int/float/double channels on gcc and VC and have so far discovered no problem. | |
525 | // We have even tried using strange channels consisting of short + char (3 bytes). With the default 4-byte alignment on VC, the size | |
526 | // of this channel is padded to 4 bytes, so an RGB pixel of it will be 4x3=12 bytes. The code below will still work properly. | |
527 | // However, the client must nevertheless ensure that proper compiler settings are used for their compiler and their channel types. | |
528 | ||
529 | template <typename Element, typename Layout, int K> | |
92f5a8d4 TL |
530 | auto dynamic_at_c(homogeneous_color_base<Element,Layout,K>& cb, std::size_t i) |
531 | -> typename element_reference_type<homogeneous_color_base<Element, Layout, K>>::type | |
532 | { | |
533 | BOOST_ASSERT(i < K); | |
7c673cae FG |
534 | return (gil_reinterpret_cast<Element*>(&cb))[i]; |
535 | } | |
536 | ||
537 | template <typename Element, typename Layout, int K> | |
92f5a8d4 TL |
538 | auto dynamic_at_c(homogeneous_color_base<Element, Layout, K> const& cb, std::size_t i) |
539 | -> typename element_const_reference_type | |
540 | < | |
541 | homogeneous_color_base<Element, Layout, K> | |
542 | >::type | |
543 | { | |
544 | BOOST_ASSERT(i < K); | |
7c673cae FG |
545 | return (gil_reinterpret_cast_c<const Element*>(&cb))[i]; |
546 | } | |
547 | ||
548 | template <typename Element, typename Layout, int K> | |
92f5a8d4 TL |
549 | auto dynamic_at_c(homogeneous_color_base<Element&, Layout, K> const& cb, std::size_t i) |
550 | -> typename element_reference_type | |
551 | < | |
552 | homogeneous_color_base<Element&, Layout, K> | |
553 | >::type | |
554 | { | |
555 | BOOST_ASSERT(i < K); | |
7c673cae FG |
556 | return cb.at_c_dynamic(i); |
557 | } | |
558 | ||
559 | template <typename Element, typename Layout, int K> | |
92f5a8d4 TL |
560 | auto dynamic_at_c( |
561 | homogeneous_color_base<Element const&, Layout, K>const& cb, std::size_t i) | |
562 | -> typename element_const_reference_type | |
563 | < | |
564 | homogeneous_color_base<Element const&, Layout, K> | |
565 | >::type | |
566 | { | |
567 | BOOST_ASSERT(i < K); | |
7c673cae FG |
568 | return cb.at_c_dynamic(i); |
569 | } | |
570 | ||
7c673cae FG |
571 | } // namespace detail |
572 | ||
92f5a8d4 TL |
573 | template <typename Element, typename Layout, int K1, int K> |
574 | struct kth_element_type<detail::homogeneous_color_base<Element, Layout, K1>, K> | |
575 | { | |
576 | using type = Element; | |
7c673cae FG |
577 | }; |
578 | ||
92f5a8d4 TL |
579 | template <typename Element, typename Layout, int K1, int K> |
580 | struct kth_element_reference_type<detail::homogeneous_color_base<Element, Layout, K1>, K> | |
581 | : std::add_lvalue_reference<Element> | |
582 | {}; | |
7c673cae | 583 | |
92f5a8d4 TL |
584 | template <typename Element, typename Layout, int K1, int K> |
585 | struct kth_element_const_reference_type | |
586 | < | |
587 | detail::homogeneous_color_base<Element, Layout, K1>, | |
588 | K | |
589 | > | |
590 | : std::add_lvalue_reference<typename std::add_const<Element>::type> | |
591 | {}; | |
7c673cae FG |
592 | |
593 | /// \brief Provides mutable access to the K-th element, in physical order | |
594 | /// \ingroup ColorBaseModelHomogeneous | |
92f5a8d4 TL |
595 | template <int K, typename E, typename L, int N> |
596 | inline | |
597 | auto at_c(detail::homogeneous_color_base<E, L, N>& p) | |
598 | -> typename std::add_lvalue_reference<E>::type | |
599 | { | |
600 | return p.at(std::integral_constant<int, K>()); | |
601 | } | |
7c673cae FG |
602 | |
603 | /// \brief Provides constant access to the K-th element, in physical order | |
604 | /// \ingroup ColorBaseModelHomogeneous | |
92f5a8d4 TL |
605 | template <int K, typename E, typename L, int N> |
606 | inline | |
607 | auto at_c(const detail::homogeneous_color_base<E, L, N>& p) | |
608 | -> typename std::add_lvalue_reference<typename std::add_const<E>::type>::type | |
609 | { | |
610 | return p.at(std::integral_constant<int, K>()); | |
7c673cae FG |
611 | } |
612 | ||
92f5a8d4 TL |
613 | namespace detail |
614 | { | |
615 | ||
616 | struct swap_fn | |
617 | { | |
618 | template <typename T> | |
619 | void operator()(T& x, T& y) const | |
620 | { | |
621 | using std::swap; | |
622 | swap(x, y); | |
623 | } | |
624 | }; | |
625 | ||
626 | } // namespace detail | |
627 | ||
628 | template <typename E, typename L, int N> | |
629 | inline | |
630 | void swap( | |
631 | detail::homogeneous_color_base<E, L, N>& x, | |
632 | detail::homogeneous_color_base<E, L, N>& y) | |
633 | { | |
634 | static_for_each(x, y, detail::swap_fn()); | |
635 | } | |
7c673cae | 636 | |
92f5a8d4 | 637 | }} // namespace boost::gil |
7c673cae FG |
638 | |
639 | #endif |