Boost GIL


pixel.hpp
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>
19 
20 #include <functional>
21 #include <type_traits>
22 
23 namespace boost { namespace gil {
24 
25 // Forward-declare gray_t
26 struct gray_color_t;
27 using gray_t = mp11::mp_list<gray_color_t>;
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 
33 template <typename PixelBased>
34 struct color_space_type<PixelBased const> : color_space_type<PixelBased> {};
35 
36 template <typename PixelBased>
37 struct channel_mapping_type<PixelBased const> : channel_mapping_type<PixelBased> {};
38 
39 template <typename PixelBased>
40 struct channel_type<PixelBased const> : channel_type<PixelBased> {};
41 
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> {};
50 
53 template <typename PixelBased>
54 struct num_channels : mp11::mp_size<typename color_space_type<PixelBased>::type>::type {};
55 
72 
79 
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 {
107 private:
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  >;
115 public:
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;
120 
121  pixel() = default;
122  explicit pixel(channel_t v) : parent_t(v) {} // sets all channels to v
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  {}
137 
138  pixel(const pixel& p) : parent_t(p) {}
139 
140  pixel& operator=(pixel const& p)
141  {
142  static_copy(p,*this);
143  return *this;
144  }
145 
146  // Construct from another compatible pixel type
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  {
152  check_compatible<Pixel>();
153  }
154 
155  template <typename Pixel>
156  pixel& operator=(Pixel const& p)
157  {
158  assign(p, is_pixel<Pixel>());
159  return *this;
160  }
161 
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); }
167 
168  // homogeneous pixels have operator[]
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 
181 private:
182  template <typename Pixel>
183  void assign(Pixel const& p, std::true_type)
184  {
185  check_compatible<Pixel>();
186  static_copy(p, *this);
187  }
188 
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  }
201 
202 // Support for assignment/equality comparison of a channel with a grayscale pixel
203 
204 private:
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 
224 public:
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  }
237 };
238 
240 // ColorBasedConcept
242 
243 template <typename ChannelValue, typename Layout, int K>
244 struct kth_element_type<pixel<ChannelValue,Layout>, K>
245 {
246  using type = ChannelValue;
247 };
248 
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;
253 };
254 
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;
259 };
260 
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;
265 };
266 
268 // PixelConcept
270 
271 template <typename ChannelValue, typename Layout>
272 struct is_pixel<pixel<ChannelValue,Layout>> : std::true_type {};
273 
275 // HomogeneousPixelBasedConcept
277 
278 template <typename ChannelValue, typename Layout>
279 struct color_space_type<pixel<ChannelValue, Layout>>
280 {
281  using type = typename Layout::color_space_t;
282 };
283 
284 template <typename ChannelValue, typename Layout>
285 struct channel_mapping_type<pixel<ChannelValue, Layout>>
286 {
287  using type = typename Layout::channel_mapping_t;
288 };
289 
290 template <typename ChannelValue, typename Layout>
291 struct is_planar<pixel<ChannelValue, Layout>> : std::false_type {};
292 
293 template <typename ChannelValue, typename Layout>
294 struct channel_type<pixel<ChannelValue, Layout>>
295 {
296  using type = ChannelValue;
297 };
298 
299 }} // namespace boost::gil
300 
301 #endif