Chris@16: /* Chris@16: Copyright 2005-2007 Adobe Systems Incorporated Chris@16: Chris@16: Use, modification and distribution are subject to the Boost Software License, Chris@16: Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: http://www.boost.org/LICENSE_1_0.txt). Chris@16: Chris@16: See http://opensource.adobe.com/gil for most recent version including documentation. Chris@16: */ Chris@16: Chris@16: /*************************************************************************************************/ Chris@16: Chris@16: #ifndef GIL_UTILITIES_H Chris@16: #define GIL_UTILITIES_H Chris@16: Chris@16: #include "gil_config.hpp" Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file Chris@16: /// \brief Various utilities not specific to the image library. Some are non-standard STL extensions or generic iterator adaptors Chris@16: /// \author Lubomir Bourdev and Hailin Jin \n Chris@16: /// Adobe Systems Incorporated Chris@16: /// \date 2005-2007 \n Last updated on September 18, 2007 Chris@16: /// Chris@16: /// Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: namespace boost { namespace gil { Chris@16: Chris@16: /** Chris@16: \addtogroup PointModel Chris@16: Chris@16: Example: Chris@16: \code Chris@16: point2 p(3,2); Chris@16: assert((p[0] == p.x) && (p[1] == p.y)); Chris@16: assert(axis_value<0>(p) == 3); Chris@16: assert(axis_value<1>(p) == 2); Chris@16: \endcode Chris@16: */ Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: // CLASS point2 Chris@16: /// Chris@16: /// \brief 2D point both axes of which have the same dimension type Chris@16: /// \ingroup PointModel Chris@16: /// Models: Point2DConcept Chris@16: /// Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: template Chris@16: class point2 { Chris@16: public: Chris@16: typedef T value_type; Chris@16: template struct axis { typedef value_type coord_t; }; Chris@16: static const std::size_t num_dimensions=2; Chris@16: Chris@16: point2() : x(0), y(0) {} Chris@16: point2(T newX, T newY) : x(newX), y(newY) {} Chris@16: point2(const point2& p) : x(p.x), y(p.y) {} Chris@16: ~point2() {} Chris@16: Chris@16: point2& operator=(const point2& p) { x=p.x; y=p.y; return *this; } Chris@16: Chris@16: point2 operator<<(std::ptrdiff_t shift) const { return point2(x<>(std::ptrdiff_t shift) const { return point2(x>>shift,y>>shift); } Chris@16: point2& operator+=(const point2& p) { x+=p.x; y+=p.y; return *this; } Chris@16: point2& operator-=(const point2& p) { x-=p.x; y-=p.y; return *this; } Chris@16: point2& operator/=(double t) { x/=t; y/=t; return *this; } Chris@16: Chris@16: const T& operator[](std::size_t i) const { return this->*mem_array[i]; } Chris@16: T& operator[](std::size_t i) { return this->*mem_array[i]; } Chris@16: Chris@16: T x,y; Chris@16: private: Chris@16: // this static array of pointers to member variables makes operator[] safe and doesn't seem to exhibit any performance penalty Chris@16: static T point2::* const mem_array[num_dimensions]; Chris@16: }; Chris@16: Chris@16: template Chris@16: T point2::* const point2::mem_array[point2::num_dimensions] = { &point2::x, &point2::y }; Chris@16: Chris@16: /// \ingroup PointModel Chris@16: template GIL_FORCEINLINE Chris@16: bool operator==(const point2& p1, const point2& p2) { return (p1.x==p2.x && p1.y==p2.y); } Chris@16: /// \ingroup PointModel Chris@16: template GIL_FORCEINLINE Chris@16: bool operator!=(const point2& p1, const point2& p2) { return p1.x!=p2.x || p1.y!=p2.y; } Chris@16: /// \ingroup PointModel Chris@16: template GIL_FORCEINLINE Chris@16: point2 operator+(const point2& p1, const point2& p2) { return point2(p1.x+p2.x,p1.y+p2.y); } Chris@16: /// \ingroup PointModel Chris@16: template GIL_FORCEINLINE Chris@16: point2 operator-(const point2& p) { return point2(-p.x,-p.y); } Chris@16: /// \ingroup PointModel Chris@16: template GIL_FORCEINLINE Chris@16: point2 operator-(const point2& p1, const point2& p2) { return point2(p1.x-p2.x,p1.y-p2.y); } Chris@16: /// \ingroup PointModel Chris@16: template GIL_FORCEINLINE Chris@16: point2 operator/(const point2& p, double t) { return t==0 ? point2(0,0):point2(p.x/t,p.y/t); } Chris@16: /// \ingroup PointModel Chris@16: template GIL_FORCEINLINE Chris@16: point2 operator*(const point2& p, std::ptrdiff_t t) { return point2(p.x*t,p.y*t); } Chris@16: /// \ingroup PointModel Chris@16: template GIL_FORCEINLINE Chris@16: point2 operator*(std::ptrdiff_t t, const point2& p) { return point2(p.x*t,p.y*t); } Chris@16: Chris@16: /// \ingroup PointModel Chris@16: template GIL_FORCEINLINE Chris@16: const T& axis_value(const point2& p) { return p[K]; } Chris@16: Chris@16: /// \ingroup PointModel Chris@16: template GIL_FORCEINLINE Chris@16: T& axis_value( point2& p) { return p[K]; } Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: /// Chris@16: /// Rounding of real numbers / points to integers / integer points Chris@16: /// Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: inline std::ptrdiff_t iround(float x ) { return static_cast(x + (x < 0.0f ? -0.5f : 0.5f)); } Chris@16: inline std::ptrdiff_t iround(double x) { return static_cast(x + (x < 0.0 ? -0.5 : 0.5)); } Chris@16: inline std::ptrdiff_t ifloor(float x ) { return static_cast(std::floor(x)); } Chris@16: inline std::ptrdiff_t ifloor(double x) { return static_cast(std::floor(x)); } Chris@16: inline std::ptrdiff_t iceil(float x ) { return static_cast(std::ceil(x)); } Chris@16: inline std::ptrdiff_t iceil(double x) { return static_cast(std::ceil(x)); } Chris@16: Chris@16: /** Chris@16: \addtogroup PointAlgorithm Chris@16: Chris@16: Example: Chris@16: \code Chris@16: assert(iround(point2(3.1, 3.9)) == point2(3,4)); Chris@16: \endcode Chris@16: */ Chris@16: Chris@16: /// \ingroup PointAlgorithm Chris@16: inline point2 iround(const point2& p) { return point2(iround(p.x),iround(p.y)); } Chris@16: /// \ingroup PointAlgorithm Chris@16: inline point2 iround(const point2& p) { return point2(iround(p.x),iround(p.y)); } Chris@16: /// \ingroup PointAlgorithm Chris@16: inline point2 ifloor(const point2& p) { return point2(ifloor(p.x),ifloor(p.y)); } Chris@16: /// \ingroup PointAlgorithm Chris@16: inline point2 ifloor(const point2& p) { return point2(ifloor(p.x),ifloor(p.y)); } Chris@16: /// \ingroup PointAlgorithm Chris@16: inline point2 iceil (const point2& p) { return point2(iceil(p.x), iceil(p.y)); } Chris@16: /// \ingroup PointAlgorithm Chris@16: inline point2 iceil (const point2& p) { return point2(iceil(p.x), iceil(p.y)); } Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: /// Chris@16: /// computing size with alignment Chris@16: /// Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: template Chris@16: inline T align(T val, std::size_t alignment) { Chris@16: return val+(alignment - val%alignment)%alignment; Chris@16: } Chris@16: Chris@16: /// \brief Helper base class for pixel dereference adaptors. Chris@16: /// \ingroup PixelDereferenceAdaptorModel Chris@16: /// Chris@16: template Chris@16: struct deref_base : public std::unary_function { Chris@16: typedef ConstT const_t; Chris@16: typedef Value value_type; Chris@16: typedef Reference reference; Chris@16: typedef ConstReference const_reference; Chris@16: BOOST_STATIC_CONSTANT(bool, is_mutable = IsMutable); Chris@16: }; Chris@16: Chris@16: /// \brief Composes two dereference function objects. Similar to std::unary_compose but needs to pull some typedefs from the component types. Models: PixelDereferenceAdaptorConcept Chris@16: /// \ingroup PixelDereferenceAdaptorModel Chris@16: /// Chris@16: template Chris@16: class deref_compose : public deref_base< Chris@16: deref_compose, Chris@16: typename D1::value_type, typename D1::reference, typename D1::const_reference, Chris@16: typename D2::argument_type, typename D1::result_type, D1::is_mutable && D2::is_mutable> Chris@16: { Chris@16: public: Chris@16: D1 _fn1; Chris@16: D2 _fn2; Chris@16: Chris@16: typedef typename D2::argument_type argument_type; Chris@16: typedef typename D1::result_type result_type; Chris@16: Chris@16: deref_compose() {} Chris@16: deref_compose(const D1& x, const D2& y) : _fn1(x), _fn2(y) {} Chris@16: deref_compose(const deref_compose& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {} Chris@16: template deref_compose(const deref_compose<_D1,_D2>& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {} Chris@16: Chris@16: result_type operator()(argument_type x) const { return _fn1(_fn2(x)); } Chris@16: result_type operator()(argument_type x) { return _fn1(_fn2(x)); } Chris@16: }; Chris@16: Chris@16: // reinterpret_cast is implementation-defined. Static cast is not. Chris@16: template GIL_FORCEINLINE Chris@16: OutPtr gil_reinterpret_cast( In* p) { return static_cast(static_cast(p)); } Chris@16: Chris@16: template GIL_FORCEINLINE Chris@16: const OutPtr gil_reinterpret_cast_c(const In* p) { return static_cast(static_cast(p)); } Chris@16: Chris@16: namespace detail { Chris@16: Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: /// Chris@16: /// \brief copy_n taken from SGI STL. Chris@16: /// Chris@16: //////////////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: template Chris@16: std::pair _copy_n(InputIter first, Size count, Chris@16: OutputIter result, Chris@16: std::input_iterator_tag) { Chris@16: for ( ; count > 0; --count) { Chris@16: *result = *first; Chris@16: ++first; Chris@16: ++result; Chris@16: } Chris@16: return std::pair(first, result); Chris@16: } Chris@16: Chris@16: template Chris@16: inline std::pair Chris@16: _copy_n(RAIter first, Size count, OutputIter result, std::random_access_iterator_tag) { Chris@16: RAIter last = first + count; Chris@16: return std::pair(last, std::copy(first, last, result)); Chris@16: } Chris@16: Chris@16: template Chris@16: inline std::pair Chris@16: _copy_n(InputIter first, Size count, OutputIter result) { Chris@16: return _copy_n(first, count, result, typename std::iterator_traits::iterator_category()); Chris@16: } Chris@16: Chris@16: template Chris@16: inline std::pair Chris@16: copy_n(InputIter first, Size count, OutputIter result) { Chris@16: return detail::_copy_n(first, count, result); Chris@16: } Chris@16: Chris@16: /// \brief identity taken from SGI STL. Chris@16: template Chris@16: struct identity : public std::unary_function { Chris@16: const T& operator()(const T& val) const { return val; } Chris@16: }; Chris@16: Chris@16: /*************************************************************************************************/ Chris@16: Chris@16: /// \brief plus function object whose arguments may be of different type. Chris@16: template Chris@16: struct plus_asymmetric : public std::binary_function { Chris@16: T1 operator()(T1 f1, T2 f2) const { Chris@16: return f1+f2; Chris@16: } Chris@16: }; Chris@16: Chris@16: /*************************************************************************************************/ Chris@16: Chris@16: /// \brief operator++ wrapped in a function object Chris@16: template Chris@16: struct inc : public std::unary_function { Chris@16: T operator()(T x) const { return ++x; } Chris@16: }; Chris@16: Chris@16: /*************************************************************************************************/ Chris@16: Chris@16: /// \brief operator-- wrapped in a function object Chris@16: template Chris@16: struct dec : public std::unary_function { Chris@16: T operator()(T x) const { return --x; } Chris@16: }; Chris@16: Chris@16: /// \brief Returns the index corresponding to the first occurrance of a given given type in Chris@16: // a given MPL RandomAccessSequence (or size if the type is not present) Chris@16: template Chris@16: struct type_to_index Chris@16: : public mpl::distance::type, Chris@16: typename mpl::find::type>::type {}; Chris@16: } // namespace detail Chris@16: Chris@16: Chris@16: Chris@16: /// \ingroup ColorSpaceAndLayoutModel Chris@16: /// \brief Represents a color space and ordering of channels in memory Chris@16: template ::value> > Chris@16: struct layout { Chris@16: typedef ColorSpace color_space_t; Chris@16: typedef ChannelMapping channel_mapping_t; Chris@16: }; Chris@16: Chris@16: /// \brief A version of swap that also works with reference proxy objects Chris@16: template // where value_type == value_type == Value Chris@16: void swap_proxy(T1& left, T2& right) { Chris@16: Value tmp = left; Chris@16: left = right; Chris@16: right = tmp; Chris@16: } Chris@16: Chris@16: /// \brief Run-time detection of whether the underlying architecture is little endian Chris@16: inline bool little_endian() { Chris@16: short tester = 0x0001; Chris@16: return *(char*)&tester!=0; Chris@16: } Chris@16: /// \brief Run-time detection of whether the underlying architecture is big endian Chris@16: inline bool big_endian() { Chris@16: return !little_endian(); Chris@16: } Chris@16: Chris@16: } } // namespace boost::gil Chris@16: Chris@16: #endif