image_view.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  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_CONCEPTS_IMAGE_VIEW_HPP
  9. #define BOOST_GIL_CONCEPTS_IMAGE_VIEW_HPP
  10. #include <boost/gil/concepts/basic.hpp>
  11. #include <boost/gil/concepts/concept_check.hpp>
  12. #include <boost/gil/concepts/fwd.hpp>
  13. #include <boost/gil/concepts/pixel.hpp>
  14. #include <boost/gil/concepts/pixel_dereference.hpp>
  15. #include <boost/gil/concepts/pixel_iterator.hpp>
  16. #include <boost/gil/concepts/pixel_locator.hpp>
  17. #include <boost/gil/concepts/point.hpp>
  18. #include <boost/gil/concepts/detail/utility.hpp>
  19. #include <cstddef>
  20. #include <iterator>
  21. #include <type_traits>
  22. #if defined(BOOST_CLANG)
  23. #pragma clang diagnostic push
  24. #pragma clang diagnostic ignored "-Wunknown-pragmas"
  25. #pragma clang diagnostic ignored "-Wunused-local-typedefs"
  26. #endif
  27. #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
  28. #pragma GCC diagnostic push
  29. #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
  30. #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
  31. #endif
  32. namespace boost { namespace gil {
  33. /// \defgroup ImageViewNDConcept ImageViewNDLocatorConcept
  34. /// \ingroup ImageViewConcept
  35. /// \brief N-dimensional range
  36. /// \defgroup ImageView2DConcept ImageView2DLocatorConcept
  37. /// \ingroup ImageViewConcept
  38. /// \brief 2-dimensional range
  39. /// \defgroup PixelImageViewConcept ImageViewConcept
  40. /// \ingroup ImageViewConcept
  41. /// \brief 2-dimensional range over pixel data
  42. /// \ingroup ImageViewNDConcept
  43. /// \brief N-dimensional view over immutable values
  44. ///
  45. /// \code
  46. /// concept RandomAccessNDImageViewConcept<Regular View>
  47. /// {
  48. /// typename value_type;
  49. /// typename reference; // result of dereferencing
  50. /// typename difference_type; // result of operator-(iterator,iterator) (1-dimensional!)
  51. /// typename const_t; where RandomAccessNDImageViewConcept<View>; // same as View, but over immutable values
  52. /// typename point_t; where PointNDConcept<point_t>; // N-dimensional point
  53. /// typename locator; where RandomAccessNDLocatorConcept<locator>; // N-dimensional locator.
  54. /// typename iterator; where RandomAccessTraversalConcept<iterator>; // 1-dimensional iterator over all values
  55. /// typename reverse_iterator; where RandomAccessTraversalConcept<reverse_iterator>;
  56. /// typename size_type; // the return value of size()
  57. ///
  58. /// // Equivalent to RandomAccessNDLocatorConcept::axis
  59. /// template <size_t D> struct axis {
  60. /// typename coord_t = point_t::axis<D>::coord_t;
  61. /// typename iterator; where RandomAccessTraversalConcept<iterator>; // iterator along D-th axis.
  62. /// where SameType<coord_t, iterator::difference_type>;
  63. /// where SameType<iterator::value_type,value_type>;
  64. /// };
  65. ///
  66. /// // Defines the type of a view similar to this type, except it invokes Deref upon dereferencing
  67. /// template <PixelDereferenceAdaptorConcept Deref> struct add_deref {
  68. /// typename type; where RandomAccessNDImageViewConcept<type>;
  69. /// static type make(const View& v, const Deref& deref);
  70. /// };
  71. ///
  72. /// static const size_t num_dimensions = point_t::num_dimensions;
  73. ///
  74. /// // Create from a locator at the top-left corner and dimensions
  75. /// View::View(const locator&, const point_type&);
  76. ///
  77. /// size_type View::size() const; // total number of elements
  78. /// reference operator[](View, const difference_type&) const; // 1-dimensional reference
  79. /// iterator View::begin() const;
  80. /// iterator View::end() const;
  81. /// reverse_iterator View::rbegin() const;
  82. /// reverse_iterator View::rend() const;
  83. /// iterator View::at(const point_t&);
  84. /// point_t View::dimensions() const; // number of elements along each dimension
  85. /// bool View::is_1d_traversable() const; // can an iterator over the first dimension visit each value? I.e. are there gaps between values?
  86. ///
  87. /// // iterator along a given dimension starting at a given point
  88. /// template <size_t D> View::axis<D>::iterator View::axis_iterator(const point_t&) const;
  89. ///
  90. /// reference operator()(View,const point_t&) const;
  91. /// };
  92. /// \endcode
  93. template <typename View>
  94. struct RandomAccessNDImageViewConcept
  95. {
  96. void constraints()
  97. {
  98. gil_function_requires<Regular<View>>();
  99. using value_type = typename View::value_type;
  100. using reference = typename View::reference; // result of dereferencing
  101. using pointer = typename View::pointer;
  102. using difference_type = typename View::difference_type; // result of operator-(1d_iterator,1d_iterator)
  103. using const_t = typename View::const_t; // same as this type, but over const values
  104. using point_t = typename View::point_t; // N-dimensional point
  105. using locator = typename View::locator; // N-dimensional locator
  106. using iterator = typename View::iterator;
  107. using const_iterator = typename View::const_iterator;
  108. using reverse_iterator = typename View::reverse_iterator;
  109. using size_type = typename View::size_type;
  110. static const std::size_t N=View::num_dimensions;
  111. gil_function_requires<RandomAccessNDLocatorConcept<locator>>();
  112. gil_function_requires<boost_concepts::RandomAccessTraversalConcept<iterator>>();
  113. gil_function_requires<boost_concepts::RandomAccessTraversalConcept<reverse_iterator>>();
  114. using first_it_type = typename View::template axis<0>::iterator;
  115. using last_it_type = typename View::template axis<N-1>::iterator;
  116. gil_function_requires<boost_concepts::RandomAccessTraversalConcept<first_it_type>>();
  117. gil_function_requires<boost_concepts::RandomAccessTraversalConcept<last_it_type>>();
  118. // static_assert(typename std::iterator_traits<first_it_type>::difference_type, typename point_t::template axis<0>::coord_t>::value, "");
  119. // static_assert(typename std::iterator_traits<last_it_type>::difference_type, typename point_t::template axis<N-1>::coord_t>::value, "");
  120. // point_t must be an N-dimensional point, each dimension of which must have the same type as difference_type of the corresponding iterator
  121. gil_function_requires<PointNDConcept<point_t>>();
  122. static_assert(point_t::num_dimensions == N, "");
  123. static_assert(std::is_same
  124. <
  125. typename std::iterator_traits<first_it_type>::difference_type,
  126. typename point_t::template axis<0>::coord_t
  127. >::value, "");
  128. static_assert(std::is_same
  129. <
  130. typename std::iterator_traits<last_it_type>::difference_type,
  131. typename point_t::template axis<N-1>::coord_t
  132. >::value, "");
  133. point_t p;
  134. locator lc;
  135. iterator it;
  136. reverse_iterator rit;
  137. difference_type d; detail::initialize_it(d); ignore_unused_variable_warning(d);
  138. View(p,lc); // view must be constructible from a locator and a point
  139. p = view.dimensions();
  140. lc = view.pixels();
  141. size_type sz = view.size(); ignore_unused_variable_warning(sz);
  142. bool is_contiguous = view.is_1d_traversable();
  143. ignore_unused_variable_warning(is_contiguous);
  144. it = view.begin();
  145. it = view.end();
  146. rit = view.rbegin();
  147. rit = view.rend();
  148. reference r1 = view[d]; ignore_unused_variable_warning(r1); // 1D access
  149. reference r2 = view(p); ignore_unused_variable_warning(r2); // 2D access
  150. // get 1-D iterator of any dimension at a given pixel location
  151. first_it_type fi = view.template axis_iterator<0>(p);
  152. ignore_unused_variable_warning(fi);
  153. last_it_type li = view.template axis_iterator<N-1>(p);
  154. ignore_unused_variable_warning(li);
  155. using deref_t = PixelDereferenceAdaptorArchetype<typename View::value_type>;
  156. using dtype = typename View::template add_deref<deref_t>::type;
  157. }
  158. View view;
  159. };
  160. /// \ingroup ImageView2DConcept
  161. /// \brief 2-dimensional view over immutable values
  162. ///
  163. /// \code
  164. /// concept RandomAccess2DImageViewConcept<RandomAccessNDImageViewConcept View> {
  165. /// where num_dimensions==2;
  166. ///
  167. /// typename x_iterator = axis<0>::iterator;
  168. /// typename y_iterator = axis<1>::iterator;
  169. /// typename x_coord_t = axis<0>::coord_t;
  170. /// typename y_coord_t = axis<1>::coord_t;
  171. /// typename xy_locator = locator;
  172. ///
  173. /// x_coord_t View::width() const;
  174. /// y_coord_t View::height() const;
  175. ///
  176. /// // X-navigation
  177. /// x_iterator View::x_at(const point_t&) const;
  178. /// x_iterator View::row_begin(y_coord_t) const;
  179. /// x_iterator View::row_end (y_coord_t) const;
  180. ///
  181. /// // Y-navigation
  182. /// y_iterator View::y_at(const point_t&) const;
  183. /// y_iterator View::col_begin(x_coord_t) const;
  184. /// y_iterator View::col_end (x_coord_t) const;
  185. ///
  186. /// // navigating in 2D
  187. /// xy_locator View::xy_at(const point_t&) const;
  188. ///
  189. /// // (x,y) versions of all methods taking point_t
  190. /// View::View(x_coord_t,y_coord_t,const locator&);
  191. /// iterator View::at(x_coord_t,y_coord_t) const;
  192. /// reference operator()(View,x_coord_t,y_coord_t) const;
  193. /// xy_locator View::xy_at(x_coord_t,y_coord_t) const;
  194. /// x_iterator View::x_at(x_coord_t,y_coord_t) const;
  195. /// y_iterator View::y_at(x_coord_t,y_coord_t) const;
  196. /// };
  197. /// \endcode
  198. template <typename View>
  199. struct RandomAccess2DImageViewConcept
  200. {
  201. void constraints()
  202. {
  203. gil_function_requires<RandomAccessNDImageViewConcept<View>>();
  204. static_assert(View::num_dimensions == 2, "");
  205. // TODO: This executes the requirements for RandomAccessNDLocatorConcept again. Fix it to improve compile time
  206. gil_function_requires<RandomAccess2DLocatorConcept<typename View::locator>>();
  207. using dynamic_x_step_t = typename dynamic_x_step_type<View>::type;
  208. using dynamic_y_step_t = typename dynamic_y_step_type<View>::type;
  209. using transposed_t = typename transposed_type<View>::type;
  210. using x_iterator = typename View::x_iterator;
  211. using y_iterator = typename View::y_iterator;
  212. using x_coord_t = typename View::x_coord_t;
  213. using y_coord_t = typename View::y_coord_t;
  214. using xy_locator = typename View::xy_locator;
  215. x_coord_t xd = 0; ignore_unused_variable_warning(xd);
  216. y_coord_t yd = 0; ignore_unused_variable_warning(yd);
  217. x_iterator xit;
  218. y_iterator yit;
  219. typename View::point_t d;
  220. View(xd, yd, xy_locator()); // constructible with width, height, 2d_locator
  221. xy_locator lc = view.xy_at(xd, yd);
  222. lc = view.xy_at(d);
  223. typename View::reference r = view(xd, yd);
  224. ignore_unused_variable_warning(r);
  225. xd = view.width();
  226. yd = view.height();
  227. xit = view.x_at(d);
  228. xit = view.x_at(xd,yd);
  229. xit = view.row_begin(xd);
  230. xit = view.row_end(xd);
  231. yit = view.y_at(d);
  232. yit = view.y_at(xd,yd);
  233. yit = view.col_begin(xd);
  234. yit = view.col_end(xd);
  235. }
  236. View view;
  237. };
  238. /// \brief GIL view as Collection.
  239. ///
  240. /// \see https://www.boost.org/libs/utility/Collection.html
  241. ///
  242. template <typename View>
  243. struct CollectionImageViewConcept
  244. {
  245. void constraints()
  246. {
  247. using value_type = typename View::value_type;
  248. using iterator = typename View::iterator;
  249. using const_iterator = typename View::const_iterator;
  250. using reference = typename View::reference;
  251. using const_reference = typename View::const_reference;
  252. using pointer = typename View::pointer;
  253. using difference_type = typename View::difference_type;
  254. using size_type= typename View::size_type;
  255. iterator i;
  256. i = view1.begin();
  257. i = view2.end();
  258. const_iterator ci;
  259. ci = view1.begin();
  260. ci = view2.end();
  261. size_type s;
  262. s = view1.size();
  263. s = view2.size();
  264. ignore_unused_variable_warning(s);
  265. view1.empty();
  266. view1.swap(view2);
  267. }
  268. View view1;
  269. View view2;
  270. };
  271. /// \brief GIL view as ForwardCollection.
  272. ///
  273. /// \see https://www.boost.org/libs/utility/Collection.html
  274. ///
  275. template <typename View>
  276. struct ForwardCollectionImageViewConcept
  277. {
  278. void constraints()
  279. {
  280. gil_function_requires<CollectionImageViewConcept<View>>();
  281. using reference = typename View::reference;
  282. using const_reference = typename View::const_reference;
  283. reference r = view.front();
  284. ignore_unused_variable_warning(r);
  285. const_reference cr = view.front();
  286. ignore_unused_variable_warning(cr);
  287. }
  288. View view;
  289. };
  290. /// \brief GIL view as ReversibleCollection.
  291. ///
  292. /// \see https://www.boost.org/libs/utility/Collection.html
  293. ///
  294. template <typename View>
  295. struct ReversibleCollectionImageViewConcept
  296. {
  297. void constraints()
  298. {
  299. gil_function_requires<CollectionImageViewConcept<View>>();
  300. using reverse_iterator = typename View::reverse_iterator;
  301. using reference = typename View::reference;
  302. using const_reference = typename View::const_reference;
  303. reverse_iterator i;
  304. i = view.rbegin();
  305. i = view.rend();
  306. reference r = view.back();
  307. ignore_unused_variable_warning(r);
  308. const_reference cr = view.back();
  309. ignore_unused_variable_warning(cr);
  310. }
  311. View view;
  312. };
  313. /// \ingroup PixelImageViewConcept
  314. /// \brief GIL's 2-dimensional view over immutable GIL pixels
  315. /// \code
  316. /// concept ImageViewConcept<RandomAccess2DImageViewConcept View>
  317. /// {
  318. /// where PixelValueConcept<value_type>;
  319. /// where PixelIteratorConcept<x_iterator>;
  320. /// where PixelIteratorConcept<y_iterator>;
  321. /// where x_coord_t == y_coord_t;
  322. ///
  323. /// typename coord_t = x_coord_t;
  324. ///
  325. /// std::size_t View::num_channels() const;
  326. /// };
  327. /// \endcode
  328. template <typename View>
  329. struct ImageViewConcept
  330. {
  331. void constraints()
  332. {
  333. gil_function_requires<RandomAccess2DImageViewConcept<View>>();
  334. // TODO: This executes the requirements for RandomAccess2DLocatorConcept again. Fix it to improve compile time
  335. gil_function_requires<PixelLocatorConcept<typename View::xy_locator>>();
  336. static_assert(std::is_same<typename View::x_coord_t, typename View::y_coord_t>::value, "");
  337. using coord_t = typename View::coord_t; // 1D difference type (same for all dimensions)
  338. std::size_t num_chan = view.num_channels(); ignore_unused_variable_warning(num_chan);
  339. }
  340. View view;
  341. };
  342. namespace detail {
  343. /// \tparam View Models RandomAccessNDImageViewConcept
  344. template <typename View>
  345. struct RandomAccessNDImageViewIsMutableConcept
  346. {
  347. void constraints()
  348. {
  349. gil_function_requires<detail::RandomAccessNDLocatorIsMutableConcept<typename View::locator>>();
  350. gil_function_requires<detail::RandomAccessIteratorIsMutableConcept<typename View::iterator>>();
  351. gil_function_requires<detail::RandomAccessIteratorIsMutableConcept
  352. <
  353. typename View::reverse_iterator
  354. >>();
  355. gil_function_requires<detail::RandomAccessIteratorIsMutableConcept
  356. <
  357. typename View::template axis<0>::iterator
  358. >>();
  359. gil_function_requires<detail::RandomAccessIteratorIsMutableConcept
  360. <
  361. typename View::template axis<View::num_dimensions - 1>::iterator
  362. >>();
  363. typename View::difference_type diff;
  364. initialize_it(diff);
  365. ignore_unused_variable_warning(diff);
  366. typename View::point_t pt;
  367. typename View::value_type v;
  368. initialize_it(v);
  369. view[diff] = v;
  370. view(pt) = v;
  371. }
  372. View view;
  373. };
  374. /// \tparam View Models RandomAccessNDImageViewConcept
  375. template <typename View>
  376. struct RandomAccess2DImageViewIsMutableConcept
  377. {
  378. void constraints()
  379. {
  380. gil_function_requires<detail::RandomAccessNDImageViewIsMutableConcept<View>>();
  381. typename View::x_coord_t xd = 0; ignore_unused_variable_warning(xd);
  382. typename View::y_coord_t yd = 0; ignore_unused_variable_warning(yd);
  383. typename View::value_type v; initialize_it(v);
  384. view(xd, yd) = v;
  385. }
  386. View view;
  387. };
  388. /// \tparam View Models ImageViewConcept
  389. template <typename View>
  390. struct PixelImageViewIsMutableConcept
  391. {
  392. void constraints()
  393. {
  394. gil_function_requires<detail::RandomAccess2DImageViewIsMutableConcept<View>>();
  395. }
  396. };
  397. } // namespace detail
  398. /// \ingroup ImageViewNDConcept
  399. /// \brief N-dimensional view over mutable values
  400. ///
  401. /// \code
  402. /// concept MutableRandomAccessNDImageViewConcept<RandomAccessNDImageViewConcept View>
  403. /// {
  404. /// where Mutable<reference>;
  405. /// };
  406. /// \endcode
  407. template <typename View>
  408. struct MutableRandomAccessNDImageViewConcept
  409. {
  410. void constraints()
  411. {
  412. gil_function_requires<RandomAccessNDImageViewConcept<View>>();
  413. gil_function_requires<detail::RandomAccessNDImageViewIsMutableConcept<View>>();
  414. }
  415. };
  416. /// \ingroup ImageView2DConcept
  417. /// \brief 2-dimensional view over mutable values
  418. ///
  419. /// \code
  420. /// concept MutableRandomAccess2DImageViewConcept<RandomAccess2DImageViewConcept View>
  421. /// : MutableRandomAccessNDImageViewConcept<View> {};
  422. /// \endcode
  423. template <typename View>
  424. struct MutableRandomAccess2DImageViewConcept
  425. {
  426. void constraints()
  427. {
  428. gil_function_requires<RandomAccess2DImageViewConcept<View>>();
  429. gil_function_requires<detail::RandomAccess2DImageViewIsMutableConcept<View>>();
  430. }
  431. };
  432. /// \ingroup PixelImageViewConcept
  433. /// \brief GIL's 2-dimensional view over mutable GIL pixels
  434. ///
  435. /// \code
  436. /// concept MutableImageViewConcept<ImageViewConcept View>
  437. /// : MutableRandomAccess2DImageViewConcept<View> {};
  438. /// \endcode
  439. template <typename View>
  440. struct MutableImageViewConcept
  441. {
  442. void constraints()
  443. {
  444. gil_function_requires<ImageViewConcept<View>>();
  445. gil_function_requires<detail::PixelImageViewIsMutableConcept<View>>();
  446. }
  447. };
  448. /// \brief Returns whether two views are compatible
  449. ///
  450. /// Views are compatible if their pixels are compatible.
  451. /// Compatible views can be assigned and copy constructed from one another.
  452. ///
  453. /// \tparam V1 Models ImageViewConcept
  454. /// \tparam V2 Models ImageViewConcept
  455. ///
  456. template <typename V1, typename V2>
  457. struct views_are_compatible
  458. : pixels_are_compatible<typename V1::value_type, typename V2::value_type>
  459. {
  460. };
  461. /// \ingroup ImageViewConcept
  462. /// \brief Views are compatible if they have the same color spaces and compatible channel values.
  463. ///
  464. /// Constness and layout are not important for compatibility.
  465. ///
  466. /// \code
  467. /// concept ViewsCompatibleConcept<ImageViewConcept V1, ImageViewConcept V2>
  468. /// {
  469. /// where PixelsCompatibleConcept<V1::value_type, P2::value_type>;
  470. /// };
  471. /// \endcode
  472. template <typename V1, typename V2>
  473. struct ViewsCompatibleConcept
  474. {
  475. void constraints()
  476. {
  477. static_assert(views_are_compatible<V1, V2>::value, "");
  478. }
  479. };
  480. }} // namespace boost::gil
  481. #if defined(BOOST_CLANG)
  482. #pragma clang diagnostic pop
  483. #endif
  484. #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
  485. #pragma GCC diagnostic pop
  486. #endif
  487. #endif