]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
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_PACKED_PIXEL_HPP | |
9 | #define BOOST_GIL_PACKED_PIXEL_HPP | |
10 | ||
11 | #include <boost/gil/pixel.hpp> | |
12 | #include <boost/gil/detail/mp11.hpp> | |
7c673cae FG |
13 | |
14 | #include <functional> | |
92f5a8d4 | 15 | #include <type_traits> |
7c673cae FG |
16 | |
17 | namespace boost { namespace gil { | |
18 | ||
92f5a8d4 TL |
19 | /// A model of a heterogeneous pixel whose channels are bit ranges. |
20 | /// For example 16-bit RGB in '565' format. | |
21 | ||
22 | /// \defgroup ColorBaseModelPackedPixel packed_pixel | |
7c673cae FG |
23 | /// \ingroup ColorBaseModel |
24 | /// \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. | |
25 | ||
92f5a8d4 TL |
26 | /// \defgroup PixelModelPackedPixel packed_pixel |
27 | /// \ingroup PixelModel | |
28 | /// \brief A heterogeneous pixel used to represent packed pixels with non-byte-aligned channels. Models PixelValueConcept | |
29 | /// | |
30 | /// Example: | |
31 | /// \code | |
32 | /// using rgb565_pixel_t = packed_pixel_type<uint16_t, mp11::mp_list-c<unsigned,5,6,5>, rgb_layout_t>::type; | |
33 | /// static_assert(sizeof(rgb565_pixel_t) == 2, ""); | |
34 | /// | |
35 | /// rgb565_pixel_t r565; | |
36 | /// get_color(r565,red_t()) = 31; | |
37 | /// get_color(r565,green_t()) = 63; | |
38 | /// get_color(r565,blue_t()) = 31; | |
39 | /// assert(r565 == rgb565_pixel_t((uint16_t)0xFFFF)); | |
40 | /// \endcode | |
7c673cae FG |
41 | |
42 | /// \ingroup ColorBaseModelPackedPixel PixelModelPackedPixel PixelBasedModel | |
43 | /// \brief Heterogeneous pixel value whose channel references can be constructed from the pixel bitfield and their index. Models ColorBaseValueConcept, PixelValueConcept, PixelBasedConcept | |
44 | /// Typical use for this is a model of a packed pixel (like 565 RGB) | |
92f5a8d4 TL |
45 | /// \tparam BitField Type that holds the bits of the pixel. Typically an integral type, like std::uint16_t. |
46 | /// \tparam ChannelRefs MP11 list whose elements are packed channels. They must be constructible from BitField. GIL uses packed_channel_reference | |
47 | /// \tparam Layout defining the color space and ordering of the channels. Example value: rgb_layout_t | |
48 | template <typename BitField, typename ChannelRefs, typename Layout> | |
49 | struct packed_pixel | |
50 | { | |
51 | BitField _bitfield{0}; // TODO: Make private | |
52 | ||
53 | using layout_t = Layout; | |
54 | using value_type = packed_pixel<BitField, ChannelRefs, Layout>; | |
55 | using reference = value_type&; | |
56 | using const_reference = value_type const&; | |
57 | ||
58 | static constexpr bool is_mutable = | |
59 | channel_traits<mp11::mp_front<ChannelRefs>>::is_mutable; | |
60 | ||
61 | packed_pixel() = default; | |
7c673cae FG |
62 | explicit packed_pixel(const BitField& bitfield) : _bitfield(bitfield) {} |
63 | ||
64 | // Construct from another compatible pixel type | |
65 | packed_pixel(const packed_pixel& p) : _bitfield(p._bitfield) {} | |
92f5a8d4 TL |
66 | |
67 | template <typename Pixel> | |
68 | packed_pixel(Pixel const& p, | |
69 | typename std::enable_if<is_pixel<Pixel>::value>::type* /*dummy*/ = nullptr) | |
70 | { | |
71 | check_compatible<Pixel>(); | |
72 | static_copy(p, *this); | |
73 | } | |
74 | ||
75 | packed_pixel(int chan0, int chan1) | |
76 | : _bitfield(0) | |
77 | { | |
78 | static_assert(num_channels<packed_pixel>::value == 2, ""); | |
79 | gil::at_c<0>(*this) = chan0; gil::at_c<1>(*this) = chan1; | |
80 | } | |
81 | ||
82 | packed_pixel(int chan0, int chan1, int chan2) | |
83 | : _bitfield(0) | |
84 | { | |
85 | static_assert(num_channels<packed_pixel>::value == 3, ""); | |
86 | gil::at_c<0>(*this) = chan0; | |
87 | gil::at_c<1>(*this) = chan1; | |
88 | gil::at_c<2>(*this) = chan2; | |
89 | } | |
90 | ||
91 | packed_pixel(int chan0, int chan1, int chan2, int chan3) | |
92 | : _bitfield(0) | |
93 | { | |
94 | static_assert(num_channels<packed_pixel>::value == 4, ""); | |
95 | gil::at_c<0>(*this) = chan0; | |
96 | gil::at_c<1>(*this) = chan1; | |
97 | gil::at_c<2>(*this) = chan2; | |
98 | gil::at_c<3>(*this) = chan3; | |
99 | } | |
100 | ||
101 | packed_pixel(int chan0, int chan1, int chan2, int chan3, int chan4) | |
102 | : _bitfield(0) | |
103 | { | |
104 | static_assert(num_channels<packed_pixel>::value == 5, ""); | |
105 | gil::at_c<0>(*this) = chan0; | |
106 | gil::at_c<1>(*this) = chan1; | |
107 | gil::at_c<2>(*this) = chan2; | |
108 | gil::at_c<3>(*this) = chan3; | |
109 | gil::at_c<4>(*this) = chan4; | |
110 | } | |
111 | ||
112 | auto operator=(packed_pixel const& p) -> packed_pixel& | |
113 | { | |
114 | _bitfield = p._bitfield; | |
115 | return *this; | |
116 | } | |
117 | ||
118 | template <typename Pixel> | |
119 | auto operator=(Pixel const& p) -> packed_pixel& | |
120 | { | |
121 | assign(p, is_pixel<Pixel>()); | |
122 | return *this; | |
123 | } | |
124 | ||
125 | template <typename Pixel> | |
126 | bool operator==(Pixel const& p) const | |
127 | { | |
128 | return equal(p, is_pixel<Pixel>()); | |
129 | } | |
130 | ||
131 | template <typename Pixel> | |
132 | bool operator!=(Pixel const& p) const { return !(*this==p); } | |
7c673cae FG |
133 | |
134 | private: | |
92f5a8d4 TL |
135 | template <typename Pixel> |
136 | static void check_compatible() | |
137 | { | |
138 | gil_function_requires<PixelsCompatibleConcept<Pixel, packed_pixel>>(); | |
139 | } | |
140 | ||
141 | template <typename Pixel> | |
142 | void assign(Pixel const& p, std::true_type) | |
143 | { | |
144 | check_compatible<Pixel>(); | |
145 | static_copy(p, *this); | |
146 | } | |
147 | ||
148 | template <typename Pixel> | |
149 | bool equal(Pixel const& p, std::true_type) const | |
150 | { | |
151 | check_compatible<Pixel>(); | |
152 | return static_equal(*this, p); | |
153 | } | |
154 | ||
155 | // Support for assignment/equality comparison of a channel with a grayscale pixel | |
156 | static void check_gray() | |
157 | { | |
158 | static_assert(std::is_same<typename Layout::color_space_t, gray_t>::value, ""); | |
159 | } | |
160 | ||
161 | template <typename Channel> | |
162 | void assign(Channel const& channel, std::false_type) | |
163 | { | |
164 | check_gray(); | |
165 | gil::at_c<0>(*this) = channel; | |
166 | } | |
167 | ||
168 | template <typename Channel> | |
169 | bool equal (Channel const& channel, std::false_type) const | |
170 | { | |
171 | check_gray(); | |
172 | return gil::at_c<0>(*this) == channel; | |
173 | } | |
174 | ||
7c673cae | 175 | public: |
92f5a8d4 TL |
176 | auto operator=(int channel) -> packed_pixel& |
177 | { | |
178 | check_gray(); | |
179 | gil::at_c<0>(*this) = channel; | |
180 | return *this; | |
181 | } | |
182 | ||
183 | bool operator==(int channel) const | |
184 | { | |
185 | check_gray(); | |
186 | return gil::at_c<0>(*this) == channel; | |
187 | } | |
7c673cae FG |
188 | }; |
189 | ||
190 | ///////////////////////////// | |
191 | // ColorBasedConcept | |
192 | ///////////////////////////// | |
193 | ||
92f5a8d4 TL |
194 | template <typename BitField, typename ChannelRefs, typename Layout, int K> |
195 | struct kth_element_type<packed_pixel<BitField, ChannelRefs, Layout>, K> | |
196 | { | |
197 | using type = typename channel_traits<mp11::mp_at_c<ChannelRefs, K>>::value_type; | |
198 | }; | |
7c673cae | 199 | |
92f5a8d4 TL |
200 | template <typename BitField, typename ChannelRefs, typename Layout, int K> |
201 | struct kth_element_reference_type<packed_pixel<BitField, ChannelRefs, Layout>, K> | |
202 | { | |
203 | using type = typename channel_traits<mp11::mp_at_c<ChannelRefs, K>>::reference; | |
204 | }; | |
7c673cae | 205 | |
92f5a8d4 TL |
206 | template <typename BitField, typename ChannelRefs, typename Layout, int K> |
207 | struct kth_element_const_reference_type<packed_pixel<BitField, ChannelRefs, Layout>, K> | |
208 | { | |
209 | using type = typename channel_traits<mp11::mp_at_c<ChannelRefs, K>>::const_reference; | |
7c673cae FG |
210 | }; |
211 | ||
92f5a8d4 TL |
212 | template <int K, typename P, typename C, typename L> |
213 | inline | |
214 | auto at_c(packed_pixel<P, C, L>& p) | |
215 | -> typename kth_element_reference_type<packed_pixel<P, C, L>, K>::type | |
216 | { | |
217 | return typename kth_element_reference_type | |
218 | < | |
219 | packed_pixel<P, C, L>, | |
220 | K | |
221 | >::type{&p._bitfield}; | |
7c673cae FG |
222 | } |
223 | ||
92f5a8d4 TL |
224 | template <int K, typename P, typename C, typename L> |
225 | inline | |
226 | auto at_c(const packed_pixel<P, C, L>& p) | |
227 | -> typename kth_element_const_reference_type<packed_pixel<P, C, L>, K>::type | |
228 | { | |
229 | return typename kth_element_const_reference_type | |
230 | < | |
231 | packed_pixel<P, C, L>, | |
232 | K>::type{&p._bitfield}; | |
7c673cae FG |
233 | } |
234 | ||
235 | ///////////////////////////// | |
236 | // PixelConcept | |
237 | ///////////////////////////// | |
238 | ||
239 | // Metafunction predicate that flags packed_pixel as a model of PixelConcept. Required by PixelConcept | |
92f5a8d4 TL |
240 | template <typename BitField, typename ChannelRefs, typename Layout> |
241 | struct is_pixel<packed_pixel<BitField, ChannelRefs, Layout>> : std::true_type {}; | |
7c673cae FG |
242 | |
243 | ///////////////////////////// | |
244 | // PixelBasedConcept | |
245 | ///////////////////////////// | |
246 | ||
247 | template <typename P, typename C, typename Layout> | |
92f5a8d4 TL |
248 | struct color_space_type<packed_pixel<P, C, Layout>> |
249 | { | |
250 | using type = typename Layout::color_space_t; | |
251 | }; | |
7c673cae FG |
252 | |
253 | template <typename P, typename C, typename Layout> | |
92f5a8d4 TL |
254 | struct channel_mapping_type<packed_pixel<P, C, Layout>> |
255 | { | |
256 | using type = typename Layout::channel_mapping_t; | |
257 | }; | |
7c673cae FG |
258 | |
259 | template <typename P, typename C, typename Layout> | |
92f5a8d4 | 260 | struct is_planar<packed_pixel<P, C, Layout>> : std::false_type {}; |
7c673cae FG |
261 | |
262 | //////////////////////////////////////////////////////////////////////////////// | |
7c673cae | 263 | /// Support for interleaved iterators over packed pixel |
7c673cae FG |
264 | //////////////////////////////////////////////////////////////////////////////// |
265 | ||
266 | /// \defgroup PixelIteratorModelPackedInterleavedPtr Pointer to packed_pixel<P,CR,Layout> | |
267 | /// \ingroup PixelIteratorModel | |
268 | /// \brief Iterators over interleaved pixels. | |
269 | /// The pointer packed_pixel<P,CR,Layout>* is used as an iterator over interleaved pixels of packed format. Models PixelIteratorConcept, HasDynamicXStepTypeConcept, MemoryBasedIteratorConcept | |
270 | ||
92f5a8d4 TL |
271 | template <typename P, typename C, typename L> |
272 | struct iterator_is_mutable<packed_pixel<P, C, L>*> | |
273 | : std::integral_constant<bool, packed_pixel<P, C, L>::is_mutable> | |
274 | {}; | |
7c673cae | 275 | |
92f5a8d4 TL |
276 | template <typename P, typename C, typename L> |
277 | struct iterator_is_mutable<const packed_pixel<P, C, L>*> : std::false_type {}; | |
7c673cae | 278 | |
92f5a8d4 | 279 | }} // namespace boost::gil |
7c673cae | 280 | |
7c673cae | 281 | #endif |