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