any_image_view.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. //
  2. // Copyright 2005-2007 Adobe Systems Incorporated
  3. // Copyright 2020 Samuel Debionne
  4. //
  5. // Distributed under the Boost Software License, Version 1.0
  6. // See accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt
  8. //
  9. #ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_ANY_IMAGE_VIEW_HPP
  10. #define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_ANY_IMAGE_VIEW_HPP
  11. #include <boost/gil/dynamic_step.hpp>
  12. #include <boost/gil/image.hpp>
  13. #include <boost/gil/image_view.hpp>
  14. #include <boost/gil/point.hpp>
  15. #include <boost/gil/detail/mp11.hpp>
  16. #include <boost/variant2/variant.hpp>
  17. namespace boost { namespace gil {
  18. template <typename View>
  19. struct dynamic_xy_step_transposed_type;
  20. namespace detail {
  21. template <typename View>
  22. using get_const_t = typename View::const_t;
  23. template <typename Views>
  24. using views_get_const_t = mp11::mp_transform<get_const_t, Views>;
  25. // works for both image_view and image
  26. struct any_type_get_num_channels
  27. {
  28. using result_type = int;
  29. template <typename T>
  30. result_type operator()(const T&) const { return num_channels<T>::value; }
  31. };
  32. // works for both image_view and image
  33. struct any_type_get_dimensions
  34. {
  35. using result_type = point<std::ptrdiff_t>;
  36. template <typename T>
  37. result_type operator()(const T& v) const { return v.dimensions(); }
  38. };
  39. // works for image_view
  40. struct any_type_get_size
  41. {
  42. using result_type = std::size_t;
  43. template <typename T>
  44. result_type operator()(const T& v) const { return v.size(); }
  45. };
  46. } // namespace detail
  47. ////////////////////////////////////////////////////////////////////////////////////////
  48. /// CLASS any_image_view
  49. ///
  50. /// \ingroup ImageViewModel
  51. /// \brief Represents a run-time specified image view. Models HasDynamicXStepTypeConcept, HasDynamicYStepTypeConcept, Note that this class does NOT model ImageViewConcept
  52. ///
  53. /// Represents a view whose type (color space, layout, planar/interleaved organization, etc) can be specified at run time.
  54. /// It is the runtime equivalent of \p image_view.
  55. /// Some of the requirements of ImageViewConcept, such as the \p value_type alias cannot be fulfilled, since the language does not allow runtime type specification.
  56. /// Other requirements, such as access to the pixels, would be inefficient to provide. Thus \p any_image_view does not fully model ImageViewConcept.
  57. /// However, many algorithms provide overloads taking runtime specified views and thus in many cases \p any_image_view can be used in places taking a view.
  58. ///
  59. /// To perform an algorithm on any_image_view, put the algorithm in a function object and invoke it by calling \p variant2::visit(algorithm_fn, runtime_view);
  60. ////////////////////////////////////////////////////////////////////////////////////////
  61. template <typename ...Views>
  62. class any_image_view : public variant2::variant<Views...>
  63. {
  64. using parent_t = variant2::variant<Views...>;
  65. public:
  66. using const_t = detail::views_get_const_t<any_image_view>;
  67. using x_coord_t = std::ptrdiff_t;
  68. using y_coord_t = std::ptrdiff_t;
  69. using point_t = point<std::ptrdiff_t>;
  70. using size_type = std::size_t;
  71. using parent_t::parent_t;
  72. any_image_view& operator=(any_image_view const& view)
  73. {
  74. parent_t::operator=((parent_t const&)view);
  75. return *this;
  76. }
  77. template <typename View>
  78. any_image_view& operator=(View const& view)
  79. {
  80. parent_t::operator=(view);
  81. return *this;
  82. }
  83. template <typename ...OtherViews>
  84. any_image_view& operator=(any_image_view<OtherViews...> const& view)
  85. {
  86. parent_t::operator=((variant2::variant<OtherViews...> const&)view);
  87. return *this;
  88. }
  89. std::size_t num_channels() const { return variant2::visit(detail::any_type_get_num_channels(), *this); }
  90. point_t dimensions() const { return variant2::visit(detail::any_type_get_dimensions(), *this); }
  91. size_type size() const { return variant2::visit(detail::any_type_get_size(), *this); }
  92. x_coord_t width() const { return dimensions().x; }
  93. y_coord_t height() const { return dimensions().y; }
  94. };
  95. /////////////////////////////
  96. // HasDynamicXStepTypeConcept
  97. /////////////////////////////
  98. template <typename ...Views>
  99. struct dynamic_x_step_type<any_image_view<Views...>>
  100. {
  101. private:
  102. // FIXME: Remove class name injection with gil:: qualification
  103. // Required as workaround for Boost.MP11 issue that treats unqualified metafunction
  104. // in the class definition of the same name as the specialization (Peter Dimov):
  105. // invalid template argument for template parameter 'F', expected a class template
  106. template <typename T>
  107. using dynamic_step_view = typename gil::dynamic_x_step_type<T>::type;
  108. public:
  109. using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
  110. };
  111. /////////////////////////////
  112. // HasDynamicYStepTypeConcept
  113. /////////////////////////////
  114. template <typename ...Views>
  115. struct dynamic_y_step_type<any_image_view<Views...>>
  116. {
  117. private:
  118. // FIXME: Remove class name injection with gil:: qualification
  119. // Required as workaround for Boost.MP11 issue that treats unqualified metafunction
  120. // in the class definition of the same name as the specialization (Peter Dimov):
  121. // invalid template argument for template parameter 'F', expected a class template
  122. template <typename T>
  123. using dynamic_step_view = typename gil::dynamic_y_step_type<T>::type;
  124. public:
  125. using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
  126. };
  127. template <typename ...Views>
  128. struct dynamic_xy_step_type<any_image_view<Views...>>
  129. {
  130. private:
  131. // FIXME: Remove class name injection with gil:: qualification
  132. // Required as workaround for Boost.MP11 issue that treats unqualified metafunction
  133. // in the class definition of the same name as the specialization (Peter Dimov):
  134. // invalid template argument for template parameter 'F', expected a class template
  135. template <typename T>
  136. using dynamic_step_view = typename gil::dynamic_xy_step_type<T>::type;
  137. public:
  138. using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
  139. };
  140. template <typename ...Views>
  141. struct dynamic_xy_step_transposed_type<any_image_view<Views...>>
  142. {
  143. private:
  144. // FIXME: Remove class name injection with gil:: qualification
  145. // Required as workaround for Boost.MP11 issue that treats unqualified metafunction
  146. // in the class definition of the same name as the specialization (Peter Dimov):
  147. // invalid template argument for template parameter 'F', expected a class template
  148. template <typename T>
  149. using dynamic_step_view = typename gil::dynamic_xy_step_type<T>::type;
  150. public:
  151. using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
  152. };
  153. }} // namespace boost::gil
  154. #endif