]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | // |
2 | // Copyright 2005-2007 Adobe Systems Incorporated | |
3 | // Copyright 2019 Mateusz Loskot <mateusz at loskot dot net> | |
4 | // | |
5 | // Distributed under the Boost Software License, Version 1.0 | |
6 | // See accompanying file LICENSE_1_0.txt or copy at | |
7 | // http://www.boost.org/LICENSE_1_0.txt | |
8 | // | |
9 | #ifndef BOOST_GIL_PIXEL_HPP | |
10 | #define BOOST_GIL_PIXEL_HPP | |
11 | ||
12 | #include <boost/gil/channel.hpp> | |
13 | #include <boost/gil/color_base.hpp> | |
14 | #include <boost/gil/color_base_algorithm.hpp> | |
15 | #include <boost/gil/concepts.hpp> | |
16 | #include <boost/gil/metafunctions.hpp> | |
17 | #include <boost/gil/utilities.hpp> | |
18 | #include <boost/gil/detail/mp11.hpp> | |
7c673cae FG |
19 | |
20 | #include <functional> | |
92f5a8d4 | 21 | #include <type_traits> |
7c673cae FG |
22 | |
23 | namespace boost { namespace gil { | |
24 | ||
25 | // Forward-declare gray_t | |
26 | struct gray_color_t; | |
92f5a8d4 | 27 | using gray_t = mp11::mp_list<gray_color_t>; |
7c673cae FG |
28 | template <typename PixelBased> struct color_space_type; |
29 | template <typename PixelBased> struct channel_mapping_type; | |
30 | template <typename PixelBased> struct channel_type; | |
31 | template <typename PixelBased> struct is_planar; | |
32 | ||
92f5a8d4 TL |
33 | template <typename PixelBased> |
34 | struct color_space_type<PixelBased const> : color_space_type<PixelBased> {}; | |
7c673cae | 35 | |
92f5a8d4 TL |
36 | template <typename PixelBased> |
37 | struct channel_mapping_type<PixelBased const> : channel_mapping_type<PixelBased> {}; | |
7c673cae | 38 | |
92f5a8d4 TL |
39 | template <typename PixelBased> |
40 | struct channel_type<PixelBased const> : channel_type<PixelBased> {}; | |
7c673cae | 41 | |
92f5a8d4 TL |
42 | template <typename PixelBased> |
43 | struct is_planar : std::false_type {}; | |
44 | ||
45 | template <typename PixelBased> | |
46 | struct is_planar<PixelBased const> : is_planar<PixelBased> {}; | |
47 | ||
48 | template <typename T> struct is_pixel : std::false_type {}; | |
49 | template <typename T> struct is_pixel<T const> : is_pixel<T> {}; | |
7c673cae FG |
50 | |
51 | /// \ingroup PixelBasedAlgorithm | |
52 | /// \brief Returns the number of channels of a pixel-based GIL construct | |
53 | template <typename PixelBased> | |
92f5a8d4 | 54 | struct num_channels : mp11::mp_size<typename color_space_type<PixelBased>::type>::type {}; |
7c673cae FG |
55 | |
56 | /** | |
57 | \addtogroup PixelBasedAlgorithm | |
58 | ||
59 | Example: | |
60 | \code | |
92f5a8d4 TL |
61 | static_assert(num_channels<rgb8_view_t>::value == 3, ""); |
62 | static_assert(num_channels<cmyk16_planar_ptr_t>::value == 4, ""); | |
63 | ||
64 | static_assert(is_planar<rgb16_planar_image_t>::value)); | |
65 | static_assert(std::is_same<color_space_type<rgb8_planar_ref_t>::type, rgb_t>::value, ""); | |
66 | static_assert(std::is_same<channel_mapping_type<cmyk8_pixel_t>::type, | |
67 | channel_mapping_type<rgba8_pixel_t>::type>::value, ""); | |
68 | static_assert(std::is_same<channel_type<bgr8_pixel_t>::type, uint8_t>::value, ""); | |
7c673cae FG |
69 | \endcode |
70 | */ | |
71 | ||
92f5a8d4 | 72 | /// \defgroup ColorBaseModelPixel pixel |
7c673cae FG |
73 | /// \ingroup ColorBaseModel |
74 | /// \brief A homogeneous color base whose element is a channel value. Models HomogeneousColorBaseValueConcept | |
75 | ||
92f5a8d4 | 76 | /// \defgroup PixelModelPixel pixel |
7c673cae FG |
77 | /// \ingroup PixelModel |
78 | /// \brief A homogeneous pixel value. Models HomogeneousPixelValueConcept | |
79 | ||
80 | /// \ingroup PixelModelPixel ColorBaseModelPixel PixelBasedModel | |
81 | /// \brief Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept, PixelValueConcept, HomogeneousPixelBasedConcept | |
92f5a8d4 TL |
82 | /// |
83 | /// A pixel is a set of channels defining the color at a given point in an image. Conceptually, a pixel is little more than a color base whose elements | |
84 | /// model \p ChannelConcept. The class \p pixel defines a simple, homogeneous pixel value. It is used to store | |
7c673cae FG |
85 | /// the value of a color. The built-in C++ references to \p pixel, \p pixel& and \p const \p pixel& are used to represent a reference to a pixel |
86 | /// inside an interleaved image view (a view in which all channels are together in memory). Similarly, built-in pointer types \p pixel* and \p const \p pixel* | |
92f5a8d4 | 87 | /// are used as the standard iterator over a row of interleaved homogeneous pixels. |
7c673cae FG |
88 | /// |
89 | /// Since \p pixel inherits the properties of color base, assigning, equality comparison and copy-construcion are allowed between compatible pixels. | |
90 | /// This means that an 8-bit RGB pixel may be assigned to an 8-bit BGR pixel, or to an 8-bit planar reference. The channels are properly paired semantically. | |
91 | /// | |
92 | /// The single-channel (grayscale) instantiation of the class pixel, (i.e. \p pixel<T,gray_layout_t>) is also convertible to/from a channel value. | |
93 | /// This allows grayscale pixels to be used in simpler expressions like *gray_pix1 = *gray_pix2 instead of more complicated at_c<0>(gray_pix1) = at_c<0>(gray_pix2) | |
94 | /// or get_color<gray_color_t>(gray_pix1) = get_color<gray_color_t>(gray_pix2) | |
92f5a8d4 TL |
95 | /// |
96 | /// \tparam ChannelValue TODO | |
97 | /// \tparam Layout mp11::make_integer_sequence<int, ColorSpace::size> | |
98 | template <typename ChannelValue, typename Layout> | |
99 | struct pixel : | |
100 | detail::homogeneous_color_base | |
101 | < | |
102 | ChannelValue, | |
103 | Layout, | |
104 | mp11::mp_size<typename Layout::color_space_t>::value | |
105 | > | |
106 | { | |
7c673cae | 107 | private: |
92f5a8d4 TL |
108 | using channel_t = ChannelValue; |
109 | using parent_t = detail::homogeneous_color_base | |
110 | < | |
111 | ChannelValue, | |
112 | Layout, | |
113 | mp11::mp_size<typename Layout::color_space_t>::value | |
114 | >; | |
7c673cae | 115 | public: |
92f5a8d4 TL |
116 | using value_type = pixel<ChannelValue, Layout>; |
117 | using reference = value_type&; | |
118 | using const_reference = value_type const&; | |
119 | static constexpr bool is_mutable = channel_traits<channel_t>::is_mutable; | |
7c673cae | 120 | |
92f5a8d4 | 121 | pixel() = default; |
7c673cae | 122 | explicit pixel(channel_t v) : parent_t(v) {} // sets all channels to v |
92f5a8d4 TL |
123 | pixel(channel_t v0, channel_t v1) : parent_t(v0, v1) {} |
124 | pixel(channel_t v0, channel_t v1, channel_t v2) : parent_t(v0, v1, v2) {} | |
125 | ||
126 | pixel(channel_t v0, channel_t v1, channel_t v2, channel_t v3) | |
127 | : parent_t(v0, v1, v2, v3) | |
128 | {} | |
129 | ||
130 | pixel(channel_t v0, channel_t v1, channel_t v2, channel_t v3, channel_t v4) | |
131 | : parent_t(v0, v1, v2, v3, v4) | |
132 | {} | |
133 | ||
134 | pixel(channel_t v0, channel_t v1, channel_t v2, channel_t v3, channel_t v4, channel_t v5) | |
135 | : parent_t(v0, v1, v2, v3, v4, v5) | |
136 | {} | |
7c673cae FG |
137 | |
138 | pixel(const pixel& p) : parent_t(p) {} | |
92f5a8d4 TL |
139 | |
140 | pixel& operator=(pixel const& p) | |
141 | { | |
142 | static_copy(p,*this); | |
143 | return *this; | |
144 | } | |
7c673cae FG |
145 | |
146 | // Construct from another compatible pixel type | |
92f5a8d4 TL |
147 | template <typename Pixel> |
148 | pixel(Pixel const& p, | |
149 | typename std::enable_if<is_pixel<Pixel>::value>::type* /*dummy*/ = nullptr) | |
150 | : parent_t(p) | |
151 | { | |
7c673cae | 152 | check_compatible<Pixel>(); |
92f5a8d4 | 153 | } |
7c673cae | 154 | |
92f5a8d4 TL |
155 | template <typename Pixel> |
156 | pixel& operator=(Pixel const& p) | |
157 | { | |
158 | assign(p, is_pixel<Pixel>()); | |
159 | return *this; | |
160 | } | |
7c673cae | 161 | |
92f5a8d4 TL |
162 | template <typename Pixel> |
163 | bool operator==(Pixel const& p) const { return equal(p, is_pixel<Pixel>()); } | |
164 | ||
165 | template <typename Pixel> | |
166 | bool operator!=(Pixel const& p) const { return !(*this == p); } | |
7c673cae FG |
167 | |
168 | // homogeneous pixels have operator[] | |
92f5a8d4 TL |
169 | auto operator[](std::size_t index) |
170 | -> typename channel_traits<channel_t>::reference | |
171 | { | |
172 | return dynamic_at_c(*this, index); | |
173 | } | |
174 | ||
175 | auto operator[](std::size_t index) const | |
176 | -> typename channel_traits<channel_t>::const_reference | |
177 | { | |
178 | return dynamic_at_c(*this, index); | |
179 | } | |
180 | ||
7c673cae | 181 | private: |
92f5a8d4 TL |
182 | template <typename Pixel> |
183 | void assign(Pixel const& p, std::true_type) | |
184 | { | |
185 | check_compatible<Pixel>(); | |
186 | static_copy(p, *this); | |
187 | } | |
7c673cae | 188 | |
92f5a8d4 TL |
189 | template <typename Pixel> |
190 | bool equal(Pixel const& p, std::true_type) const | |
191 | { | |
192 | check_compatible<Pixel>(); | |
193 | return static_equal(*this, p); | |
194 | } | |
195 | ||
196 | template <typename Pixel> | |
197 | void check_compatible() const | |
198 | { | |
199 | gil_function_requires<PixelsCompatibleConcept<Pixel, pixel>>(); | |
200 | } | |
7c673cae FG |
201 | |
202 | // Support for assignment/equality comparison of a channel with a grayscale pixel | |
203 | ||
204 | private: | |
92f5a8d4 TL |
205 | static void check_gray() |
206 | { | |
207 | static_assert(std::is_same<typename Layout::color_space_t, gray_t>::value, ""); | |
208 | } | |
209 | ||
210 | template <typename Channel> | |
211 | void assign(Channel const& channel, std::false_type) | |
212 | { | |
213 | check_gray(); | |
214 | gil::at_c<0>(*this) = channel; | |
215 | } | |
216 | ||
217 | template <typename Channel> | |
218 | bool equal (Channel const& channel, std::false_type) const | |
219 | { | |
220 | check_gray(); | |
221 | return gil::at_c<0>(*this) == channel; | |
222 | } | |
223 | ||
7c673cae | 224 | public: |
92f5a8d4 TL |
225 | pixel& operator= (channel_t channel) |
226 | { | |
227 | check_gray(); | |
228 | gil::at_c<0>(*this) = channel; | |
229 | return *this; | |
230 | } | |
231 | ||
232 | bool operator==(channel_t channel) const | |
233 | { | |
234 | check_gray(); | |
235 | return gil::at_c<0>(*this) == channel; | |
236 | } | |
7c673cae FG |
237 | }; |
238 | ||
239 | ///////////////////////////// | |
240 | // ColorBasedConcept | |
241 | ///////////////////////////// | |
242 | ||
92f5a8d4 TL |
243 | template <typename ChannelValue, typename Layout, int K> |
244 | struct kth_element_type<pixel<ChannelValue,Layout>, K> | |
245 | { | |
246 | using type = ChannelValue; | |
7c673cae FG |
247 | }; |
248 | ||
92f5a8d4 TL |
249 | template <typename ChannelValue, typename Layout, int K> |
250 | struct kth_element_reference_type<pixel<ChannelValue,Layout>, K> | |
251 | { | |
252 | using type = typename channel_traits<ChannelValue>::reference; | |
7c673cae FG |
253 | }; |
254 | ||
92f5a8d4 TL |
255 | template <typename ChannelValue, typename Layout, int K> |
256 | struct kth_element_reference_type<const pixel<ChannelValue,Layout>, K> | |
257 | { | |
258 | using type = typename channel_traits<ChannelValue>::const_reference; | |
7c673cae FG |
259 | }; |
260 | ||
92f5a8d4 TL |
261 | template <typename ChannelValue, typename Layout, int K> |
262 | struct kth_element_const_reference_type<pixel<ChannelValue,Layout>, K> | |
263 | { | |
264 | using type = typename channel_traits<ChannelValue>::const_reference; | |
7c673cae FG |
265 | }; |
266 | ||
267 | ///////////////////////////// | |
268 | // PixelConcept | |
269 | ///////////////////////////// | |
270 | ||
92f5a8d4 TL |
271 | template <typename ChannelValue, typename Layout> |
272 | struct is_pixel<pixel<ChannelValue,Layout>> : std::true_type {}; | |
7c673cae FG |
273 | |
274 | ///////////////////////////// | |
275 | // HomogeneousPixelBasedConcept | |
276 | ///////////////////////////// | |
277 | ||
278 | template <typename ChannelValue, typename Layout> | |
92f5a8d4 TL |
279 | struct color_space_type<pixel<ChannelValue, Layout>> |
280 | { | |
281 | using type = typename Layout::color_space_t; | |
282 | }; | |
7c673cae FG |
283 | |
284 | template <typename ChannelValue, typename Layout> | |
92f5a8d4 TL |
285 | struct channel_mapping_type<pixel<ChannelValue, Layout>> |
286 | { | |
287 | using type = typename Layout::channel_mapping_t; | |
288 | }; | |
7c673cae FG |
289 | |
290 | template <typename ChannelValue, typename Layout> | |
92f5a8d4 | 291 | struct is_planar<pixel<ChannelValue, Layout>> : std::false_type {}; |
7c673cae FG |
292 | |
293 | template <typename ChannelValue, typename Layout> | |
92f5a8d4 TL |
294 | struct channel_type<pixel<ChannelValue, Layout>> |
295 | { | |
296 | using type = ChannelValue; | |
297 | }; | |
7c673cae | 298 | |
92f5a8d4 | 299 | }} // namespace boost::gil |
7c673cae | 300 | |
7c673cae | 301 | #endif |