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  BOOST_ASSERT(i < size());
248  return begin() + i;
249  }
250 
251  auto at(point_t const& p) const -> iterator
252  {
253  BOOST_ASSERT(0 <= p.x && p.x < width());
254  BOOST_ASSERT(0 <= p.y && p.y < height());
255  return begin() + p.y * width() + p.x;
256  }
257 
258  auto at(x_coord_t x, y_coord_t y) const -> iterator
259  {
260  BOOST_ASSERT(0 <= x && x < width());
261  BOOST_ASSERT(0 <= y && y < height());
262  return begin() + y * width() + x;
263  }
264  //\}@
265 
266  //\{@
268  auto operator()(point_t const& p) const -> reference
269  {
270  BOOST_ASSERT(0 <= p.x && p.x < width());
271  BOOST_ASSERT(0 <= p.y && p.y < height());
272  return _pixels(p.x, p.y);
273  }
274 
275  auto operator()(x_coord_t x, y_coord_t y) const -> reference
276  {
277  BOOST_ASSERT(0 <= x && x < width());
278  BOOST_ASSERT(0 <= y && y < height());
279  return _pixels(x, y);
280  }
281 
282  template <std::size_t D>
283  auto axis_iterator(point_t const& p) const -> typename axis<D>::iterator
284  {
285  // allow request for iterators from inclusive range of [begin, end]
286  BOOST_ASSERT(0 <= p.x && p.x <= width());
287  BOOST_ASSERT(0 <= p.y && p.y <= height());
288  return _pixels.template axis_iterator<D>(p);
289  }
290 
291  auto xy_at(x_coord_t x, y_coord_t y) const -> xy_locator
292  {
293  // TODO: Are relative locations of neighbors with negative offsets valid? Sampling?
294  BOOST_ASSERT(x < width());
295  BOOST_ASSERT(y < height());
296  return _pixels + point_t(x, y);
297  }
298 
299  auto xy_at(point_t const& p) const -> locator
300  {
301  // TODO: Are relative locations of neighbors with negative offsets valid? Sampling?
302  BOOST_ASSERT(p.x < width());
303  BOOST_ASSERT(p.y < height());
304  return _pixels + p;
305  }
306  //\}@
307 
308  //\{@
310  auto x_at(x_coord_t x, y_coord_t y) const -> x_iterator
311  {
312  BOOST_ASSERT(0 <= x && x <= width()); // allow request for [begin, end] inclusive
313  BOOST_ASSERT(0 <= y && y < height());
314  return _pixels.x_at(x, y);
315  }
316 
317  auto x_at(point_t const& p) const -> x_iterator
318  {
319  BOOST_ASSERT(0 <= p.x && p.x <= width()); // allow request for [begin, end] inclusive
320  BOOST_ASSERT(0 <= p.y && p.y < height());
321  return _pixels.x_at(p);
322  }
323 
324  auto row_begin(y_coord_t y) const -> x_iterator
325  {
326  BOOST_ASSERT(0 <= y && y < height());
327  return x_at(0, y);
328  }
329 
330  auto row_end(y_coord_t y) const -> x_iterator
331  {
332  BOOST_ASSERT(0 <= y && y < height());
333  return x_at(width(), y);
334  }
335  //\}@
336 
337  //\{@
339  auto y_at(x_coord_t x, y_coord_t y) const -> y_iterator
340  {
341  BOOST_ASSERT(0 <= x && x < width());
342  BOOST_ASSERT(0 <= y && y <= height()); // allow request for [begin, end] inclusive
343  return xy_at(x, y).y();
344  }
345 
346  auto y_at(point_t const& p) const -> y_iterator
347  {
348  BOOST_ASSERT(0 <= p.x && p.x < width());
349  BOOST_ASSERT(0 <= p.y && p.y <= height()); // allow request for [begin, end] inclusive
350  return xy_at(p).y();
351  }
352 
353  auto col_begin(x_coord_t x) const -> y_iterator
354  {
355  BOOST_ASSERT(0 <= x && x < width());
356  return y_at(x, 0);
357  }
358 
359  auto col_end(x_coord_t x) const -> y_iterator
360  {
361  BOOST_ASSERT(0 <= x && x < width());
362  return y_at(x, height());
363  }
364  //\}@
365 
366 private:
367  template <typename L2>
368  friend class image_view;
369 
370  point_t _dimensions;
371  xy_locator _pixels;
372 };
373 
374 template <typename L2>
375 inline void swap(image_view<L2>& x, image_view<L2>& y) {
376  using std::swap;
377  swap(x._dimensions,y._dimensions);
378  swap(x._pixels, y._pixels); // TODO: Extend further
379 }
380 
382 // PixelBasedConcept
384 
385 template <typename L>
386 struct channel_type<image_view<L> > : public channel_type<L> {};
387 
388 template <typename L>
389 struct color_space_type<image_view<L> > : public color_space_type<L> {};
390 
391 template <typename L>
392 struct channel_mapping_type<image_view<L> > : public channel_mapping_type<L> {};
393 
394 template <typename L>
395 struct is_planar<image_view<L> > : public is_planar<L> {};
396 
398 // HasDynamicXStepTypeConcept
400 
401 template <typename L>
402 struct dynamic_x_step_type<image_view<L>>
403 {
404  using type = image_view<typename gil::dynamic_x_step_type<L>::type>;
405 };
406 
408 // HasDynamicYStepTypeConcept
410 
411 template <typename L>
412 struct dynamic_y_step_type<image_view<L>>
413 {
414  using type = image_view<typename gil::dynamic_y_step_type<L>::type>;
415 };
416 
418 // HasTransposedTypeConcept
420 
421 template <typename L>
422 struct transposed_type<image_view<L>>
423 {
424  using type = image_view<typename transposed_type<L>::type>;
425 };
426 
427 }} // namespace boost::gil
428 
429 #endif
A lightweight object that interprets memory as a 2D array of pixels. Models ImageViewConcept,...
Definition: image_view.hpp:53
Provides 1D random-access navigation to the pixels of the image. Models: PixelIteratorConcept,...
Definition: iterator_from_2d.hpp:42
auto back() const -> reference
Returns a reference to the last element in raster order.
Definition: image_view.hpp:205
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
void swap(boost::gil::packed_channel_reference< BF, FB, NB, M > const x, R &y)
swap for packed_channel_reference
Definition: channel.hpp:529
bool empty() const
Returns true if the view has no elements, false otherwise.
Definition: image_view.hpp:186
const image< Pixel, IsPlanar, Alloc >::view_t & view(image< Pixel, IsPlanar, Alloc > &img)
Returns the non-constant-pixel view of an image.
Definition: image.hpp:443
Returns an integral constant type specifying the number of elements in a color base.
Definition: color_base_algorithm.hpp:42
auto front() const -> reference
Returns a reference to the first element in raster order.
Definition: image_view.hpp:195