Boost GIL


image_view.hpp
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_IMAGE_VIEW_HPP
9 #define BOOST_GIL_IMAGE_VIEW_HPP
10 
11 #include <boost/gil/dynamic_step.hpp>
12 #include <boost/gil/iterator_from_2d.hpp>
13 
14 #include <boost/assert.hpp>
15 
16 #include <cstddef>
17 #include <iterator>
18 
19 namespace boost { namespace gil {
20 
52 template <typename Loc> // Models 2D Pixel Locator
54 {
55 public:
56  // aliases required by ConstRandomAccessNDImageViewConcept
57  static const std::size_t num_dimensions=2;
58  using value_type = typename Loc::value_type;
59  using reference = typename Loc::reference; // result of dereferencing
60  using coord_t = typename Loc::coord_t; // 1D difference type (same for all dimensions)
61  using difference_type = coord_t; // result of operator-(1d_iterator,1d_iterator)
62  using point_t = typename Loc::point_t;
63  using locator = Loc;
64  using const_t = image_view<typename Loc::const_t>; // same as this type, but over const values
65  template <std::size_t D> struct axis
66  {
67  using coord_t = typename Loc::template axis<D>::coord_t; // difference_type along each dimension
68  using iterator = typename Loc::template axis<D>::iterator; // 1D iterator type along each dimension
69  };
70  using iterator = iterator_from_2d<Loc>; // 1D iterator type for each pixel left-to-right inside top-to-bottom
71  using const_iterator = typename const_t::iterator; // may be used to examine, but not to modify values
72  using const_reference = typename const_t::reference; // behaves as a const reference
73  using pointer = typename std::iterator_traits<iterator>::pointer; // behaves as a pointer to the value type
74  using reverse_iterator = std::reverse_iterator<iterator>;
75  using size_type = std::size_t;
76 
77  // aliases required by ConstRandomAccess2DImageViewConcept
78  using xy_locator = locator;
79  using x_iterator = typename xy_locator::x_iterator; // pixel iterator along a row
80  using y_iterator = typename xy_locator::y_iterator; // pixel iterator along a column
81  using x_coord_t = typename xy_locator::x_coord_t;
82  using y_coord_t = typename xy_locator::y_coord_t;
83 
84  template <typename Deref>
85  struct add_deref
86  {
88  static type make(image_view<Loc> const& view, Deref const& d)
89  {
90  return type(view.dimensions(), Loc::template add_deref<Deref>::make(view.pixels(), d));
91  }
92  };
93 
94  image_view() : _dimensions(0,0) {}
95  image_view(image_view const& img_view)
96  : _dimensions(img_view.dimensions()), _pixels(img_view.pixels())
97  {}
98 
99  template <typename View>
100  image_view(View const& view) : _dimensions(view.dimensions()), _pixels(view.pixels()) {}
101 
102  template <typename L2>
103  image_view(point_t const& dims, L2 const& loc) : _dimensions(dims), _pixels(loc) {}
104 
105  template <typename L2>
106  image_view(coord_t width, coord_t height, L2 const& loc)
107  : _dimensions(x_coord_t(width), y_coord_t(height)), _pixels(loc)
108  {}
109 
110  template <typename View>
111  image_view& operator=(View const& view)
112  {
113  _pixels = view.pixels();
114  _dimensions = view.dimensions();
115  return *this;
116  }
117 
118  image_view& operator=(image_view const& view)
119  {
120  // TODO: Self-assignment protection?
121  _pixels = view.pixels();
122  _dimensions = view.dimensions();
123  return *this;
124  }
125 
126  template <typename View>
127  bool operator==(View const &view) const
128  {
129  return pixels() == view.pixels() && dimensions() == view.dimensions();
130  }
131 
132  template <typename View>
133  bool operator!=(View const& view) const
134  {
135  return !(*this == view);
136  }
137 
138  template <typename L2>
139  friend void swap(image_view<L2> &lhs, image_view<L2> &rhs);
140 
146  void swap(image_view<Loc>& other)
147  {
148  using boost::gil::swap;
149  swap(*this, other);
150  }
151 
152  auto dimensions() const -> point_t const&
153  {
154  return _dimensions;
155  }
156 
157  auto pixels() const -> locator const&
158  {
159  return _pixels;
160  }
161 
162  auto width() const -> x_coord_t
163  {
164  return dimensions().x;
165  }
166 
167  auto height() const -> y_coord_t
168  {
169  return dimensions().y;
170  }
171 
172  auto num_channels() const -> std::size_t
173  {
174  return gil::num_channels<value_type>::value;
175  }
176 
177  bool is_1d_traversable() const
178  {
179  return _pixels.is_1d_traversable(width());
180  }
181 
186  bool empty() const
187  {
188  return !(width() > 0 && height() > 0);
189  }
190 
195  auto front() const -> reference
196  {
197  BOOST_ASSERT(!empty());
198  return *begin();
199  }
200 
205  auto back() const -> reference
206  {
207  BOOST_ASSERT(!empty());
208  return *rbegin();
209  }
210 
211  //\{@
213  auto size() const -> size_type
214  {
215  return width() * height();
216  }
217 
218  auto begin() const -> iterator
219  {
220  return iterator(_pixels, _dimensions.x);
221  }
222 
223  auto end() const -> iterator
224  {
225  // potential performance problem!
226  return begin() + static_cast<difference_type>(size());
227  }
228 
229  auto rbegin() const -> reverse_iterator
230  {
231  return reverse_iterator(end());
232  }
233 
234  auto rend() const -> reverse_iterator
235  {
236  return reverse_iterator(begin());
237  }
238 
239  auto operator[](difference_type i) const -> reference
240  {
241  BOOST_ASSERT(i < static_cast<difference_type>(size()));
242  return begin()[i]; // potential performance problem!
243  }
244 
245  auto at(difference_type i) const -> iterator
246  {
247  // UB if the specified increment advances non-incrementable iterator (i.e. past-the-end)
248  BOOST_ASSERT(i < static_cast<difference_type>(size()));
249  return begin() + i;
250  }
251 
252  auto at(point_t const& p) const -> iterator
253  {
254  // UB if the specified coordinates advance non-incrementable iterator (i.e. past-the-end)
255  BOOST_ASSERT(0 <= p.x && p.x < width());
256  BOOST_ASSERT(0 <= p.y && p.y < height());
257  return begin() + p.y * width() + p.x;
258  }
259 
260  auto at(x_coord_t x, y_coord_t y) const -> iterator
261  {
262  // UB if the specified coordinates advance non-incrementable iterator (i.e. past-the-end)
263  BOOST_ASSERT(0 <= x && x < width());
264  BOOST_ASSERT(0 <= y && y < height());
265  return begin() + y * width() + x;
266  }
267  //\}@
268 
269  //\{@
271  auto operator()(point_t const& p) const -> reference
272  {
273  BOOST_ASSERT(0 <= p.x && p.x < width());
274  BOOST_ASSERT(0 <= p.y && p.y < height());
275  return _pixels(p.x, p.y);
276  }
277 
278  auto operator()(x_coord_t x, y_coord_t y) const -> reference
279  {
280  BOOST_ASSERT(0 <= x && x < width());
281  BOOST_ASSERT(0 <= y && y < height());
282  return _pixels(x, y);
283  }
284 
285  template <std::size_t D>
286  auto axis_iterator(point_t const& p) const -> typename axis<D>::iterator
287  {
288  // Allow request for iterators from inclusive range of [begin, end]
289  BOOST_ASSERT(0 <= p.x && p.x <= width());
290  BOOST_ASSERT(0 <= p.y && p.y <= height());
291  return _pixels.template axis_iterator<D>(p);
292  }
293 
294  auto xy_at(x_coord_t x, y_coord_t y) const -> xy_locator
295  {
296  // TODO: Are relative locations of neighbors with negative offsets valid? Sampling?
297  BOOST_ASSERT(x < width());
298  BOOST_ASSERT(y <= height());
299  return _pixels + point_t(x, y);
300  }
301 
302  auto xy_at(point_t const& p) const -> xy_locator
303  {
304  // TODO: Are relative locations of neighbors with negative offsets valid? Sampling?
305  BOOST_ASSERT(p.x < width());
306  BOOST_ASSERT(p.y < height());
307  return _pixels + p;
308  }
309  //\}@
310 
311  //\{@
313  auto x_at(x_coord_t x, y_coord_t y) const -> x_iterator
314  {
315  BOOST_ASSERT(0 <= x && x <= width()); // allow request for [begin, end] inclusive
316  BOOST_ASSERT(0 <= y && y < height()); // TODO: For empty image/view, shouldn't we accept: row_begin(0) == view.row_end(0) ?
317  return _pixels.x_at(x, y);
318  }
319 
320  auto x_at(point_t const& p) const -> x_iterator
321  {
322  BOOST_ASSERT(0 <= p.x && p.x <= width()); // allow request for [begin, end] inclusive
323  BOOST_ASSERT(0 <= p.y && p.y < height()); // TODO: For empty image/view, shouldn't we accept: row_begin(0) == view.row_end(0) ?
324  return _pixels.x_at(p);
325  }
326 
327  auto row_begin(y_coord_t y) const -> x_iterator
328  {
329  BOOST_ASSERT(0 <= y && y < height());
330  return x_at(0, y);
331  }
332 
333  auto row_end(y_coord_t y) const -> x_iterator
334  {
335  BOOST_ASSERT(0 <= y && y < height());
336  return x_at(width(), y);
337  }
338  //\}@
339 
340  //\{@
342  auto y_at(x_coord_t x, y_coord_t y) const -> y_iterator
343  {
344  BOOST_ASSERT(0 <= x && x < width()); // TODO: For empty image/view, shouldn't we accept: view.col_begin(0) == view.col_end(0) ?
345  BOOST_ASSERT(0 <= y && y <= height()); // allow request for [begin, end] inclusive
346  return xy_at(x, y).y();
347  }
348 
349  auto y_at(point_t const& p) const -> y_iterator
350  {
351  BOOST_ASSERT(0 <= p.x && p.x < width()); // TODO: For empty image/view, shouldn't we accept: view.col_begin(0) == view.col_end(0) ?
352  BOOST_ASSERT(0 <= p.y && p.y <= height()); // allow request for [begin, end] inclusive
353  return xy_at(p).y();
354  }
355 
356  auto col_begin(x_coord_t x) const -> y_iterator
357  {
358  BOOST_ASSERT(0 <= x && x < width());
359  return y_at(x, 0);
360  }
361 
362  auto col_end(x_coord_t x) const -> y_iterator
363  {
364  BOOST_ASSERT(0 <= x && x < width());
365  return y_at(x, height());
366  }
367  //\}@
368 
369 private:
370  template <typename L2>
371  friend class image_view;
372 
373  point_t _dimensions;
374  xy_locator _pixels;
375 };
376 
377 template <typename L2>
378 inline void swap(image_view<L2>& x, image_view<L2>& y) {
379  using std::swap;
380  swap(x._dimensions,y._dimensions);
381  swap(x._pixels, y._pixels); // TODO: Extend further
382 }
383 
385 // PixelBasedConcept
387 
388 template <typename L>
389 struct channel_type<image_view<L> > : public channel_type<L> {};
390 
391 template <typename L>
392 struct color_space_type<image_view<L> > : public color_space_type<L> {};
393 
394 template <typename L>
395 struct channel_mapping_type<image_view<L> > : public channel_mapping_type<L> {};
396 
397 template <typename L>
398 struct is_planar<image_view<L> > : public is_planar<L> {};
399 
401 // HasDynamicXStepTypeConcept
403 
404 template <typename L>
405 struct dynamic_x_step_type<image_view<L>>
406 {
407  using type = image_view<typename gil::dynamic_x_step_type<L>::type>;
408 };
409 
411 // HasDynamicYStepTypeConcept
413 
414 template <typename L>
415 struct dynamic_y_step_type<image_view<L>>
416 {
417  using type = image_view<typename gil::dynamic_y_step_type<L>::type>;
418 };
419 
421 // HasTransposedTypeConcept
423 
424 template <typename L>
425 struct transposed_type<image_view<L>>
426 {
427  using type = image_view<typename transposed_type<L>::type>;
428 };
429 
430 }} // namespace boost::gil
431 
432 #endif
A lightweight object that interprets memory as a 2D array of pixels. Models ImageViewConcept,...
Definition: image_view.hpp:54
auto back() const -> reference
Returns a reference to the last element in raster order.
Definition: image_view.hpp:205
auto front() const -> reference
Returns a reference to the first element in raster order.
Definition: image_view.hpp:195
bool empty() const
Returns true if the view has no elements, false otherwise.
Definition: image_view.hpp:186
void swap(image_view< Loc > &other)
Exchanges the elements of the current view with those of other in constant time.
Definition: image_view.hpp:146
Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept,...
Definition: iterator_from_2d.hpp:46
auto view(image< Pixel, IsPlanar, Alloc > &img) -> typename image< Pixel, IsPlanar, Alloc >::view_t const &
Returns the non-constant-pixel view of an image.
Definition: image.hpp:565
void swap(boost::gil::packed_channel_reference< BF, FB, NB, M > const x, R &y)
swap for packed_channel_reference
Definition: channel.hpp:583
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
Definition: algorithm.hpp:36
Returns an integral constant type specifying the number of elements in a color base.
Definition: color_base_algorithm.hpp:42