1/*
2 Copyright 2005-2007 Adobe Systems Incorporated
3
4 Use, modification and distribution are subject to the Boost Software License,
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt).
7
8 See http://stlab.adobe.com/gil for most recent version including documentation.
9*/
10
11/*************************************************************************************************/
12
13#ifndef GIL_COLOR_BASE_HPP
14#define GIL_COLOR_BASE_HPP
15
16////////////////////////////////////////////////////////////////////////////////////////
17/// \file
18/// \brief pixel class and related utilities
19/// \author Lubomir Bourdev and Hailin Jin \n
20/// Adobe Systems Incorporated
21/// \date 2005-2007 \n Last updated on May 6, 2007
22///
23////////////////////////////////////////////////////////////////////////////////////////
24
25#include <cassert>
26#include <boost/mpl/range_c.hpp>
27#include <boost/mpl/size.hpp>
28#include <boost/mpl/vector_c.hpp>
29#include <boost/type_traits.hpp>
30#include <boost/utility/enable_if.hpp>
31
32#include "gil_config.hpp"
33#include "utilities.hpp"
34#include "gil_concept.hpp"
35
36namespace boost { namespace gil {
37
38// Forward-declare
39template <typename P> P* memunit_advanced(const P* p, std::ptrdiff_t diff);
40
41// Forward-declare semantic_at_c
42template <int K, typename ColorBase>
43typename disable_if<is_const<ColorBase>,typename kth_semantic_element_reference_type<ColorBase,K>::type>::type semantic_at_c(ColorBase& p);
44template <int K, typename ColorBase>
45typename kth_semantic_element_const_reference_type<ColorBase,K>::type semantic_at_c(const ColorBase& p);
46
47// Forward declare element_reference_type
48template <typename ColorBase> struct element_reference_type;
49template <typename ColorBase> struct element_const_reference_type;
50template <typename ColorBase, int K> struct kth_element_type;
51template <typename ColorBase, int K> struct kth_element_type<const ColorBase,K> : public kth_element_type<ColorBase,K> {};
52template <typename ColorBase, int K> struct kth_element_reference_type;
53template <typename ColorBase, int K> struct kth_element_reference_type<const ColorBase,K> : public kth_element_reference_type<ColorBase,K> {};
54template <typename ColorBase, int K> struct kth_element_const_reference_type;
55template <typename ColorBase, int K> struct kth_element_const_reference_type<const ColorBase,K> : public kth_element_const_reference_type<ColorBase,K> {};
56
57namespace detail {
58
59template <typename DstLayout, typename SrcLayout, int K>
60struct mapping_transform
61 : public mpl::at<typename SrcLayout::channel_mapping_t,
62 typename detail::type_to_index<typename DstLayout::channel_mapping_t,mpl::integral_c<int,K> >::type
63 >::type {};
64
65/// \defgroup ColorBaseModelHomogeneous detail::homogeneous_color_base
66/// \ingroup ColorBaseModel
67/// \brief A homogeneous color base holding one color element. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
68/// If the element type models Regular, this class models HomogeneousColorBaseValueConcept.
69
70
71/// \brief A homogeneous color base holding one color element. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
72/// \ingroup ColorBaseModelHomogeneous
73template <typename Element, typename Layout>
74struct homogeneous_color_base<Element,Layout,1> {
75private:
76 Element _v0;
77public:
78 typedef Layout layout_t;
79 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
80 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
81
82 homogeneous_color_base() {}
83 homogeneous_color_base(Element v) : _v0(v) {}
84
85 // grayscale pixel values are convertible to channel type
86 operator Element () const { return _v0; }
87
88 template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,1>& c) : _v0(at_c<0>(c)) {}
89};
90
91
92/// \brief A homogeneous color base holding two color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
93/// \ingroup ColorBaseModelHomogeneous
94template <typename Element, typename Layout>
95struct homogeneous_color_base<Element,Layout,2> {
96private:
97 Element _v0, _v1;
98public:
99 typedef Layout layout_t;
100 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
101 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
102 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
103 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
104
105 homogeneous_color_base() {}
106 explicit homogeneous_color_base(Element v) : _v0(v), _v1(v) {}
107 homogeneous_color_base(Element v0, Element v1) : _v0(v0), _v1(v1) {}
108
109 template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,2>& c) :
110 _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
111 _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)) {}
112
113 // Support for l-value reference proxy copy construction
114 template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,2>& c) :
115 _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
116 _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)) {}
117
118 // Support for planar_pixel_iterator construction and dereferencing
119 template <typename P> homogeneous_color_base(P* p,bool) :
120 _v0(&semantic_at_c<0>(*p)),
121 _v1(&semantic_at_c<1>(*p)) {}
122 template <typename Ref> Ref deref() const {
123 return Ref(*semantic_at_c<0>(*this),
124 *semantic_at_c<1>(*this)); }
125
126 // Support for planar_pixel_reference offset constructor
127 template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
128 : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
129 _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)) {}
130
131 // Support for planar_pixel_reference operator[]
132 Element at_c_dynamic(std::size_t i) const {
133 if (i==0) return _v0;
134 return _v1;
135 }
136};
137
138/// \brief A homogeneous color base holding three color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
139/// \ingroup ColorBaseModelHomogeneous
140template <typename Element, typename Layout>
141struct homogeneous_color_base<Element,Layout,3> {
142private:
143 Element _v0, _v1, _v2;
144public:
145 typedef Layout layout_t;
146 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
147 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
148 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
149 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
150 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) { return _v2; }
151 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
152
153 homogeneous_color_base() {}
154 explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v) {}
155 homogeneous_color_base(Element v0, Element v1, Element v2) : _v0(v0), _v1(v1), _v2(v2) {}
156
157 template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,3>& c) :
158 _v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
159 _v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
160 _v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)) {}
161
162 // Support for l-value reference proxy copy construction
163 template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,3>& c) :
164 _v0(gil::at_c<mapping_transform<Layout,L2,0>::value>(c)),
165 _v1(gil::at_c<mapping_transform<Layout,L2,1>::value>(c)),
166 _v2(gil::at_c<mapping_transform<Layout,L2,2>::value>(c)) {}
167
168 // Support for planar_pixel_iterator construction and dereferencing
169 template <typename P> homogeneous_color_base(P* p,bool) :
170 _v0(&semantic_at_c<0>(*p)),
171 _v1(&semantic_at_c<1>(*p)),
172 _v2(&semantic_at_c<2>(*p)) {}
173 template <typename Ref> Ref deref() const {
174 return Ref(*semantic_at_c<0>(*this),
175 *semantic_at_c<1>(*this),
176 *semantic_at_c<2>(*this)); }
177
178 // Support for planar_pixel_reference offset constructor
179 template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
180 : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
181 _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
182 _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)) {}
183
184 // Support for planar_pixel_reference operator[]
185 Element at_c_dynamic(std::size_t i) const {
186 switch (i) {
187 case 0: return _v0;
188 case 1: return _v1;
189 }
190 return _v2;
191 }
192};
193
194/// \brief A homogeneous color base holding four color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
195/// \ingroup ColorBaseModelHomogeneous
196template <typename Element, typename Layout>
197struct homogeneous_color_base<Element,Layout,4> {
198private:
199 Element _v0, _v1, _v2, _v3;
200public:
201 typedef Layout layout_t;
202 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
203 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
204 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
205 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
206 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) { return _v2; }
207 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
208 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) { return _v3; }
209 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) const { return _v3; }
210 homogeneous_color_base() {}
211 explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v), _v3(v) {}
212 homogeneous_color_base(Element v0, Element v1, Element v2, Element v3) : _v0(v0), _v1(v1), _v2(v2), _v3(v3) {}
213
214 template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,4>& c) :
215 _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
216 _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)),
217 _v2(at_c<mapping_transform<Layout,L2,2>::value>(c)),
218 _v3(at_c<mapping_transform<Layout,L2,3>::value>(c)) {}
219
220 // Support for l-value reference proxy copy construction
221 template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,4>& c) :
222 _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
223 _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)),
224 _v2(at_c<mapping_transform<Layout,L2,2>::value>(c)),
225 _v3(at_c<mapping_transform<Layout,L2,3>::value>(c)) {}
226
227 // Support for planar_pixel_iterator construction and dereferencing
228 template <typename P> homogeneous_color_base(P* p,bool) :
229 _v0(&semantic_at_c<0>(*p)),
230 _v1(&semantic_at_c<1>(*p)),
231 _v2(&semantic_at_c<2>(*p)),
232 _v3(&semantic_at_c<3>(*p)) {}
233
234 template <typename Ref> Ref deref() const {
235 return Ref(*semantic_at_c<0>(*this),
236 *semantic_at_c<1>(*this),
237 *semantic_at_c<2>(*this),
238 *semantic_at_c<3>(*this)); }
239
240 // Support for planar_pixel_reference offset constructor
241 template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
242 : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
243 _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
244 _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)),
245 _v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)) {}
246
247 // Support for planar_pixel_reference operator[]
248 Element at_c_dynamic(std::size_t i) const {
249 switch (i) {
250 case 0: return _v0;
251 case 1: return _v1;
252 case 2: return _v2;
253 }
254 return _v3;
255 }
256};
257
258/// \brief A homogeneous color base holding five color elements. Models HomogeneousColorBaseConcept or HomogeneousColorBaseValueConcept
259/// \ingroup ColorBaseModelHomogeneous
260template <typename Element, typename Layout>
261struct homogeneous_color_base<Element,Layout,5> {
262private:
263 Element _v0, _v1, _v2, _v3, _v4;
264public:
265 typedef Layout layout_t;
266 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) { return _v0; }
267 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<0>) const { return _v0; }
268 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) { return _v1; }
269 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<1>) const { return _v1; }
270 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) { return _v2; }
271 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<2>) const { return _v2; }
272 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) { return _v3; }
273 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<3>) const { return _v3; }
274 typename element_reference_type<homogeneous_color_base>::type at(mpl::int_<4>) { return _v4; }
275 typename element_const_reference_type<homogeneous_color_base>::type at(mpl::int_<4>) const { return _v4; }
276 homogeneous_color_base() {}
277 explicit homogeneous_color_base(Element v) : _v0(v), _v1(v), _v2(v), _v3(v), _v4(v) {}
278 homogeneous_color_base(Element v0, Element v1, Element v2, Element v3, Element v4) : _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4) {}
279
280 template <typename E2, typename L2> homogeneous_color_base(const homogeneous_color_base<E2,L2,5>& c) :
281 _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
282 _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)),
283 _v2(at_c<mapping_transform<Layout,L2,2>::value>(c)),
284 _v3(at_c<mapping_transform<Layout,L2,3>::value>(c)),
285 _v4(at_c<mapping_transform<Layout,L2,4>::value>(c)) {}
286
287 // Support for l-value reference proxy copy construction
288 template <typename E2, typename L2> homogeneous_color_base( homogeneous_color_base<E2,L2,5>& c) :
289 _v0(at_c<mapping_transform<Layout,L2,0>::value>(c)),
290 _v1(at_c<mapping_transform<Layout,L2,1>::value>(c)),
291 _v2(at_c<mapping_transform<Layout,L2,2>::value>(c)),
292 _v3(at_c<mapping_transform<Layout,L2,3>::value>(c)),
293 _v4(at_c<mapping_transform<Layout,L2,4>::value>(c)) {}
294
295 // Support for planar_pixel_iterator construction and dereferencing
296 template <typename P> homogeneous_color_base(P* p,bool) :
297 _v0(&semantic_at_c<0>(*p)),
298 _v1(&semantic_at_c<1>(*p)),
299 _v2(&semantic_at_c<2>(*p)),
300 _v3(&semantic_at_c<3>(*p)),
301 _v4(&semantic_at_c<4>(*p)) {}
302
303 template <typename Ref> Ref deref() const {
304 return Ref(*semantic_at_c<0>(*this),
305 *semantic_at_c<1>(*this),
306 *semantic_at_c<2>(*this),
307 *semantic_at_c<3>(*this),
308 *semantic_at_c<4>(*this)); }
309
310 // Support for planar_pixel_reference offset constructor
311 template <typename Ptr> homogeneous_color_base(const Ptr& ptr, std::ptrdiff_t diff)
312 : _v0(*memunit_advanced(semantic_at_c<0>(ptr),diff)),
313 _v1(*memunit_advanced(semantic_at_c<1>(ptr),diff)),
314 _v2(*memunit_advanced(semantic_at_c<2>(ptr),diff)),
315 _v3(*memunit_advanced(semantic_at_c<3>(ptr),diff)),
316 _v4(*memunit_advanced(semantic_at_c<4>(ptr),diff)) {}
317
318 // Support for planar_pixel_reference operator[]
319 Element at_c_dynamic(std::size_t i) const {
320 switch (i) {
321 case 0: return _v0;
322 case 1: return _v1;
323 case 2: return _v2;
324 case 3: return _v3;
325 }
326 return _v4;
327 }
328};
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
340template <typename Element, typename Layout, int K>
341typename element_reference_type<homogeneous_color_base<Element,Layout,K> >::type
342dynamic_at_c(homogeneous_color_base<Element,Layout,K>& cb, std::size_t i) {
343 assert(i<K);
344 return (gil_reinterpret_cast<Element*>(&cb))[i];
345}
346
347template <typename Element, typename Layout, int K>
348typename element_const_reference_type<homogeneous_color_base<Element,Layout,K> >::type
349dynamic_at_c(const homogeneous_color_base<Element,Layout,K>& cb, std::size_t i) {
350 assert(i<K);
351 return (gil_reinterpret_cast_c<const Element*>(&cb))[i];
352}
353
354template <typename Element, typename Layout, int K>
355typename element_reference_type<homogeneous_color_base<Element&,Layout,K> >::type
356dynamic_at_c(const homogeneous_color_base<Element&,Layout,K>& cb, std::size_t i) {
357 assert(i<K);
358 return cb.at_c_dynamic(i);
359}
360
361template <typename Element, typename Layout, int K>
362typename element_const_reference_type<homogeneous_color_base<const Element&,Layout,K> >::type
363dynamic_at_c(const homogeneous_color_base<const Element&,Layout,K>& cb, std::size_t i) {
364 assert(i<K);
365 return cb.at_c_dynamic(i);
366}
367
368
369} // namespace detail
370
371template <typename Element, typename Layout, int K1, int K>
372struct kth_element_type<detail::homogeneous_color_base<Element,Layout,K1>, K> {
373 typedef Element type;
374};
375
376template <typename Element, typename Layout, int K1, int K>
377struct kth_element_reference_type<detail::homogeneous_color_base<Element,Layout,K1>, K> : public add_reference<Element> {};
378
379template <typename Element, typename Layout, int K1, int K>
380struct kth_element_const_reference_type<detail::homogeneous_color_base<Element,Layout,K1>, K> : public add_reference<typename add_const<Element>::type> {};
381
382/// \brief Provides mutable access to the K-th element, in physical order
383/// \ingroup ColorBaseModelHomogeneous
384template <int K, typename E, typename L, int N> inline
385typename add_reference<E>::type
386at_c( detail::homogeneous_color_base<E,L,N>& p) { return p.at(mpl::int_<K>()); }
387
388/// \brief Provides constant access to the K-th element, in physical order
389/// \ingroup ColorBaseModelHomogeneous
390template <int K, typename E, typename L, int N> inline
391typename add_reference<typename add_const<E>::type>::type
392at_c(const detail::homogeneous_color_base<E,L,N>& p) { return p.at(mpl::int_<K>()); }
393
394namespace detail {
395 struct swap_fn {
396 template <typename T> void operator()(T& x, T& y) const {
397 using std::swap;
398 swap(x,y);
399 }
400 };
401}
402template <typename E, typename L, int N> inline
403void swap(detail::homogeneous_color_base<E,L,N>& x, detail::homogeneous_color_base<E,L,N>& y) {
404 static_for_each(x,y,detail::swap_fn());
405}
406
407
408} } // namespace boost::gil
409
410#endif
411

source code of boost/boost/gil/color_base.hpp