utilities.hpp 7.7 KB

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