Boost GIL


image_view_factory.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_FACTORY_HPP
9 #define BOOST_GIL_IMAGE_VIEW_FACTORY_HPP
10 
11 #include <boost/gil/color_convert.hpp>
12 #include <boost/gil/dynamic_step.hpp>
13 #include <boost/gil/gray.hpp>
14 #include <boost/gil/image_view.hpp>
15 #include <boost/gil/metafunctions.hpp>
16 #include <boost/gil/point.hpp>
17 #include <boost/gil/detail/mp11.hpp>
18 
19 #include <boost/assert.hpp>
20 
21 #include <cstddef>
22 #include <type_traits>
23 
27 
31 
35 
36 namespace boost { namespace gil {
37 
38 struct default_color_converter;
39 
40 template <typename T> struct transposed_type;
41 
44 template <typename View>
46  : dynamic_y_step_type<typename dynamic_x_step_type<View>::type> {};
47 
50 template <typename View>
52  : dynamic_xy_step_type<typename transposed_type<View>::type> {};
53 
56 template <typename Iterator>
58 interleaved_view(std::size_t width, std::size_t height,
59  Iterator pixels, std::ptrdiff_t rowsize_in_bytes) {
60  using RView = typename type_from_x_iterator<Iterator>::view_t;
61  return RView(width, height, typename RView::locator(pixels, rowsize_in_bytes));
62 }
63 
66 template <typename Iterator>
67 auto interleaved_view(point<std::size_t> dim, Iterator pixels,
68  std::ptrdiff_t rowsize_in_bytes)
70 {
71  using RView = typename type_from_x_iterator<Iterator>::view_t;
72  return RView(dim, typename RView::locator(pixels, rowsize_in_bytes));
73 }
74 
76 // interleaved_view_get_raw_data, planar_view_get_raw_data - return pointers to the raw data (the channels) of a basic homogeneous view.
78 
79 namespace detail {
80  template <typename View, bool IsMutable> struct channel_pointer_type_impl;
81 
82  template <typename View> struct channel_pointer_type_impl<View, true> {
83  using type = typename channel_type<View>::type *;
84  };
85  template <typename View> struct channel_pointer_type_impl<View, false> {
86  using type = const typename channel_type<View>::type *;
87  };
88 
89  template <typename View> struct channel_pointer_type
90  : public channel_pointer_type_impl<View, view_is_mutable<View>::value> {};
91 } // namespace detail
92 
95 template <typename HomogeneousView>
96 typename detail::channel_pointer_type<HomogeneousView>::type interleaved_view_get_raw_data(const HomogeneousView& view) {
97  static_assert(!is_planar<HomogeneousView>::value && view_is_basic<HomogeneousView>::value, "");
98  static_assert(std::is_pointer<typename HomogeneousView::x_iterator>::value, "");
99 
100  return &gil::at_c<0>(view(0,0));
101 }
102 
105 template <typename HomogeneousView>
106 typename detail::channel_pointer_type<HomogeneousView>::type planar_view_get_raw_data(const HomogeneousView& view, int plane_index) {
107  static_assert(is_planar<HomogeneousView>::value && view_is_basic<HomogeneousView>::value, "");
108  return dynamic_at_c(view.row_begin(0),plane_index);
109 }
110 
111 
115 
120 template <typename SrcConstRefP, typename DstP, typename CC=default_color_converter > // const_reference to the source pixel and destination pixel value
121 class color_convert_deref_fn : public deref_base<color_convert_deref_fn<SrcConstRefP,DstP,CC>, DstP, DstP, const DstP&, SrcConstRefP, DstP, false> {
122 private:
123  CC _cc; // color-converter
124 public:
126  color_convert_deref_fn(CC cc_in) : _cc(cc_in) {}
127 
128  DstP operator()(SrcConstRefP srcP) const {
129  DstP dstP;
130  _cc(srcP,dstP);
131  return dstP;
132  }
133 };
134 
135 namespace detail {
136  // Add color converter upon dereferencing
137  template <typename SrcView, typename CC, typename DstP, typename SrcP>
138  struct _color_converted_view_type {
139  private:
141  using add_ref_t = typename SrcView::template add_deref<deref_t>;
142  public:
143  using type = typename add_ref_t::type;
144  static type make(const SrcView& sv,CC cc) {return add_ref_t::make(sv,deref_t(cc));}
145  };
146 
147  // If the Src view has the same pixel type as the target, there is no need for color conversion
148  template <typename SrcView, typename CC, typename DstP>
149  struct _color_converted_view_type<SrcView,CC,DstP,DstP> {
150  using type = SrcView;
151  static type make(const SrcView& sv,CC) {return sv;}
152  };
153 } // namespace detail
154 
155 
158 template <typename SrcView, typename DstP, typename CC=default_color_converter>
159 struct color_converted_view_type : public detail::_color_converted_view_type<SrcView,
160  CC,
161  DstP,
162  typename SrcView::value_type> {
163  BOOST_GIL_CLASS_REQUIRE(DstP, boost::gil, MutablePixelConcept)//why does it have to be mutable???
164 };
165 
166 
169 template <typename DstP, typename View, typename CC>
172 }
173 
176 template <typename DstP, typename View>
177 inline typename color_converted_view_type<View,DstP>::type
178 color_converted_view(const View& src) {
179  return color_converted_view<DstP>(src,default_color_converter());
180 }
181 
185 
187 template <typename View>
188 inline typename dynamic_y_step_type<View>::type flipped_up_down_view(const View& src) {
189  using RView = typename dynamic_y_step_type<View>::type;
190  return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1));
191 }
192 
196 
198 template <typename View>
199 inline typename dynamic_x_step_type<View>::type flipped_left_right_view(const View& src) {
200  using RView = typename dynamic_x_step_type<View>::type;
201  return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(src.width()-1,0),-1,1));
202 }
203 
207 
209 template <typename View>
210 inline typename dynamic_xy_step_transposed_type<View>::type transposed_view(const View& src) {
211  using RView = typename dynamic_xy_step_transposed_type<View>::type;
212  return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(0,0),1,1,true));
213 }
214 
218 
220 template <typename View>
221 inline typename dynamic_xy_step_transposed_type<View>::type rotated90cw_view(const View& src) {
222  using RView = typename dynamic_xy_step_transposed_type<View>::type;
223  return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1,1,true));
224 }
225 
229 
231 template <typename View>
232 inline typename dynamic_xy_step_transposed_type<View>::type rotated90ccw_view(const View& src) {
233  using RView = typename dynamic_xy_step_transposed_type<View>::type;
234  return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(src.width()-1,0),1,-1,true));
235 }
236 
240 
242 template <typename View>
243 inline typename dynamic_xy_step_type<View>::type rotated180_view(const View& src) {
244  using RView = typename dynamic_xy_step_type<View>::type;
245  return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(src.width()-1,src.height()-1),-1,-1));
246 }
247 
251 
253 template <typename View>
254 inline View subimage_view(
255  View const& src,
256  typename View::point_t const& topleft,
257  typename View::point_t const& dimensions)
258 {
259  return View(dimensions, src.xy_at(topleft));
260 }
261 
263 template <typename View>
264 inline View subimage_view(View const& src,
265  typename View::coord_t x_min,
266  typename View::coord_t y_min,
267  typename View::coord_t width,
268  typename View::coord_t height)
269 {
270  return View(width, height, src.xy_at(x_min, y_min));
271 }
272 
276 
278 template <typename View>
279 inline
280 auto subsampled_view(View const& src, typename View::coord_t x_step, typename View::coord_t y_step)
281  -> typename dynamic_xy_step_type<View>::type
282 {
283  BOOST_ASSERT(x_step > 0 && y_step > 0);
284  using view_t =typename dynamic_xy_step_type<View>::type;
285  return view_t(
286  (src.width() + (x_step - 1)) / x_step,
287  (src.height() + (y_step - 1)) / y_step,
288  typename view_t::xy_locator(src.xy_at(0,0), x_step, y_step));
289 }
290 
292 template <typename View>
293 inline auto subsampled_view(View const& src, typename View::point_t const& step)
294  -> typename dynamic_xy_step_type<View>::type
295 {
296  return subsampled_view(src, step.x, step.y);
297 }
298 
302 
303 namespace detail {
304  template <typename View, bool AreChannelsTogether> struct __nth_channel_view_basic;
305 
306  // nth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images
307  // or images with a step
308  template <typename View>
309  struct __nth_channel_view_basic<View,false> {
310  using type = typename view_type<typename channel_type<View>::type, gray_layout_t, false, true, view_is_mutable<View>::value>::type;
311 
312  static type make(const View& src, int n) {
313  using locator_t = typename type::xy_locator;
314  using x_iterator_t = typename type::x_iterator;
315  using x_iterator_base_t = typename iterator_adaptor_get_base<x_iterator_t>::type;
316  x_iterator_t sit(x_iterator_base_t(&(src(0,0)[n])),src.pixels().pixel_size());
317  return type(src.dimensions(),locator_t(sit, src.pixels().row_size()));
318  }
319  };
320 
321  // nth_channel_view when the channels are together in memory (true for simple grayscale or planar images)
322  template <typename View>
323  struct __nth_channel_view_basic<View,true> {
324  using type = typename view_type<typename channel_type<View>::type, gray_layout_t, false, false, view_is_mutable<View>::value>::type;
325  static type make(const View& src, int n) {
326  using x_iterator_t = typename type::x_iterator;
327  return interleaved_view(src.width(),src.height(),(x_iterator_t)&(src(0,0)[n]), src.pixels().row_size());
328  }
329  };
330 
331  template <typename View, bool IsBasic> struct __nth_channel_view;
332 
333  // For basic (memory-based) views dispatch to __nth_channel_view_basic
334  template <typename View>
335  struct __nth_channel_view<View,true>
336  {
337  private:
338  using src_x_iterator = typename View::x_iterator;
339 
340  // Determines whether the channels of a given pixel iterator are adjacent in memory.
341  // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not.
342  static constexpr bool adjacent =
343  !iterator_is_step<src_x_iterator>::value &&
344  (is_planar<src_x_iterator>::value || num_channels<View>::value == 1);
345 
346  public:
347  using type = typename __nth_channel_view_basic<View,adjacent>::type;
348 
349  static type make(const View& src, int n) {
350  return __nth_channel_view_basic<View,adjacent>::make(src,n);
351  }
352  };
353 
358  template <typename SrcP> // SrcP is a reference to PixelConcept (could be pixel value or const/non-const reference)
359  // Examples: pixel<T,L>, pixel<T,L>&, const pixel<T,L>&, planar_pixel_reference<T&,L>, planar_pixel_reference<const T&,L>
361  {
362  static constexpr bool is_mutable =
364  private:
365  using src_pixel_t = typename std::remove_reference<SrcP>::type;
366  using channel_t = typename channel_type<src_pixel_t>::type;
367  using const_ref_t = typename src_pixel_t::const_reference;
369  public:
371  using value_type = typename pixel_value_type<channel_t,gray_layout_t>::type;
373  using argument_type = SrcP;
374  using reference = mp11::mp_if_c<is_mutable, ref_t, value_type>;
375  using result_type = reference;
376 
377  nth_channel_deref_fn(int n=0) : _n(n) {}
378  template <typename P> nth_channel_deref_fn(const nth_channel_deref_fn<P>& d) : _n(d._n) {}
379 
380  int _n; // the channel to use
381 
382  result_type operator()(argument_type srcP) const {
383  return result_type(srcP[_n]);
384  }
385  };
386 
387  template <typename View> struct __nth_channel_view<View,false> {
388  private:
390  using AD = typename View::template add_deref<deref_t>;
391  public:
392  using type = typename AD::type;
393  static type make(const View& src, int n) {
394  return AD::make(src, deref_t(n));
395  }
396  };
397 } // namespace detail
398 
405 template <typename View>
407 private:
408  BOOST_GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept)
409  using VB = detail::__nth_channel_view<View,view_is_basic<View>::value>;
410 public:
411  using type = typename VB::type;
412  static type make(const View& src, int n) { return VB::make(src,n); }
413 };
414 
415 
417 template <typename View>
418 typename nth_channel_view_type<View>::type nth_channel_view(const View& src, int n) {
419  return nth_channel_view_type<View>::make(src,n);
420 }
421 
422 
423 
424 
425 
426 
427 
431 
432 namespace detail {
433  template <int K, typename View, bool AreChannelsTogether> struct __kth_channel_view_basic;
434 
435  // kth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images
436  // or images with a step
437  template <int K, typename View>
438  struct __kth_channel_view_basic<K,View,false> {
439  private:
440  using channel_t = typename kth_element_type<typename View::value_type,K>::type;
441  public:
442  using type = typename view_type<channel_t, gray_layout_t, false, true, view_is_mutable<View>::value>::type;
443 
444  static type make(const View& src) {
445  using locator_t = typename type::xy_locator;
446  using x_iterator_t = typename type::x_iterator;
447  using x_iterator_base_t = typename iterator_adaptor_get_base<x_iterator_t>::type;
448  x_iterator_t sit(x_iterator_base_t(&gil::at_c<K>(src(0,0))),src.pixels().pixel_size());
449  return type(src.dimensions(),locator_t(sit, src.pixels().row_size()));
450  }
451  };
452 
453  // kth_channel_view when the channels are together in memory (true for simple grayscale or planar images)
454  template <int K, typename View>
455  struct __kth_channel_view_basic<K,View,true> {
456  private:
457  using channel_t = typename kth_element_type<typename View::value_type, K>::type;
458  public:
459  using type = typename view_type<channel_t, gray_layout_t, false, false, view_is_mutable<View>::value>::type;
460  static type make(const View& src) {
461  using x_iterator_t = typename type::x_iterator;
462  return interleaved_view(src.width(),src.height(),(x_iterator_t)&gil::at_c<K>(src(0,0)), src.pixels().row_size());
463  }
464  };
465 
466  template <int K, typename View, bool IsBasic> struct __kth_channel_view;
467 
468  // For basic (memory-based) views dispatch to __kth_channel_view_basic
469  template <int K, typename View> struct __kth_channel_view<K,View,true>
470  {
471  private:
472  using src_x_iterator = typename View::x_iterator;
473 
474  // Determines whether the channels of a given pixel iterator are adjacent in memory.
475  // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not.
476  static constexpr bool adjacent =
477  !iterator_is_step<src_x_iterator>::value &&
478  (is_planar<src_x_iterator>::value || num_channels<View>::value == 1);
479 
480  public:
481  using type = typename __kth_channel_view_basic<K,View,adjacent>::type;
482 
483  static type make(const View& src) {
484  return __kth_channel_view_basic<K,View,adjacent>::make(src);
485  }
486  };
487 
494  template <int K, typename SrcP>
496  {
497  static constexpr bool is_mutable =
499 
500  private:
501  using src_pixel_t = typename std::remove_reference<SrcP>::type;
502  using channel_t = typename kth_element_type<src_pixel_t, K>::type;
503  using const_ref_t = typename src_pixel_t::const_reference;
505 
506  public:
508  using value_type = typename pixel_value_type<channel_t,gray_layout_t>::type;
510  using argument_type = SrcP;
511  using reference = mp11::mp_if_c<is_mutable, ref_t, value_type>;
512  using result_type = reference;
513 
515  template <typename P> kth_channel_deref_fn(const kth_channel_deref_fn<K,P>&) {}
516 
517  result_type operator()(argument_type srcP) const {
518  return result_type(gil::at_c<K>(srcP));
519  }
520  };
521 
522  template <int K, typename View> struct __kth_channel_view<K,View,false> {
523  private:
525  using AD = typename View::template add_deref<deref_t>;
526  public:
527  using type = typename AD::type;
528  static type make(const View& src) {
529  return AD::make(src, deref_t());
530  }
531  };
532 } // namespace detail
533 
540 template <int K, typename View>
542 private:
543  BOOST_GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept)
544  using VB = detail::__kth_channel_view<K,View,view_is_basic<View>::value>;
545 public:
546  using type = typename VB::type;
547  static type make(const View& src) { return VB::make(src); }
548 };
549 
551 template <int K, typename View>
552 typename kth_channel_view_type<K,View>::type kth_channel_view(const View& src) {
554 }
555 
556 } } // namespace boost::gil
557 
558 #endif
Returns the type of a transposed view that has a dynamic step along both X and Y.
Definition: image_view_factory.hpp:51
A lightweight object that interprets memory as a 2D array of pixels. Models ImageViewConcept,...
Definition: image_view.hpp:53
Represents a pixel value (a container of channels). Models: HomogeneousColorBaseValueConcept,...
Definition: metafunctions.hpp:23
Function object that given a source pixel, returns it converted to a given color space and channel de...
Definition: image_view_factory.hpp:121
Returns the type of a view that has a dynamic step along both X and Y.
Definition: dynamic_step.hpp:27
Given a source image view type View, returns the type of an image view over a single channel of ViewI...
Definition: image_view_factory.hpp:406
Helper base class for pixel dereference adaptors.
Definition: utilities.hpp:106
Function object that returns a grayscale reference of the K-th channel (specified as a template param...
Definition: image_view_factory.hpp:495
Returns the type of a view that does color conversion upon dereferencing its pixels.
Definition: image_view_factory.hpp:159
Determines if the given pixel reference is mutable (i.e. its channels can be changed)
Definition: metafunctions.hpp:228
Definition: image_view_factory.hpp:40
Function object that returns a grayscale reference of the N-th channel of a given reference....
Definition: image_view_factory.hpp:360
detail::channel_pointer_type< HomogeneousView >::type planar_view_get_raw_data(const HomogeneousView &view, int plane_index)
Returns C pointer to the the channels of a given color plane of a planar homogeneous view.
Definition: image_view_factory.hpp:106
auto interleaved_view(point< std::size_t > dim, Iterator pixels, std::ptrdiff_t rowsize_in_bytes) -> typename type_from_x_iterator< Iterator >::view_t
Constructing image views from raw interleaved pixel data.
Definition: image_view_factory.hpp:67
Pixel concept that allows for changing its channels.
Definition: concepts/pixel.hpp:101
Returns the type of a homogeneous pixel reference given the channel type, layout, whether it operates...
Definition: metafunctions.hpp:266
Base template for types that model HasDynamicYStepTypeConcept.
Definition: dynamic_step.hpp:21
detail::channel_pointer_type< HomogeneousView >::type interleaved_view_get_raw_data(const HomogeneousView &view)
Returns C pointer to the the channels of an interleaved homogeneous view.
Definition: image_view_factory.hpp:96
Definition: color_convert.hpp:31
GIL's 2-dimensional view over immutable GIL pixels.
Definition: concepts/image_view.hpp:375
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:535
color_converted_view_type< View, DstP >::type color_converted_view(const View &src)
overload of generic color_converted_view with the default color-converter
Definition: image_view_factory.hpp:178
Given a model of a pixel, determines whether the model represents a pixel reference (as opposed to pi...
Definition: metafunctions.hpp:216
class for color-converting one pixel to another
Definition: color_convert.hpp:295
Basic views must be over basic locators.
Definition: metafunctions.hpp:129
Given a source image view type View, returns the type of an image view over a given channel of View....
Definition: image_view_factory.hpp:541
2D point both axes of which have the same dimension typeModels: Point2DConcept
Definition: locator.hpp:28