2 // Copyright 2005-2007 Adobe Systems Incorporated
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
8 #ifndef BOOST_GIL_UTILITIES_HPP
9 #define BOOST_GIL_UTILITIES_HPP
11 #include <boost/gil/detail/mp11.hpp>
13 #include <boost/config.hpp>
15 #if defined(BOOST_CLANG)
16 #pragma clang diagnostic push
17 #pragma clang diagnostic ignored "-Wconversion"
20 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
21 #pragma GCC diagnostic push
22 #pragma GCC diagnostic ignored "-Wconversion"
25 #include <boost/iterator/iterator_adaptor.hpp>
26 #include <boost/iterator/iterator_facade.hpp>
28 #if defined(BOOST_CLANG)
29 #pragma clang diagnostic pop
32 #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
33 #pragma GCC diagnostic pop
42 #include <type_traits>
44 namespace boost { namespace gil {
46 /// Various utilities not specific to the image library.
47 /// Some are non-standard STL extensions or generic iterator adaptors
49 ////////////////////////////////////////////////////////////////////////////////
50 /// Rounding of real numbers / points to integers / integer points
51 ////////////////////////////////////////////////////////////////////////////////
53 inline std::ptrdiff_t iround(float x)
55 return static_cast<std::ptrdiff_t>(x + (x < 0.0f ? -0.5f : 0.5f));
58 inline std::ptrdiff_t iround(double x)
60 return static_cast<std::ptrdiff_t>(x + (x < 0.0 ? -0.5 : 0.5));
63 inline std::ptrdiff_t ifloor(float x)
65 return static_cast<std::ptrdiff_t>(std::floor(x));
68 inline std::ptrdiff_t ifloor(double x)
70 return static_cast<std::ptrdiff_t>(std::floor(x));
73 inline std::ptrdiff_t iceil(float x)
75 return static_cast<std::ptrdiff_t>(std::ceil(x));
78 inline std::ptrdiff_t iceil(double x)
80 return static_cast<std::ptrdiff_t>(std::ceil(x));
83 ////////////////////////////////////////////////////////////////////////////////
84 /// computing size with alignment
85 ////////////////////////////////////////////////////////////////////////////////
88 inline T align(T val, std::size_t alignment)
90 return val+(alignment - val%alignment)%alignment;
93 /// \brief Helper base class for pixel dereference adaptors.
94 /// \ingroup PixelDereferenceAdaptorModel
101 typename ConstReference,
108 using argument_type = ArgType;
109 using result_type = ResultType;
110 using const_t = ConstT;
111 using value_type = Value;
112 using reference = Reference;
113 using const_reference = ConstReference;
114 static constexpr bool is_mutable = IsMutable;
117 /// \brief Composes two dereference function objects. Similar to std::unary_compose but needs to pull some aliases from the component types. Models: PixelDereferenceAdaptorConcept
118 /// \ingroup PixelDereferenceAdaptorModel
120 template <typename D1, typename D2>
121 class deref_compose : public deref_base
123 deref_compose<typename D1::const_t, typename D2::const_t>,
124 typename D1::value_type,
125 typename D1::reference,
126 typename D1::const_reference,
127 typename D2::argument_type,
128 typename D1::result_type,
129 D1::is_mutable && D2::is_mutable
136 using argument_type = typename D2::argument_type;
137 using result_type = typename D1::result_type;
139 deref_compose() = default;
140 deref_compose(const D1& x, const D2& y) : _fn1(x), _fn2(y) {}
141 deref_compose(const deref_compose& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {}
143 template <typename _D1, typename _D2>
144 deref_compose(const deref_compose<_D1,_D2>& dc)
145 : _fn1(dc._fn1), _fn2(dc._fn2)
148 result_type operator()(argument_type x) const { return _fn1(_fn2(x)); }
149 result_type operator()(argument_type x) { return _fn1(_fn2(x)); }
152 // reinterpret_cast is implementation-defined. Static cast is not.
153 template <typename OutPtr, typename In>
155 OutPtr gil_reinterpret_cast(In* p)
157 return static_cast<OutPtr>(static_cast<void*>(p));
160 template <typename OutPtr, typename In> BOOST_FORCEINLINE
161 const OutPtr gil_reinterpret_cast_c(const In* p)
163 return static_cast<const OutPtr>(static_cast<const void*>(p));
168 ////////////////////////////////////////////////////////////////////////////////
169 /// \brief copy_n taken from SGI STL.
170 ////////////////////////////////////////////////////////////////////////////////
172 template <class InputIter, class Size, class OutputIter>
173 std::pair<InputIter, OutputIter> _copy_n(InputIter first, Size count,
174 OutputIter result, std::input_iterator_tag)
176 for ( ; count > 0; --count)
182 return std::pair<InputIter, OutputIter>(first, result);
185 template <class RAIter, class Size, class OutputIter>
186 inline std::pair<RAIter, OutputIter>
187 _copy_n(RAIter first, Size count, OutputIter result, std::random_access_iterator_tag)
189 RAIter last = first + count;
190 return std::pair<RAIter, OutputIter>(last, std::copy(first, last, result));
193 template <class InputIter, class Size, class OutputIter>
194 inline std::pair<InputIter, OutputIter>
195 _copy_n(InputIter first, Size count, OutputIter result)
197 return _copy_n(first, count, result, typename std::iterator_traits<InputIter>::iterator_category());
200 template <class InputIter, class Size, class OutputIter>
201 inline std::pair<InputIter, OutputIter>
202 copy_n(InputIter first, Size count, OutputIter result)
204 return detail::_copy_n(first, count, result);
207 /// \brief identity taken from SGI STL.
208 template <typename T>
211 using argument_type = T;
212 using result_type = T;
213 const T& operator()(const T& val) const { return val; }
216 /// \brief plus function object whose arguments may be of different type.
217 template <typename T1, typename T2>
218 struct plus_asymmetric {
219 using first_argument_type = T1;
220 using second_argument_type = T2;
221 using result_type = T1;
222 T1 operator()(T1 f1, T2 f2) const
228 /// \brief operator++ wrapped in a function object
229 template <typename T>
232 using argument_type = T;
233 using result_type = T;
234 T operator()(T x) const { return ++x; }
237 /// \brief operator-- wrapped in a function object
238 template <typename T>
241 using argument_type = T;
242 using result_type = T;
243 T operator()(T x) const { return --x; }
246 /// \brief Returns the index corresponding to the first occurrance of a given given type in
247 // a given Boost.MP11-compatible list (or size if the type is not present)
248 template <typename Types, typename T>
249 struct type_to_index : mp11::mp_find<Types, T>
251 static_assert(mp11::mp_contains<Types, T>::value, "T should be element of Types");
254 } // namespace detail
256 /// \ingroup ColorSpaceAndLayoutModel
257 /// \brief Represents a color space and ordering of channels in memory
261 typename ChannelMapping = mp11::mp_iota
263 std::integral_constant<int, mp11::mp_size<ColorSpace>::value>
268 using color_space_t = ColorSpace;
269 using channel_mapping_t = ChannelMapping;
271 static_assert(mp11::mp_size<ColorSpace>::value > 0,
272 "color space should not be empty sequence");
275 /// \brief A version of swap that also works with reference proxy objects
276 /// Where value_type<T1> == value_type<T2> == Value
277 template <typename Value, typename T1, typename T2>
278 void swap_proxy(T1& left, T2& right)
285 /// \brief Run-time detection of whether the underlying architecture is little endian
286 BOOST_FORCEINLINE bool little_endian()
288 short tester = 0x0001;
289 return *(char*)&tester!=0;
291 /// \brief Run-time detection of whether the underlying architecture is big endian
292 BOOST_FORCEINLINE bool big_endian()
294 return !little_endian();
297 }} // namespace boost::gil