utilities.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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_UTILITIES_HPP
  9. #define BOOST_GIL_UTILITIES_HPP
  10. #include <boost/gil/detail/mp11.hpp>
  11. #include <boost/config.hpp>
  12. #if defined(BOOST_CLANG)
  13. #pragma clang diagnostic push
  14. #pragma clang diagnostic ignored "-Wconversion"
  15. #endif
  16. #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
  17. #pragma GCC diagnostic push
  18. #pragma GCC diagnostic ignored "-Wconversion"
  19. #endif
  20. #include <boost/iterator/iterator_adaptor.hpp>
  21. #include <boost/iterator/iterator_facade.hpp>
  22. #if defined(BOOST_CLANG)
  23. #pragma clang diagnostic pop
  24. #endif
  25. #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
  26. #pragma GCC diagnostic pop
  27. #endif
  28. #include <algorithm>
  29. #include <cmath>
  30. #include <cstddef>
  31. #include <functional>
  32. #include <iterator>
  33. #include <utility>
  34. #include <type_traits>
  35. namespace boost { namespace gil {
  36. /// Various utilities not specific to the image library.
  37. /// Some are non-standard STL extensions or generic iterator adaptors
  38. ////////////////////////////////////////////////////////////////////////////////
  39. /// Rounding of real numbers / points to integers / integer points
  40. ////////////////////////////////////////////////////////////////////////////////
  41. inline std::ptrdiff_t iround(float x)
  42. {
  43. return static_cast<std::ptrdiff_t>(x + (x < 0.0f ? -0.5f : 0.5f));
  44. }
  45. inline std::ptrdiff_t iround(double x)
  46. {
  47. return static_cast<std::ptrdiff_t>(x + (x < 0.0 ? -0.5 : 0.5));
  48. }
  49. inline std::ptrdiff_t ifloor(float x)
  50. {
  51. return static_cast<std::ptrdiff_t>(std::floor(x));
  52. }
  53. inline std::ptrdiff_t ifloor(double x)
  54. {
  55. return static_cast<std::ptrdiff_t>(std::floor(x));
  56. }
  57. inline std::ptrdiff_t iceil(float x)
  58. {
  59. return static_cast<std::ptrdiff_t>(std::ceil(x));
  60. }
  61. inline std::ptrdiff_t iceil(double x)
  62. {
  63. return static_cast<std::ptrdiff_t>(std::ceil(x));
  64. }
  65. ////////////////////////////////////////////////////////////////////////////////
  66. /// computing size with alignment
  67. ////////////////////////////////////////////////////////////////////////////////
  68. template <typename T>
  69. inline T align(T val, std::size_t alignment)
  70. {
  71. return val+(alignment - val%alignment)%alignment;
  72. }
  73. /// \brief Helper base class for pixel dereference adaptors.
  74. /// \ingroup PixelDereferenceAdaptorModel
  75. ///
  76. template
  77. <
  78. typename ConstT,
  79. typename Value,
  80. typename Reference,
  81. typename ConstReference,
  82. typename ArgType,
  83. typename ResultType,
  84. bool IsMutable
  85. >
  86. struct deref_base
  87. {
  88. using argument_type = ArgType;
  89. using result_type = ResultType;
  90. using const_t = ConstT;
  91. using value_type = Value;
  92. using reference = Reference;
  93. using const_reference = ConstReference;
  94. static constexpr bool is_mutable = IsMutable;
  95. };
  96. /// \brief Composes two dereference function objects. Similar to std::unary_compose but needs to pull some aliases from the component types. Models: PixelDereferenceAdaptorConcept
  97. /// \ingroup PixelDereferenceAdaptorModel
  98. ///
  99. template <typename D1, typename D2>
  100. class deref_compose : public deref_base
  101. <
  102. deref_compose<typename D1::const_t, typename D2::const_t>,
  103. typename D1::value_type,
  104. typename D1::reference,
  105. typename D1::const_reference,
  106. typename D2::argument_type,
  107. typename D1::result_type,
  108. D1::is_mutable && D2::is_mutable
  109. >
  110. {
  111. public:
  112. D1 _fn1;
  113. D2 _fn2;
  114. using argument_type = typename D2::argument_type;
  115. using result_type = typename D1::result_type;
  116. deref_compose() = default;
  117. deref_compose(const D1& x, const D2& y) : _fn1(x), _fn2(y) {}
  118. deref_compose(const deref_compose& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {}
  119. template <typename _D1, typename _D2>
  120. deref_compose(const deref_compose<_D1,_D2>& dc)
  121. : _fn1(dc._fn1), _fn2(dc._fn2)
  122. {}
  123. result_type operator()(argument_type x) const { return _fn1(_fn2(x)); }
  124. result_type operator()(argument_type x) { return _fn1(_fn2(x)); }
  125. };
  126. // reinterpret_cast is implementation-defined. Static cast is not.
  127. template <typename OutPtr, typename In>
  128. BOOST_FORCEINLINE
  129. auto gil_reinterpret_cast(In* p) -> OutPtr
  130. {
  131. return static_cast<OutPtr>(static_cast<void*>(p));
  132. }
  133. template <typename OutPtr, typename In>
  134. BOOST_FORCEINLINE
  135. auto gil_reinterpret_cast_c(In const* p) -> OutPtr const
  136. {
  137. return static_cast<OutPtr const>(static_cast<void const*>(p));
  138. }
  139. namespace detail {
  140. ////////////////////////////////////////////////////////////////////////////////
  141. /// \brief copy_n taken from SGI STL.
  142. ////////////////////////////////////////////////////////////////////////////////
  143. template <class InputIter, class Size, class OutputIter>
  144. auto _copy_n(InputIter first, Size count, OutputIter result, std::input_iterator_tag)
  145. -> std::pair<InputIter, OutputIter>
  146. {
  147. for ( ; count > 0; --count)
  148. {
  149. *result = *first;
  150. ++first;
  151. ++result;
  152. }
  153. return std::pair<InputIter, OutputIter>(first, result);
  154. }
  155. template <class RAIter, class Size, class OutputIter>
  156. inline auto _copy_n(RAIter first, Size count, OutputIter result, std::random_access_iterator_tag)
  157. -> std::pair<RAIter, OutputIter>
  158. {
  159. RAIter last = first + count;
  160. return std::pair<RAIter, OutputIter>(last, std::copy(first, last, result));
  161. }
  162. template <class InputIter, class Size, class OutputIter>
  163. inline auto _copy_n(InputIter first, Size count, OutputIter result)
  164. -> std::pair<InputIter, OutputIter>
  165. {
  166. return _copy_n(first, count, result, typename std::iterator_traits<InputIter>::iterator_category());
  167. }
  168. template <class InputIter, class Size, class OutputIter>
  169. inline auto copy_n(InputIter first, Size count, OutputIter result)
  170. -> std::pair<InputIter, OutputIter>
  171. {
  172. return detail::_copy_n(first, count, result);
  173. }
  174. /// \brief identity taken from SGI STL.
  175. template <typename T>
  176. struct identity
  177. {
  178. using argument_type = T;
  179. using result_type = T;
  180. const T& operator()(const T& val) const { return val; }
  181. };
  182. /// \brief plus function object whose arguments may be of different type.
  183. template <typename T1, typename T2>
  184. struct plus_asymmetric {
  185. using first_argument_type = T1;
  186. using second_argument_type = T2;
  187. using result_type = T1;
  188. T1 operator()(T1 f1, T2 f2) const
  189. {
  190. return f1+f2;
  191. }
  192. };
  193. /// \brief operator++ wrapped in a function object
  194. template <typename T>
  195. struct inc
  196. {
  197. using argument_type = T;
  198. using result_type = T;
  199. T operator()(T x) const { return ++x; }
  200. };
  201. /// \brief operator-- wrapped in a function object
  202. template <typename T>
  203. struct dec
  204. {
  205. using argument_type = T;
  206. using result_type = T;
  207. T operator()(T x) const { return --x; }
  208. };
  209. /// \brief Returns the index corresponding to the first occurrance of a given given type in
  210. // a given Boost.MP11-compatible list (or size if the type is not present)
  211. template <typename Types, typename T>
  212. struct type_to_index : mp11::mp_find<Types, T>
  213. {
  214. static_assert(mp11::mp_contains<Types, T>::value, "T should be element of Types");
  215. };
  216. } // namespace detail
  217. /// \ingroup ColorSpaceAndLayoutModel
  218. /// \brief Represents a color space and ordering of channels in memory
  219. template
  220. <
  221. typename ColorSpace,
  222. typename ChannelMapping = mp11::mp_iota
  223. <
  224. std::integral_constant<int, mp11::mp_size<ColorSpace>::value>
  225. >
  226. >
  227. struct layout
  228. {
  229. using color_space_t = ColorSpace;
  230. using channel_mapping_t = ChannelMapping;
  231. static_assert(mp11::mp_size<ColorSpace>::value > 0,
  232. "color space should not be empty sequence");
  233. };
  234. /// \brief A version of swap that also works with reference proxy objects
  235. /// Where value_type<T1> == value_type<T2> == Value
  236. template <typename Value, typename T1, typename T2>
  237. void swap_proxy(T1& left, T2& right)
  238. {
  239. Value tmp = left;
  240. left = right;
  241. right = tmp;
  242. }
  243. /// \brief Run-time detection of whether the underlying architecture is little endian
  244. BOOST_FORCEINLINE bool little_endian()
  245. {
  246. short tester = 0x0001;
  247. return *(char*)&tester!=0;
  248. }
  249. /// \brief Run-time detection of whether the underlying architecture is big endian
  250. BOOST_FORCEINLINE bool big_endian()
  251. {
  252. return !little_endian();
  253. }
  254. }} // namespace boost::gil
  255. #endif