utilities.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. OutPtr gil_reinterpret_cast(In* p)
  130. {
  131. return static_cast<OutPtr>(static_cast<void*>(p));
  132. }
  133. template <typename OutPtr, typename In> BOOST_FORCEINLINE
  134. const OutPtr gil_reinterpret_cast_c(const In* p)
  135. {
  136. return static_cast<const OutPtr>(static_cast<const void*>(p));
  137. }
  138. namespace detail {
  139. ////////////////////////////////////////////////////////////////////////////////
  140. /// \brief copy_n taken from SGI STL.
  141. ////////////////////////////////////////////////////////////////////////////////
  142. template <class InputIter, class Size, class OutputIter>
  143. std::pair<InputIter, OutputIter> _copy_n(InputIter first, Size count,
  144. OutputIter result, std::input_iterator_tag)
  145. {
  146. for ( ; count > 0; --count)
  147. {
  148. *result = *first;
  149. ++first;
  150. ++result;
  151. }
  152. return std::pair<InputIter, OutputIter>(first, result);
  153. }
  154. template <class RAIter, class Size, class OutputIter>
  155. inline std::pair<RAIter, OutputIter>
  156. _copy_n(RAIter first, Size count, OutputIter result, std::random_access_iterator_tag)
  157. {
  158. RAIter last = first + count;
  159. return std::pair<RAIter, OutputIter>(last, std::copy(first, last, result));
  160. }
  161. template <class InputIter, class Size, class OutputIter>
  162. inline std::pair<InputIter, OutputIter>
  163. _copy_n(InputIter first, Size count, OutputIter result)
  164. {
  165. return _copy_n(first, count, result, typename std::iterator_traits<InputIter>::iterator_category());
  166. }
  167. template <class InputIter, class Size, class OutputIter>
  168. inline std::pair<InputIter, OutputIter>
  169. copy_n(InputIter first, Size count, OutputIter result)
  170. {
  171. return detail::_copy_n(first, count, result);
  172. }
  173. /// \brief identity taken from SGI STL.
  174. template <typename T>
  175. struct identity
  176. {
  177. using argument_type = T;
  178. using result_type = T;
  179. const T& operator()(const T& val) const { return val; }
  180. };
  181. /// \brief plus function object whose arguments may be of different type.
  182. template <typename T1, typename T2>
  183. struct plus_asymmetric {
  184. using first_argument_type = T1;
  185. using second_argument_type = T2;
  186. using result_type = T1;
  187. T1 operator()(T1 f1, T2 f2) const
  188. {
  189. return f1+f2;
  190. }
  191. };
  192. /// \brief operator++ wrapped in a function object
  193. template <typename T>
  194. struct inc
  195. {
  196. using argument_type = T;
  197. using result_type = T;
  198. T operator()(T x) const { return ++x; }
  199. };
  200. /// \brief operator-- wrapped in a function object
  201. template <typename T>
  202. struct dec
  203. {
  204. using argument_type = T;
  205. using result_type = T;
  206. T operator()(T x) const { return --x; }
  207. };
  208. /// \brief Returns the index corresponding to the first occurrance of a given given type in
  209. // a given Boost.MP11-compatible list (or size if the type is not present)
  210. template <typename Types, typename T>
  211. struct type_to_index : mp11::mp_find<Types, T>
  212. {
  213. static_assert(mp11::mp_contains<Types, T>::value, "T should be element of Types");
  214. };
  215. } // namespace detail
  216. /// \ingroup ColorSpaceAndLayoutModel
  217. /// \brief Represents a color space and ordering of channels in memory
  218. template
  219. <
  220. typename ColorSpace,
  221. typename ChannelMapping = mp11::mp_iota
  222. <
  223. std::integral_constant<int, mp11::mp_size<ColorSpace>::value>
  224. >
  225. >
  226. struct layout
  227. {
  228. using color_space_t = ColorSpace;
  229. using channel_mapping_t = ChannelMapping;
  230. static_assert(mp11::mp_size<ColorSpace>::value > 0,
  231. "color space should not be empty sequence");
  232. };
  233. /// \brief A version of swap that also works with reference proxy objects
  234. /// Where value_type<T1> == value_type<T2> == Value
  235. template <typename Value, typename T1, typename T2>
  236. void swap_proxy(T1& left, T2& right)
  237. {
  238. Value tmp = left;
  239. left = right;
  240. right = tmp;
  241. }
  242. /// \brief Run-time detection of whether the underlying architecture is little endian
  243. BOOST_FORCEINLINE bool little_endian()
  244. {
  245. short tester = 0x0001;
  246. return *(char*)&tester!=0;
  247. }
  248. /// \brief Run-time detection of whether the underlying architecture is big endian
  249. BOOST_FORCEINLINE bool big_endian()
  250. {
  251. return !little_endian();
  252. }
  253. }} // namespace boost::gil
  254. #endif