123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- //
- // Copyright 2005-2007 Adobe Systems Incorporated
- //
- // Distributed under the Boost Software License, Version 1.0
- // See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt
- //
- #ifndef BOOST_GIL_UTILITIES_HPP
- #define BOOST_GIL_UTILITIES_HPP
- #include <boost/gil/detail/mp11.hpp>
- #include <boost/config.hpp>
- #if defined(BOOST_CLANG)
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wconversion"
- #endif
- #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wconversion"
- #endif
- #include <boost/iterator/iterator_adaptor.hpp>
- #include <boost/iterator/iterator_facade.hpp>
- #if defined(BOOST_CLANG)
- #pragma clang diagnostic pop
- #endif
- #if defined(BOOST_GCC) && (BOOST_GCC >= 40900)
- #pragma GCC diagnostic pop
- #endif
- #include <algorithm>
- #include <cmath>
- #include <cstddef>
- #include <functional>
- #include <iterator>
- #include <utility>
- #include <type_traits>
- namespace boost { namespace gil {
- /// Various utilities not specific to the image library.
- /// Some are non-standard STL extensions or generic iterator adaptors
- ////////////////////////////////////////////////////////////////////////////////
- /// Rounding of real numbers / points to integers / integer points
- ////////////////////////////////////////////////////////////////////////////////
- inline std::ptrdiff_t iround(float x)
- {
- return static_cast<std::ptrdiff_t>(x + (x < 0.0f ? -0.5f : 0.5f));
- }
- inline std::ptrdiff_t iround(double x)
- {
- return static_cast<std::ptrdiff_t>(x + (x < 0.0 ? -0.5 : 0.5));
- }
- inline std::ptrdiff_t ifloor(float x)
- {
- return static_cast<std::ptrdiff_t>(std::floor(x));
- }
- inline std::ptrdiff_t ifloor(double x)
- {
- return static_cast<std::ptrdiff_t>(std::floor(x));
- }
- inline std::ptrdiff_t iceil(float x)
- {
- return static_cast<std::ptrdiff_t>(std::ceil(x));
- }
- inline std::ptrdiff_t iceil(double x)
- {
- return static_cast<std::ptrdiff_t>(std::ceil(x));
- }
- ////////////////////////////////////////////////////////////////////////////////
- /// computing size with alignment
- ////////////////////////////////////////////////////////////////////////////////
- template <typename T>
- inline T align(T val, std::size_t alignment)
- {
- return val+(alignment - val%alignment)%alignment;
- }
- /// \brief Helper base class for pixel dereference adaptors.
- /// \ingroup PixelDereferenceAdaptorModel
- ///
- template
- <
- typename ConstT,
- typename Value,
- typename Reference,
- typename ConstReference,
- typename ArgType,
- typename ResultType,
- bool IsMutable
- >
- struct deref_base
- {
- using argument_type = ArgType;
- using result_type = ResultType;
- using const_t = ConstT;
- using value_type = Value;
- using reference = Reference;
- using const_reference = ConstReference;
- static constexpr bool is_mutable = IsMutable;
- };
- /// \brief Composes two dereference function objects. Similar to std::unary_compose but needs to pull some aliases from the component types. Models: PixelDereferenceAdaptorConcept
- /// \ingroup PixelDereferenceAdaptorModel
- ///
- template <typename D1, typename D2>
- class deref_compose : public deref_base
- <
- deref_compose<typename D1::const_t, typename D2::const_t>,
- typename D1::value_type,
- typename D1::reference,
- typename D1::const_reference,
- typename D2::argument_type,
- typename D1::result_type,
- D1::is_mutable && D2::is_mutable
- >
- {
- public:
- D1 _fn1;
- D2 _fn2;
- using argument_type = typename D2::argument_type;
- using result_type = typename D1::result_type;
- deref_compose() = default;
- deref_compose(const D1& x, const D2& y) : _fn1(x), _fn2(y) {}
- deref_compose(const deref_compose& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {}
- template <typename _D1, typename _D2>
- deref_compose(const deref_compose<_D1,_D2>& dc)
- : _fn1(dc._fn1), _fn2(dc._fn2)
- {}
- result_type operator()(argument_type x) const { return _fn1(_fn2(x)); }
- result_type operator()(argument_type x) { return _fn1(_fn2(x)); }
- };
- // reinterpret_cast is implementation-defined. Static cast is not.
- template <typename OutPtr, typename In>
- BOOST_FORCEINLINE
- OutPtr gil_reinterpret_cast(In* p)
- {
- return static_cast<OutPtr>(static_cast<void*>(p));
- }
- template <typename OutPtr, typename In> BOOST_FORCEINLINE
- const OutPtr gil_reinterpret_cast_c(const In* p)
- {
- return static_cast<const OutPtr>(static_cast<const void*>(p));
- }
- namespace detail {
- ////////////////////////////////////////////////////////////////////////////////
- /// \brief copy_n taken from SGI STL.
- ////////////////////////////////////////////////////////////////////////////////
- template <class InputIter, class Size, class OutputIter>
- std::pair<InputIter, OutputIter> _copy_n(InputIter first, Size count,
- OutputIter result, std::input_iterator_tag)
- {
- for ( ; count > 0; --count)
- {
- *result = *first;
- ++first;
- ++result;
- }
- return std::pair<InputIter, OutputIter>(first, result);
- }
- template <class RAIter, class Size, class OutputIter>
- inline std::pair<RAIter, OutputIter>
- _copy_n(RAIter first, Size count, OutputIter result, std::random_access_iterator_tag)
- {
- RAIter last = first + count;
- return std::pair<RAIter, OutputIter>(last, std::copy(first, last, result));
- }
- template <class InputIter, class Size, class OutputIter>
- inline std::pair<InputIter, OutputIter>
- _copy_n(InputIter first, Size count, OutputIter result)
- {
- return _copy_n(first, count, result, typename std::iterator_traits<InputIter>::iterator_category());
- }
- template <class InputIter, class Size, class OutputIter>
- inline std::pair<InputIter, OutputIter>
- copy_n(InputIter first, Size count, OutputIter result)
- {
- return detail::_copy_n(first, count, result);
- }
- /// \brief identity taken from SGI STL.
- template <typename T>
- struct identity
- {
- using argument_type = T;
- using result_type = T;
- const T& operator()(const T& val) const { return val; }
- };
- /// \brief plus function object whose arguments may be of different type.
- template <typename T1, typename T2>
- struct plus_asymmetric {
- using first_argument_type = T1;
- using second_argument_type = T2;
- using result_type = T1;
- T1 operator()(T1 f1, T2 f2) const
- {
- return f1+f2;
- }
- };
- /// \brief operator++ wrapped in a function object
- template <typename T>
- struct inc
- {
- using argument_type = T;
- using result_type = T;
- T operator()(T x) const { return ++x; }
- };
- /// \brief operator-- wrapped in a function object
- template <typename T>
- struct dec
- {
- using argument_type = T;
- using result_type = T;
- T operator()(T x) const { return --x; }
- };
- /// \brief Returns the index corresponding to the first occurrance of a given given type in
- // a given Boost.MP11-compatible list (or size if the type is not present)
- template <typename Types, typename T>
- struct type_to_index : mp11::mp_find<Types, T>
- {
- static_assert(mp11::mp_contains<Types, T>::value, "T should be element of Types");
- };
- } // namespace detail
- /// \ingroup ColorSpaceAndLayoutModel
- /// \brief Represents a color space and ordering of channels in memory
- template
- <
- typename ColorSpace,
- typename ChannelMapping = mp11::mp_iota
- <
- std::integral_constant<int, mp11::mp_size<ColorSpace>::value>
- >
- >
- struct layout
- {
- using color_space_t = ColorSpace;
- using channel_mapping_t = ChannelMapping;
- static_assert(mp11::mp_size<ColorSpace>::value > 0,
- "color space should not be empty sequence");
- };
- /// \brief A version of swap that also works with reference proxy objects
- /// Where value_type<T1> == value_type<T2> == Value
- template <typename Value, typename T1, typename T2>
- void swap_proxy(T1& left, T2& right)
- {
- Value tmp = left;
- left = right;
- right = tmp;
- }
- /// \brief Run-time detection of whether the underlying architecture is little endian
- BOOST_FORCEINLINE bool little_endian()
- {
- short tester = 0x0001;
- return *(char*)&tester!=0;
- }
- /// \brief Run-time detection of whether the underlying architecture is big endian
- BOOST_FORCEINLINE bool big_endian()
- {
- return !little_endian();
- }
- }} // namespace boost::gil
- #endif
|