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://opensource.adobe.com/gil for most recent version including documentation. |
9 | */ |
10 | |
11 | /*************************************************************************************************/ |
12 | |
13 | #ifndef GIL_PACKED_PIXEL_H |
14 | #define GIL_PACKED_PIXEL_H |
15 | |
16 | //////////////////////////////////////////////////////////////////////////////////////// |
17 | /// \file |
18 | /// \brief A model of a heterogeneous pixel whose channels are bit ranges. For example 16-bit RGB in '565' format |
19 | /// \author Lubomir Bourdev and Hailin Jin \n |
20 | /// Adobe Systems Incorporated |
21 | /// \date 2005-2009 \n Last updated on February 20, 2009 |
22 | /// |
23 | //////////////////////////////////////////////////////////////////////////////////////// |
24 | |
25 | #include <functional> |
26 | #include <boost/utility/enable_if.hpp> |
27 | #include <boost/mpl/bool.hpp> |
28 | #include <boost/mpl/front.hpp> |
29 | #include "gil_config.hpp" |
30 | #include "pixel.hpp" |
31 | |
32 | namespace boost { namespace gil { |
33 | |
34 | /// \defgroup ColorBaseModelPackedPixel packed_pixel |
35 | /// \ingroup ColorBaseModel |
36 | /// \brief A heterogeneous color base whose elements are reference proxies to channels in a pixel. Models ColorBaseValueConcept. This class is used to model packed pixels, such as 16-bit packed RGB. |
37 | |
38 | /** |
39 | \defgroup PixelModelPackedPixel packed_pixel |
40 | \ingroup PixelModel |
41 | \brief A heterogeneous pixel used to represent packed pixels with non-byte-aligned channels. Models PixelValueConcept |
42 | |
43 | Example: |
44 | \code |
45 | typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,5,6,5>, rgb_layout_t>::type rgb565_pixel_t; |
46 | BOOST_STATIC_ASSERT((sizeof(rgb565_pixel_t)==2)); |
47 | |
48 | rgb565_pixel_t r565; |
49 | get_color(r565,red_t()) = 31; |
50 | get_color(r565,green_t()) = 63; |
51 | get_color(r565,blue_t()) = 31; |
52 | assert(r565 == rgb565_pixel_t((uint16_t)0xFFFF)); |
53 | \endcode |
54 | */ |
55 | |
56 | /// \ingroup ColorBaseModelPackedPixel PixelModelPackedPixel PixelBasedModel |
57 | /// \brief Heterogeneous pixel value whose channel references can be constructed from the pixel bitfield and their index. Models ColorBaseValueConcept, PixelValueConcept, PixelBasedConcept |
58 | /// Typical use for this is a model of a packed pixel (like 565 RGB) |
59 | template <typename BitField, // A type that holds the bits of the pixel. Typically an integral type, like boost::uint16_t |
60 | typename ChannelRefVec, // An MPL vector whose elements are packed channels. They must be constructible from BitField. GIL uses packed_channel_reference |
61 | typename Layout> // Layout defining the color space and ordering of the channels. Example value: rgb_layout_t |
62 | struct packed_pixel { |
63 | BitField _bitfield; |
64 | |
65 | typedef Layout layout_t; |
66 | typedef packed_pixel value_type; |
67 | typedef value_type& reference; |
68 | typedef const value_type& const_reference; |
69 | |
70 | BOOST_STATIC_CONSTANT(bool, is_mutable = channel_traits<typename mpl::front<ChannelRefVec>::type>::is_mutable); |
71 | |
72 | packed_pixel(){} |
73 | explicit packed_pixel(const BitField& bitfield) : _bitfield(bitfield) {} |
74 | |
75 | // Construct from another compatible pixel type |
76 | packed_pixel(const packed_pixel& p) : _bitfield(p._bitfield) {} |
77 | template <typename P> packed_pixel(const P& p, typename enable_if_c<is_pixel<P>::value>::type* d=0) { check_compatible<P>(); static_copy(p,*this); } |
78 | packed_pixel(int chan0, int chan1) : _bitfield(0) { |
79 | BOOST_STATIC_ASSERT((num_channels<packed_pixel>::value==2)); |
80 | at_c<0>(*this)=chan0; at_c<1>(*this)=chan1; |
81 | } |
82 | packed_pixel(int chan0, int chan1, int chan2) : _bitfield(0) { |
83 | BOOST_STATIC_ASSERT((num_channels<packed_pixel>::value==3)); |
84 | gil::at_c<0>(*this)=chan0; gil::at_c<1>(*this)=chan1; gil::at_c<2>(*this)=chan2; |
85 | } |
86 | packed_pixel(int chan0, int chan1, int chan2, int chan3) : _bitfield(0) { |
87 | BOOST_STATIC_ASSERT((num_channels<packed_pixel>::value==4)); |
88 | gil::at_c<0>(*this)=chan0; gil::at_c<1>(*this)=chan1; gil::at_c<2>(*this)=chan2; gil::at_c<3>(*this)=chan3; |
89 | } |
90 | packed_pixel(int chan0, int chan1, int chan2, int chan3, int chan4) : _bitfield(0) { |
91 | BOOST_STATIC_ASSERT((num_channels<packed_pixel>::value==5)); |
92 | gil::at_c<0>(*this)=chan0; gil::at_c<1>(*this)=chan1; gil::at_c<2>(*this)=chan2; gil::at_c<3>(*this)=chan3; gil::at_c<4>(*this)=chan4; |
93 | } |
94 | |
95 | packed_pixel& operator=(const packed_pixel& p) { _bitfield=p._bitfield; return *this; } |
96 | |
97 | template <typename P> packed_pixel& operator=(const P& p) { assign(p, mpl::bool_<is_pixel<P>::value>()); return *this; } |
98 | template <typename P> bool operator==(const P& p) const { return equal(p, mpl::bool_<is_pixel<P>::value>()); } |
99 | |
100 | template <typename P> bool operator!=(const P& p) const { return !(*this==p); } |
101 | |
102 | private: |
103 | template <typename Pixel> static void check_compatible() { gil_function_requires<PixelsCompatibleConcept<Pixel,packed_pixel> >(); } |
104 | template <typename Pixel> void assign(const Pixel& p, mpl::true_) { check_compatible<Pixel>(); static_copy(p,*this); } |
105 | template <typename Pixel> bool equal(const Pixel& p, mpl::true_) const { check_compatible<Pixel>(); return static_equal(*this,p); } |
106 | |
107 | // Support for assignment/equality comparison of a channel with a grayscale pixel |
108 | static void check_gray() { BOOST_STATIC_ASSERT((is_same<typename Layout::color_space_t, gray_t>::value)); } |
109 | template <typename Channel> void assign(const Channel& chan, mpl::false_) { check_gray(); at_c<0>(*this)=chan; } |
110 | template <typename Channel> bool equal (const Channel& chan, mpl::false_) const { check_gray(); return at_c<0>(*this)==chan; } |
111 | public: |
112 | packed_pixel& operator= (int chan) { check_gray(); at_c<0>(*this)=chan; return *this; } |
113 | bool operator==(int chan) const { check_gray(); return at_c<0>(*this)==chan; } |
114 | }; |
115 | |
116 | ///////////////////////////// |
117 | // ColorBasedConcept |
118 | ///////////////////////////// |
119 | |
120 | template <typename BitField, typename ChannelRefVec, typename Layout, int K> |
121 | struct kth_element_type<packed_pixel<BitField,ChannelRefVec,Layout>,K> : public mpl::at_c<ChannelRefVec,K> {}; |
122 | |
123 | template <typename BitField, typename ChannelRefVec, typename Layout, int K> |
124 | struct kth_element_reference_type<packed_pixel<BitField,ChannelRefVec,Layout>,K> : public mpl::at_c<ChannelRefVec,K> {}; |
125 | |
126 | template <typename BitField, typename ChannelRefVec, typename Layout, int K> |
127 | struct kth_element_const_reference_type<packed_pixel<BitField,ChannelRefVec,Layout>,K> { |
128 | typedef typename channel_traits<typename mpl::at_c<ChannelRefVec,K>::type>::const_reference type; |
129 | }; |
130 | |
131 | template <int K, typename P, typename C, typename L> inline |
132 | typename kth_element_reference_type<packed_pixel<P,C,L>, K>::type |
133 | at_c(packed_pixel<P,C,L>& p) { |
134 | return typename kth_element_reference_type<packed_pixel<P,C,L>, K>::type(&p._bitfield); |
135 | } |
136 | |
137 | template <int K, typename P, typename C, typename L> inline |
138 | typename kth_element_const_reference_type<packed_pixel<P,C,L>, K>::type |
139 | at_c(const packed_pixel<P,C,L>& p) { |
140 | return typename kth_element_const_reference_type<packed_pixel<P,C,L>, K>::type(&p._bitfield); |
141 | } |
142 | |
143 | ///////////////////////////// |
144 | // PixelConcept |
145 | ///////////////////////////// |
146 | |
147 | // Metafunction predicate that flags packed_pixel as a model of PixelConcept. Required by PixelConcept |
148 | template <typename BitField, typename ChannelRefVec, typename Layout> |
149 | struct is_pixel<packed_pixel<BitField,ChannelRefVec,Layout> > : public mpl::true_{}; |
150 | |
151 | ///////////////////////////// |
152 | // PixelBasedConcept |
153 | ///////////////////////////// |
154 | |
155 | template <typename P, typename C, typename Layout> |
156 | struct color_space_type<packed_pixel<P,C,Layout> > { |
157 | typedef typename Layout::color_space_t type; |
158 | }; |
159 | |
160 | template <typename P, typename C, typename Layout> |
161 | struct channel_mapping_type<packed_pixel<P,C,Layout> > { |
162 | typedef typename Layout::channel_mapping_t type; |
163 | }; |
164 | |
165 | template <typename P, typename C, typename Layout> |
166 | struct is_planar<packed_pixel<P,C,Layout> > : mpl::false_ {}; |
167 | |
168 | |
169 | //////////////////////////////////////////////////////////////////////////////// |
170 | /// |
171 | /// Support for interleaved iterators over packed pixel |
172 | /// |
173 | //////////////////////////////////////////////////////////////////////////////// |
174 | |
175 | /// \defgroup PixelIteratorModelPackedInterleavedPtr Pointer to packed_pixel<P,CR,Layout> |
176 | /// \ingroup PixelIteratorModel |
177 | /// \brief Iterators over interleaved pixels. |
178 | /// The pointer packed_pixel<P,CR,Layout>* is used as an iterator over interleaved pixels of packed format. Models PixelIteratorConcept, HasDynamicXStepTypeConcept, MemoryBasedIteratorConcept |
179 | |
180 | template <typename P, typename C, typename L> |
181 | struct iterator_is_mutable<packed_pixel<P,C,L>*> : public mpl::bool_<packed_pixel<P,C,L>::is_mutable> {}; |
182 | template <typename P, typename C, typename L> |
183 | struct iterator_is_mutable<const packed_pixel<P,C,L>*> : public mpl::false_ {}; |
184 | |
185 | |
186 | |
187 | } } // namespace boost::gil |
188 | |
189 | namespace boost { |
190 | template <typename P, typename C, typename L> |
191 | struct has_trivial_constructor<gil::packed_pixel<P,C,L> > : public has_trivial_constructor<P> {}; |
192 | } |
193 | #endif |
194 | |