image_view_factory.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  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. #include <boost/gil/color_convert.hpp>
  11. #include <boost/gil/dynamic_step.hpp>
  12. #include <boost/gil/gray.hpp>
  13. #include <boost/gil/image_view.hpp>
  14. #include <boost/gil/metafunctions.hpp>
  15. #include <boost/gil/point.hpp>
  16. #include <boost/gil/detail/mp11.hpp>
  17. #include <boost/assert.hpp>
  18. #include <cstddef>
  19. #include <type_traits>
  20. /// Methods for creating shallow image views from raw pixel data or from other image views -
  21. /// flipping horizontally or vertically, axis-aligned rotation, a subimage, subsampled
  22. /// or n-th channel image view. Derived image views are shallow copies and are fast to construct.
  23. /// \defgroup ImageViewConstructors Image View From Raw Data
  24. /// \ingroup ImageViewAlgorithm
  25. /// \brief Methods for constructing image views from raw data and for getting raw data from views
  26. /// \defgroup ImageViewTransformations Image View Transformations
  27. /// \ingroup ImageViewAlgorithm
  28. /// \brief Methods for constructing one image view from another
  29. namespace boost { namespace gil {
  30. struct default_color_converter;
  31. template <typename T> struct transposed_type;
  32. /// \brief Returns the type of a view that has a dynamic step along both X and Y
  33. /// \ingroup ImageViewTransformations
  34. template <typename View>
  35. struct dynamic_xy_step_type
  36. : dynamic_y_step_type<typename dynamic_x_step_type<View>::type> {};
  37. /// \brief Returns the type of a transposed view that has a dynamic step along both X and Y
  38. /// \ingroup ImageViewTransformations
  39. template <typename View>
  40. struct dynamic_xy_step_transposed_type
  41. : dynamic_xy_step_type<typename transposed_type<View>::type> {};
  42. /// \ingroup ImageViewConstructors
  43. /// \brief Constructing image views from raw interleaved pixel data
  44. template <typename Iterator>
  45. auto interleaved_view(
  46. std::size_t width, std::size_t height,
  47. Iterator pixels, std::ptrdiff_t rowsize_in_bytes)
  48. -> typename type_from_x_iterator<Iterator>::view_t
  49. {
  50. using RView = typename type_from_x_iterator<Iterator>::view_t;
  51. return RView(width, height, typename RView::locator(pixels, rowsize_in_bytes));
  52. }
  53. /// \ingroup ImageViewConstructors
  54. /// \brief Constructing image views from raw interleaved pixel data
  55. template <typename Iterator>
  56. auto interleaved_view(
  57. point<std::ptrdiff_t> dim, Iterator pixels,
  58. std::ptrdiff_t rowsize_in_bytes)
  59. -> typename type_from_x_iterator<Iterator>::view_t
  60. {
  61. using RView = typename type_from_x_iterator<Iterator>::view_t;
  62. return RView(dim, typename RView::locator(pixels, rowsize_in_bytes));
  63. }
  64. /////////////////////////////
  65. // interleaved_view_get_raw_data, planar_view_get_raw_data - return pointers to the raw data (the channels) of a basic homogeneous view.
  66. /////////////////////////////
  67. namespace detail {
  68. template <typename View, bool IsMutable>
  69. struct channel_pointer_type_impl;
  70. template <typename View>
  71. struct channel_pointer_type_impl<View, true>
  72. {
  73. using type = typename channel_type<View>::type*;
  74. };
  75. template <typename View>
  76. struct channel_pointer_type_impl<View, false>
  77. {
  78. using type = const typename channel_type<View>::type*;
  79. };
  80. template <typename View>
  81. struct channel_pointer_type
  82. : public channel_pointer_type_impl<View, view_is_mutable<View>::value> {};
  83. } // namespace detail
  84. /// \ingroup ImageViewConstructors
  85. /// \brief Returns C pointer to the the channels of an interleaved homogeneous view.
  86. template <typename HomogeneousView>
  87. auto interleaved_view_get_raw_data(HomogeneousView const& view)
  88. -> typename detail::channel_pointer_type<HomogeneousView>::type
  89. {
  90. static_assert(!is_planar<HomogeneousView>::value && view_is_basic<HomogeneousView>::value, "");
  91. static_assert(std::is_pointer<typename HomogeneousView::x_iterator>::value, "");
  92. return &gil::at_c<0>(view(0,0));
  93. }
  94. /// \ingroup ImageViewConstructors
  95. /// \brief Returns C pointer to the the channels of a given color plane of a planar homogeneous view.
  96. template <typename HomogeneousView>
  97. auto planar_view_get_raw_data(HomogeneousView const& view, int plane_index)
  98. -> typename detail::channel_pointer_type<HomogeneousView>::type
  99. {
  100. static_assert(is_planar<HomogeneousView>::value && view_is_basic<HomogeneousView>::value, "");
  101. return dynamic_at_c(view.row_begin(0),plane_index);
  102. }
  103. /// \defgroup ImageViewTransformationsColorConvert color_converted_view
  104. /// \ingroup ImageViewTransformations
  105. /// \brief Color converted view of another view
  106. /// \ingroup ImageViewTransformationsColorConvert PixelDereferenceAdaptorModel
  107. /// \brief Function object that given a source pixel, returns it converted to a given color space and channel depth. Models: PixelDereferenceAdaptorConcept
  108. ///
  109. /// Useful in constructing a color converted view over a given image view
  110. template <typename SrcConstRefP, typename DstP, typename CC=default_color_converter > // const_reference to the source pixel and destination pixel value
  111. class color_convert_deref_fn : public deref_base<color_convert_deref_fn<SrcConstRefP,DstP,CC>, DstP, DstP, const DstP&, SrcConstRefP, DstP, false> {
  112. private:
  113. CC _cc; // color-converter
  114. public:
  115. color_convert_deref_fn() {}
  116. color_convert_deref_fn(CC cc_in) : _cc(cc_in) {}
  117. DstP operator()(SrcConstRefP srcP) const {
  118. DstP dstP;
  119. _cc(srcP,dstP);
  120. return dstP;
  121. }
  122. };
  123. namespace detail {
  124. // Add color converter upon dereferencing
  125. template <typename SrcView, typename CC, typename DstP, typename SrcP>
  126. struct _color_converted_view_type {
  127. private:
  128. using deref_t = color_convert_deref_fn<typename SrcView::const_t::reference,DstP,CC>;
  129. using add_ref_t = typename SrcView::template add_deref<deref_t>;
  130. public:
  131. using type = typename add_ref_t::type;
  132. static type make(const SrcView& sv,CC cc) {return add_ref_t::make(sv,deref_t(cc));}
  133. };
  134. // If the Src view has the same pixel type as the target, there is no need for color conversion
  135. template <typename SrcView, typename CC, typename DstP>
  136. struct _color_converted_view_type<SrcView,CC,DstP,DstP> {
  137. using type = SrcView;
  138. static type make(const SrcView& sv,CC) {return sv;}
  139. };
  140. } // namespace detail
  141. /// \brief Returns the type of a view that does color conversion upon dereferencing its pixels
  142. /// \ingroup ImageViewTransformationsColorConvert
  143. template <typename SrcView, typename DstP, typename CC=default_color_converter>
  144. struct color_converted_view_type : public detail::_color_converted_view_type<SrcView,
  145. CC,
  146. DstP,
  147. typename SrcView::value_type> {
  148. BOOST_GIL_CLASS_REQUIRE(DstP, boost::gil, MutablePixelConcept)//why does it have to be mutable???
  149. };
  150. /// \ingroup ImageViewTransformationsColorConvert
  151. /// \brief view of a different color space with a user defined color-converter
  152. template <typename DstP, typename View, typename CC>
  153. inline auto color_converted_view(View const& src,CC cc)
  154. -> typename color_converted_view_type<View,DstP,CC>::type
  155. {
  156. return color_converted_view_type<View,DstP,CC>::make(src,cc);
  157. }
  158. /// \ingroup ImageViewTransformationsColorConvert
  159. /// \brief overload of generic color_converted_view with the default color-converter
  160. template <typename DstP, typename View>
  161. inline auto color_converted_view(View const& src)
  162. -> typename color_converted_view_type<View,DstP>::type
  163. {
  164. return color_converted_view<DstP>(src,default_color_converter());
  165. }
  166. /// \defgroup ImageViewTransformationsFlipUD flipped_up_down_view
  167. /// \ingroup ImageViewTransformations
  168. /// \brief view of a view flipped up-to-down
  169. /// \ingroup ImageViewTransformationsFlipUD
  170. template <typename View>
  171. inline auto flipped_up_down_view(View const& src)
  172. -> typename dynamic_y_step_type<View>::type
  173. {
  174. using RView = typename dynamic_y_step_type<View>::type;
  175. return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1));
  176. }
  177. /// \defgroup ImageViewTransformationsFlipLR flipped_left_right_view
  178. /// \ingroup ImageViewTransformations
  179. /// \brief view of a view flipped left-to-right
  180. /// \ingroup ImageViewTransformationsFlipLR
  181. template <typename View>
  182. inline auto flipped_left_right_view(View const& src)
  183. -> typename dynamic_x_step_type<View>::type
  184. {
  185. using RView = typename dynamic_x_step_type<View>::type;
  186. return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(src.width()-1,0),-1,1));
  187. }
  188. /// \defgroup ImageViewTransformationsTransposed transposed_view
  189. /// \ingroup ImageViewTransformations
  190. /// \brief view of a view transposed
  191. /// \ingroup ImageViewTransformationsTransposed
  192. template <typename View>
  193. inline auto transposed_view(View const& src)
  194. -> typename dynamic_xy_step_transposed_type<View>::type
  195. {
  196. using RView = typename dynamic_xy_step_transposed_type<View>::type;
  197. return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(0,0),1,1,true));
  198. }
  199. /// \defgroup ImageViewTransformations90CW rotated90cw_view
  200. /// \ingroup ImageViewTransformations
  201. /// \brief view of a view rotated 90 degrees clockwise
  202. /// \ingroup ImageViewTransformations90CW
  203. template <typename View>
  204. inline auto rotated90cw_view(View const& src)
  205. -> typename dynamic_xy_step_transposed_type<View>::type
  206. {
  207. using RView = typename dynamic_xy_step_transposed_type<View>::type;
  208. return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(0,src.height()-1),-1,1,true));
  209. }
  210. /// \defgroup ImageViewTransformations90CCW rotated90ccw_view
  211. /// \ingroup ImageViewTransformations
  212. /// \brief view of a view rotated 90 degrees counter-clockwise
  213. /// \ingroup ImageViewTransformations90CCW
  214. template <typename View>
  215. inline auto rotated90ccw_view(View const& src)
  216. -> typename dynamic_xy_step_transposed_type<View>::type
  217. {
  218. using RView = typename dynamic_xy_step_transposed_type<View>::type;
  219. return RView(src.height(),src.width(),typename RView::xy_locator(src.xy_at(src.width()-1,0),1,-1,true));
  220. }
  221. /// \defgroup ImageViewTransformations180 rotated180_view
  222. /// \ingroup ImageViewTransformations
  223. /// \brief view of a view rotated 180 degrees
  224. /// \ingroup ImageViewTransformations180
  225. template <typename View>
  226. inline auto rotated180_view(View const& src)
  227. -> typename dynamic_xy_step_type<View>::type
  228. {
  229. using RView = typename dynamic_xy_step_type<View>::type;
  230. return RView(src.dimensions(),typename RView::xy_locator(src.xy_at(src.width()-1,src.height()-1),-1,-1));
  231. }
  232. /// \defgroup ImageViewTransformationsSubimage subimage_view
  233. /// \ingroup ImageViewTransformations
  234. /// \brief view of an axis-aligned rectangular area within an image_view
  235. /// \ingroup ImageViewTransformationsSubimage
  236. template <typename View>
  237. inline View subimage_view(
  238. View const& src,
  239. typename View::point_t const& topleft,
  240. typename View::point_t const& dimensions)
  241. {
  242. return View(dimensions, src.xy_at(topleft));
  243. }
  244. /// \ingroup ImageViewTransformationsSubimage
  245. template <typename View>
  246. inline View subimage_view(View const& src,
  247. typename View::coord_t x_min,
  248. typename View::coord_t y_min,
  249. typename View::coord_t width,
  250. typename View::coord_t height)
  251. {
  252. return View(width, height, src.xy_at(x_min, y_min));
  253. }
  254. /// \defgroup ImageViewTransformationsSubsampled subsampled_view
  255. /// \ingroup ImageViewTransformations
  256. /// \brief view of a subsampled version of an image_view, stepping over a number of channels in X and number of rows in Y
  257. /// \ingroup ImageViewTransformationsSubsampled
  258. template <typename View>
  259. inline
  260. auto subsampled_view(View const& src, typename View::coord_t x_step, typename View::coord_t y_step)
  261. -> typename dynamic_xy_step_type<View>::type
  262. {
  263. BOOST_ASSERT(x_step > 0 && y_step > 0);
  264. using view_t =typename dynamic_xy_step_type<View>::type;
  265. return view_t(
  266. (src.width() + (x_step - 1)) / x_step,
  267. (src.height() + (y_step - 1)) / y_step,
  268. typename view_t::xy_locator(src.xy_at(0,0), x_step, y_step));
  269. }
  270. /// \ingroup ImageViewTransformationsSubsampled
  271. template <typename View>
  272. inline auto subsampled_view(View const& src, typename View::point_t const& step)
  273. -> typename dynamic_xy_step_type<View>::type
  274. {
  275. return subsampled_view(src, step.x, step.y);
  276. }
  277. /// \defgroup ImageViewTransformationsNthChannel nth_channel_view
  278. /// \ingroup ImageViewTransformations
  279. /// \brief single-channel (grayscale) view of the N-th channel of a given image_view
  280. namespace detail {
  281. template <typename View, bool AreChannelsTogether> struct __nth_channel_view_basic;
  282. // nth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images
  283. // or images with a step
  284. template <typename View>
  285. struct __nth_channel_view_basic<View,false> {
  286. using type = typename view_type<typename channel_type<View>::type, gray_layout_t, false, true, view_is_mutable<View>::value>::type;
  287. static type make(View const& src, int n) {
  288. using locator_t = typename type::xy_locator;
  289. using x_iterator_t = typename type::x_iterator;
  290. using x_iterator_base_t = typename iterator_adaptor_get_base<x_iterator_t>::type;
  291. x_iterator_t sit(x_iterator_base_t(&(src(0,0)[n])),src.pixels().pixel_size());
  292. return type(src.dimensions(),locator_t(sit, src.pixels().row_size()));
  293. }
  294. };
  295. // nth_channel_view when the channels are together in memory (true for simple grayscale or planar images)
  296. template <typename View>
  297. struct __nth_channel_view_basic<View,true> {
  298. using type = typename view_type<typename channel_type<View>::type, gray_layout_t, false, false, view_is_mutable<View>::value>::type;
  299. static type make(View const& src, int n) {
  300. using x_iterator_t = typename type::x_iterator;
  301. return interleaved_view(src.width(),src.height(),(x_iterator_t)&(src(0,0)[n]), src.pixels().row_size());
  302. }
  303. };
  304. template <typename View, bool IsBasic> struct __nth_channel_view;
  305. // For basic (memory-based) views dispatch to __nth_channel_view_basic
  306. template <typename View>
  307. struct __nth_channel_view<View,true>
  308. {
  309. private:
  310. using src_x_iterator = typename View::x_iterator;
  311. // Determines whether the channels of a given pixel iterator are adjacent in memory.
  312. // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not.
  313. static constexpr bool adjacent =
  314. !iterator_is_step<src_x_iterator>::value &&
  315. (is_planar<src_x_iterator>::value || num_channels<View>::value == 1);
  316. public:
  317. using type = typename __nth_channel_view_basic<View,adjacent>::type;
  318. static type make(View const& src, int n) {
  319. return __nth_channel_view_basic<View,adjacent>::make(src,n);
  320. }
  321. };
  322. /// \brief Function object that returns a grayscale reference of the N-th channel of a given reference. Models: PixelDereferenceAdaptorConcept.
  323. /// \ingroup PixelDereferenceAdaptorModel
  324. ///
  325. /// If the input is a pixel value or constant reference, the function object is immutable. Otherwise it is mutable (and returns non-const reference to the n-th channel)
  326. template <typename SrcP> // SrcP is a reference to PixelConcept (could be pixel value or const/non-const reference)
  327. // Examples: pixel<T,L>, pixel<T,L>&, const pixel<T,L>&, planar_pixel_reference<T&,L>, planar_pixel_reference<const T&,L>
  328. struct nth_channel_deref_fn
  329. {
  330. static constexpr bool is_mutable =
  331. pixel_is_reference<SrcP>::value && pixel_reference_is_mutable<SrcP>::value;
  332. private:
  333. using src_pixel_t = typename std::remove_reference<SrcP>::type;
  334. using channel_t = typename channel_type<src_pixel_t>::type;
  335. using const_ref_t = typename src_pixel_t::const_reference;
  336. using ref_t = typename pixel_reference_type<channel_t,gray_layout_t,false,is_mutable>::type;
  337. public:
  338. using const_t = nth_channel_deref_fn<const_ref_t>;
  339. using value_type = typename pixel_value_type<channel_t,gray_layout_t>::type;
  340. using const_reference = typename pixel_reference_type<channel_t,gray_layout_t,false,false>::type;
  341. using argument_type = SrcP;
  342. using reference = mp11::mp_if_c<is_mutable, ref_t, value_type>;
  343. using result_type = reference;
  344. nth_channel_deref_fn(int n=0) : _n(n) {}
  345. template <typename P>
  346. nth_channel_deref_fn(const nth_channel_deref_fn<P>& d) : _n(d._n) {}
  347. int _n; // the channel to use
  348. auto operator()(argument_type srcP) const -> result_type
  349. {
  350. return result_type(srcP[_n]);
  351. }
  352. };
  353. template <typename View> struct __nth_channel_view<View,false> {
  354. private:
  355. using deref_t = nth_channel_deref_fn<typename View::reference>;
  356. using AD = typename View::template add_deref<deref_t>;
  357. public:
  358. using type = typename AD::type;
  359. static type make(View const& src, int n) {
  360. return AD::make(src, deref_t(n));
  361. }
  362. };
  363. } // namespace detail
  364. /// \brief Given a source image view type View, returns the type of an image view over a single channel of View
  365. /// \ingroup ImageViewTransformationsNthChannel
  366. ///
  367. /// If the channels in the source view are adjacent in memory (such as planar non-step view or single-channel view) then the
  368. /// return view is a single-channel non-step view.
  369. /// If the channels are non-adjacent (interleaved and/or step view) then the return view is a single-channel step view.
  370. template <typename View>
  371. struct nth_channel_view_type {
  372. private:
  373. BOOST_GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept)
  374. using VB = detail::__nth_channel_view<View,view_is_basic<View>::value>;
  375. public:
  376. using type = typename VB::type;
  377. static type make(View const& src, int n) { return VB::make(src,n); }
  378. };
  379. /// \ingroup ImageViewTransformationsNthChannel
  380. template <typename View>
  381. typename nth_channel_view_type<View>::type nth_channel_view(View const& src, int n) {
  382. return nth_channel_view_type<View>::make(src,n);
  383. }
  384. /// \defgroup ImageViewTransformationsKthChannel kth_channel_view
  385. /// \ingroup ImageViewTransformations
  386. /// \brief single-channel (grayscale) view of the K-th channel of a given image_view. The channel index is a template parameter
  387. namespace detail {
  388. template <int K, typename View, bool AreChannelsTogether> struct __kth_channel_view_basic;
  389. // kth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images
  390. // or images with a step
  391. template <int K, typename View>
  392. struct __kth_channel_view_basic<K,View,false> {
  393. private:
  394. using channel_t = typename kth_element_type<typename View::value_type,K>::type;
  395. public:
  396. using type = typename view_type<channel_t, gray_layout_t, false, true, view_is_mutable<View>::value>::type;
  397. static type make(View const& src) {
  398. using locator_t = typename type::xy_locator;
  399. using x_iterator_t = typename type::x_iterator;
  400. using x_iterator_base_t = typename iterator_adaptor_get_base<x_iterator_t>::type;
  401. x_iterator_t sit(x_iterator_base_t(&gil::at_c<K>(src(0,0))),src.pixels().pixel_size());
  402. return type(src.dimensions(),locator_t(sit, src.pixels().row_size()));
  403. }
  404. };
  405. // kth_channel_view when the channels are together in memory (true for simple grayscale or planar images)
  406. template <int K, typename View>
  407. struct __kth_channel_view_basic<K,View,true> {
  408. private:
  409. using channel_t = typename kth_element_type<typename View::value_type, K>::type;
  410. public:
  411. using type = typename view_type<channel_t, gray_layout_t, false, false, view_is_mutable<View>::value>::type;
  412. static type make(View const& src) {
  413. using x_iterator_t = typename type::x_iterator;
  414. return interleaved_view(src.width(),src.height(),(x_iterator_t)&gil::at_c<K>(src(0,0)), src.pixels().row_size());
  415. }
  416. };
  417. template <int K, typename View, bool IsBasic> struct __kth_channel_view;
  418. // For basic (memory-based) views dispatch to __kth_channel_view_basic
  419. template <int K, typename View> struct __kth_channel_view<K,View,true>
  420. {
  421. private:
  422. using src_x_iterator = typename View::x_iterator;
  423. // Determines whether the channels of a given pixel iterator are adjacent in memory.
  424. // Planar and grayscale iterators have channels adjacent in memory, whereas multi-channel interleaved and iterators with non-fundamental step do not.
  425. static constexpr bool adjacent =
  426. !iterator_is_step<src_x_iterator>::value &&
  427. (is_planar<src_x_iterator>::value || num_channels<View>::value == 1);
  428. public:
  429. using type = typename __kth_channel_view_basic<K,View,adjacent>::type;
  430. static type make(View const& src) {
  431. return __kth_channel_view_basic<K,View,adjacent>::make(src);
  432. }
  433. };
  434. /// \brief Function object that returns a grayscale reference of the K-th channel (specified as a template parameter) of a given reference. Models: PixelDereferenceAdaptorConcept.
  435. /// \ingroup PixelDereferenceAdaptorModel
  436. ///
  437. /// If the input is a pixel value or constant reference, the function object is immutable. Otherwise it is mutable (and returns non-const reference to the k-th channel)
  438. /// \tparam SrcP reference to PixelConcept (could be pixel value or const/non-const reference)
  439. /// Examples: pixel<T,L>, pixel<T,L>&, const pixel<T,L>&, planar_pixel_reference<T&,L>, planar_pixel_reference<const T&,L>
  440. template <int K, typename SrcP>
  441. struct kth_channel_deref_fn
  442. {
  443. static constexpr bool is_mutable =
  444. pixel_is_reference<SrcP>::value && pixel_reference_is_mutable<SrcP>::value;
  445. private:
  446. using src_pixel_t = typename std::remove_reference<SrcP>::type;
  447. using channel_t = typename kth_element_type<src_pixel_t, K>::type;
  448. using const_ref_t = typename src_pixel_t::const_reference;
  449. using ref_t = typename pixel_reference_type<channel_t,gray_layout_t,false,is_mutable>::type;
  450. public:
  451. using const_t = kth_channel_deref_fn<K,const_ref_t>;
  452. using value_type = typename pixel_value_type<channel_t,gray_layout_t>::type;
  453. using const_reference = typename pixel_reference_type<channel_t,gray_layout_t,false,false>::type;
  454. using argument_type = SrcP;
  455. using reference = mp11::mp_if_c<is_mutable, ref_t, value_type>;
  456. using result_type = reference;
  457. kth_channel_deref_fn() {}
  458. template <typename P>
  459. kth_channel_deref_fn(const kth_channel_deref_fn<K,P>&) {}
  460. result_type operator()(argument_type srcP) const {
  461. return result_type(gil::at_c<K>(srcP));
  462. }
  463. };
  464. template <int K, typename View> struct __kth_channel_view<K,View,false> {
  465. private:
  466. using deref_t = kth_channel_deref_fn<K,typename View::reference>;
  467. using AD = typename View::template add_deref<deref_t>;
  468. public:
  469. using type = typename AD::type;
  470. static type make(View const& src) {
  471. return AD::make(src, deref_t());
  472. }
  473. };
  474. } // namespace detail
  475. /// \brief Given a source image view type View, returns the type of an image view over a given channel of View.
  476. /// \ingroup ImageViewTransformationsKthChannel
  477. ///
  478. /// If the channels in the source view are adjacent in memory (such as planar non-step view or single-channel view) then the
  479. /// return view is a single-channel non-step view.
  480. /// If the channels are non-adjacent (interleaved and/or step view) then the return view is a single-channel step view.
  481. template <int K, typename View>
  482. struct kth_channel_view_type {
  483. private:
  484. BOOST_GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept)
  485. using VB = detail::__kth_channel_view<K,View,view_is_basic<View>::value>;
  486. public:
  487. using type = typename VB::type;
  488. static type make(View const& src) { return VB::make(src); }
  489. };
  490. /// \ingroup ImageViewTransformationsKthChannel
  491. template <int K, typename View>
  492. auto kth_channel_view(View const& src)
  493. -> typename kth_channel_view_type<K,View>::type
  494. {
  495. return kth_channel_view_type<K,View>::make(src);
  496. }
  497. } } // namespace boost::gil
  498. #endif