Boost GIL


color_base.hpp
1 //
2 // Copyright 2005-2007 Adobe Systems Incorporated
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 #ifndef BOOST_GIL_COLOR_BASE_HPP
9 #define BOOST_GIL_COLOR_BASE_HPP
10 
11 #include <boost/gil/utilities.hpp>
12 #include <boost/gil/concepts.hpp>
13 
14 #include <boost/assert.hpp>
15 #include <boost/config.hpp>
16 #include <boost/mpl/range_c.hpp>
17 #include <boost/mpl/size.hpp>
18 #include <boost/mpl/vector_c.hpp>
19 #include <boost/type_traits.hpp>
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>
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 
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>
52 struct mapping_transform
53  : public mpl::at<typename SrcLayout::channel_mapping_t,
54  typename detail::type_to_index<typename DstLayout::channel_mapping_t,mpl::integral_c<int,K> >::type
55  >::type {};
56 
61 
62 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
63 #pragma warning(push)
64 #pragma warning(disable:4512) //assignment operator could not be generated
65 #endif
66 
69 template <typename Element, typename Layout>
70 struct homogeneous_color_base<Element,Layout,1> {
71 private:
72  Element _v0;
73 public:
74  using layout_t = Layout;
75  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
76  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
77 
78  homogeneous_color_base() {}
79  homogeneous_color_base(Element v) : _v0(v) {}
80 
81  // grayscale pixel values are convertible to channel type
82  operator Element () const { return _v0; }
83 
84  template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,1>& c) : _v0(gil::at_c<0>(c)) {}
85 };
86 
87 
90 template <typename Element, typename Layout>
91 struct homogeneous_color_base<Element,Layout,2> {
92 private:
93  Element _v0, _v1;
94 public:
95  using layout_t = Layout;
96  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
97  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
98  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
99  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
100 
101  homogeneous_color_base() {}
102  explicit homogeneous_color_base(Element v) : _v0(v), _v1(v) {}
103  homogeneous_color_base(Element v0, Element v1) : _v0(v0), _v1(v1) {}
104 
105  template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,2>& c) :
106  _v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
107  _v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)) {}
108 
109  // Support for l-value reference proxy copy construction
110  template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,2>& c) :
111  _v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
112  _v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)) {}
113 
114  // Support for planar_pixel_iterator construction and dereferencing
115  template <typename P> homogeneous_color_base(P* p,bool) :
116  _v0(&semantic_at_c<0>(*p)),
117  _v1(&semantic_at_c<1>(*p)) {}
118  template <typename Ref> Ref deref() const {
119  return Ref(*semantic_at_c<0>(*this),
120  *semantic_at_c<1>(*this)); }
121 
122  // Support for planar_pixel_reference offset constructor
123  template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
124  : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
125  _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)) {}
126 
127  // Support for planar_pixel_reference operator[]
128  Element at_c_dynamic(std::size_t i) const {
129  if (i==0) return _v0;
130  return _v1;
131  }
132 };
133 
136 template <typename Element, typename Layout>
137 struct homogeneous_color_base<Element,Layout,3> {
138 private:
139  Element _v0, _v1, _v2;
140 public:
141  using layout_t = Layout;
142  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
143  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
144  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
145  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
146  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) { return _v2; }
147  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
148 
149  homogeneous_color_base() {}
150  explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v) {}
151  homogeneous_color_base(Element v0, Element v1, Element v2) : _v0(v0), _v1(v1), _v2(v2) {}
152 
153  template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,3>& c) :
154  _v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
155  _v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
156  _v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)) {}
157 
158  // Support for l-value reference proxy copy construction
159  template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,3>& c) :
160  _v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
161  _v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
162  _v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)) {}
163 
164  // Support for planar_pixel_iterator construction and dereferencing
165  template <typename P> homogeneous_color_base(P* p,bool) :
166  _v0(&semantic_at_c<0>(*p)),
167  _v1(&semantic_at_c<1>(*p)),
168  _v2(&semantic_at_c<2>(*p)) {}
169  template <typename Ref> Ref deref() const {
170  return Ref(*semantic_at_c<0>(*this),
171  *semantic_at_c<1>(*this),
172  *semantic_at_c<2>(*this)); }
173 
174  // Support for planar_pixel_reference offset constructor
175  template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
176  : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
177  _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
178  _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)) {}
179 
180  // Support for planar_pixel_reference operator[]
181  Element at_c_dynamic(std::size_t i) const {
182  switch (i) {
183  case 0: return _v0;
184  case 1: return _v1;
185  }
186  return _v2;
187  }
188 };
189 
192 template <typename Element, typename Layout>
193 struct homogeneous_color_base<Element,Layout,4> {
194 private:
195  Element _v0, _v1, _v2, _v3;
196 public:
197  using layout_t = Layout;
198  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
199  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
200  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
201  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
202  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) { return _v2; }
203  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
204  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) { return _v3; }
205  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) const { return _v3; }
206  homogeneous_color_base() {}
207  explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v), _v3(v) {}
208  homogeneous_color_base(Element v0, Element v1, Element v2, Element v3) : _v0(v0), _v1(v1), _v2(v2), _v3(v3) {}
209 
210  template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,4>& c) :
211  _v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
212  _v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
213  _v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)),
214  _v3(gil::at_c<mapping_transform<Layout,L2,3>::value>(c)) {}
215 
216  // Support for l-value reference proxy copy construction
217  template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,4>& c) :
218  _v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
219  _v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
220  _v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)),
221  _v3(gil::at_c<mapping_transform<Layout,L2,3>::value>(c)) {}
222 
223  // Support for planar_pixel_iterator construction and dereferencing
224  template <typename P> homogeneous_color_base(P* p,bool) :
225  _v0(&semantic_at_c<0>(*p)),
226  _v1(&semantic_at_c<1>(*p)),
227  _v2(&semantic_at_c<2>(*p)),
228  _v3(&semantic_at_c<3>(*p)) {}
229 
230  template <typename Ref> Ref deref() const {
231  return Ref(*semantic_at_c<0>(*this),
232  *semantic_at_c<1>(*this),
233  *semantic_at_c<2>(*this),
234  *semantic_at_c<3>(*this)); }
235 
236  // Support for planar_pixel_reference offset constructor
237  template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
238  : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
239  _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
240  _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)),
241  _v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)) {}
242 
243  // Support for planar_pixel_reference operator[]
244  Element at_c_dynamic(std::size_t i) const {
245  switch (i) {
246  case 0: return _v0;
247  case 1: return _v1;
248  case 2: return _v2;
249  }
250  return _v3;
251  }
252 };
253 
256 template <typename Element, typename Layout>
257 struct homogeneous_color_base<Element,Layout,5> {
258 private:
259  Element _v0, _v1, _v2, _v3, _v4;
260 public:
261  using layout_t = Layout;
262  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
263  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
264  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
265  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
266  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) { return _v2; }
267  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
268  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) { return _v3; }
269  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) const { return _v3; }
270  typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<4>) { return _v4; }
271  typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<4>) const { return _v4; }
272  homogeneous_color_base() {}
273  explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v), _v3(v), _v4(v) {}
274  homogeneous_color_base(Element v0, Element v1, Element v2, Element v3, Element v4) : _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4) {}
275 
276  template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,5>& c) :
277  _v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
278  _v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
279  _v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)),
280  _v3(gil::at_c<mapping_transform<Layout,L2,3>::value>(c)),
281  _v4(gil::at_c<mapping_transform<Layout,L2,4>::value>(c)) {}
282 
283  // Support for l-value reference proxy copy construction
284  template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,5>& c) :
285  _v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
286  _v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
287  _v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)),
288  _v3(gil::at_c<mapping_transform<Layout,L2,3>::value>(c)),
289  _v4(gil::at_c<mapping_transform<Layout,L2,4>::value>(c)) {}
290 
291  // Support for planar_pixel_iterator construction and dereferencing
292  template <typename P> homogeneous_color_base(P* p,bool) :
293  _v0(&semantic_at_c<0>(*p)),
294  _v1(&semantic_at_c<1>(*p)),
295  _v2(&semantic_at_c<2>(*p)),
296  _v3(&semantic_at_c<3>(*p)),
297  _v4(&semantic_at_c<4>(*p)) {}
298 
299  template <typename Ref> Ref deref() const {
300  return Ref(*semantic_at_c<0>(*this),
301  *semantic_at_c<1>(*this),
302  *semantic_at_c<2>(*this),
303  *semantic_at_c<3>(*this),
304  *semantic_at_c<4>(*this)); }
305 
306  // Support for planar_pixel_reference offset constructor
307  template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
308  : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
309  _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
310  _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)),
311  _v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)),
312  _v4(*memunit_advanced(semantic_at_c<4>(ptr),diff)) {}
313 
314  // Support for planar_pixel_reference operator[]
315  Element at_c_dynamic(std::size_t i) const {
316  switch (i) {
317  case 0: return _v0;
318  case 1: return _v1;
319  case 2: return _v2;
320  case 3: return _v3;
321  }
322  return _v4;
323  }
324 };
325 
326 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
327 #pragma warning(pop)
328 #endif
329 
330 // The following way of casting adjacent channels (the contents of color_base) into an array appears to be unsafe
331 // -- there is no guarantee that the compiler won't add any padding between adjacent channels.
332 // Note, however, that GIL _must_ be compiled with compiler settings ensuring there is no padding in the color base structs.
333 // This is because the color base structs must model the interleaved organization in memory. In other words, the client may
334 // 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)
335 // with no padding. We have tested with char/int/float/double channels on gcc and VC and have so far discovered no problem.
336 // We have even tried using strange channels consisting of short + char (3 bytes). With the default 4-byte alignment on VC, the size
337 // 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.
338 // However, the client must nevertheless ensure that proper compiler settings are used for their compiler and their channel types.
339 
340 template <typename Element, typename Layout, int K>
342 dynamic_at_c(homogeneous_color_base<Element,Layout,K>& cb, std::size_t i)
343 {
344  BOOST_ASSERT(i < K);
345  return (gil_reinterpret_cast<Element*>(&cb))[i];
346 }
347 
348 template <typename Element, typename Layout, int K>
350 dynamic_at_c(const homogeneous_color_base<Element,Layout,K>& cb, std::size_t i) {
351  BOOST_ASSERT(i < K);
352  return (gil_reinterpret_cast_c<const Element*>(&cb))[i];
353 }
354 
355 template <typename Element, typename Layout, int K>
357 dynamic_at_c(const homogeneous_color_base<Element&,Layout,K>& cb, std::size_t i) {
358  BOOST_ASSERT(i < K);
359  return cb.at_c_dynamic(i);
360 }
361 
362 template <typename Element, typename Layout, int K>
364 dynamic_at_c(const homogeneous_color_base<const Element&,Layout,K>& cb, std::size_t i) {
365  BOOST_ASSERT(i < K);
366  return cb.at_c_dynamic(i);
367 }
368 
369 
370 } // namespace detail
371 
372 template <typename Element, typename Layout, int K1, int K>
373 struct kth_element_type<detail::homogeneous_color_base<Element,Layout,K1>, K> {
374  using type = Element;
375 };
376 
377 template <typename Element, typename Layout, int K1, int K>
378 struct kth_element_reference_type<detail::homogeneous_color_base<Element,Layout,K1>, K> : public add_reference<Element> {};
379 
380 template <typename Element, typename Layout, int K1, int K>
381 struct kth_element_const_reference_type<detail::homogeneous_color_base<Element,Layout,K1>, K> : public add_reference<typename add_const<Element>::type> {};
382 
385 template <int K, typename E, typename L, int N> inline
386 typename add_reference<E>::type
387 at_c( detail::homogeneous_color_base<E,L,N>& p) { return p.at(mpl::int_<K>()); }
388 
391 template <int K, typename E, typename L, int N> inline
392 typename add_reference<typename add_const<E>::type>::type
393 at_c(const detail::homogeneous_color_base<E,L,N>& p) { return p.at(mpl::int_<K>()); }
394 
395 namespace detail {
396  struct swap_fn {
397  template <typename T> void operator()(T& x, T& y) const {
398  using std::swap;
399  swap(x,y);
400  }
401  };
402 }
403 template <typename E, typename L, int N> inline
404 void swap(detail::homogeneous_color_base<E,L,N>& x, detail::homogeneous_color_base<E,L,N>& y) {
405  static_for_each(x,y,detail::swap_fn());
406 }
407 
408 
409 } } // namespace boost::gil
410 
411 #endif
Definition: algorithm.hpp:30
void swap(const boost::gil::packed_channel_reference< BF, FB, NB, M > x, R &y)
swap for packed_channel_reference
Definition: channel.hpp:485
kth_semantic_element_const_reference_type< ColorBase, K >::type semantic_at_c(const ColorBase &p)
A constant accessor to the K-th semantic element of a color base.
Definition: color_base_algorithm.hpp:138
Specifies the return type of the constant element accessor at_c of a homogeneous color base...
Definition: color_base.hpp:41
Specifies the return type of the mutable element accessor at_c of a homogeneous color base...
Definition: color_base.hpp:40
add_reference< typename add_const< E >::type >::type at_c(const detail::homogeneous_color_base< E, L, N > &p)
Provides constant access to the K-th element, in physical order.
Definition: color_base.hpp:393