Modules | Alphabetical List | Class List | Directories | File List | GIL Home Page # utilities.hpp Go to the documentation of this file.
    00001 /*
    00002     Copyright 2005-2007 Adobe Systems Incorporated
    00003
    00004     Use, modification and distribution are subject to the Boost Software License,
    00005     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
    00006     http://www.boost.org/LICENSE_1_0.txt).
    00007
    00008     See http://opensource.adobe.com/gil for most recent version including documentation.
    00009 */
    00010
    00011 /*************************************************************************************************/
    00012
    00013 #ifndef GIL_UTILITIES_H
    00014 #define GIL_UTILITIES_H
    00015
    00016 #include "gil_config.hpp"
    00017 #include <functional>
    00018 #include <boost/config/no_tr1/cmath.hpp>
    00019 #include <cstddef>
    00020 #include <algorithm>
    00021 #include <utility>
    00022 #include <iterator>
    00023 #include <boost/static_assert.hpp>
    00024 #include <boost/type_traits.hpp>
    00025 #include <boost/mpl/size.hpp>
    00026 #include <boost/mpl/distance.hpp>
    00027 #include <boost/mpl/begin.hpp>
    00028 #include <boost/mpl/find.hpp>
    00029 #include <boost/mpl/range_c.hpp>
    00030 #include <boost/iterator/iterator_adaptor.hpp>
    00031 #include <boost/iterator/iterator_facade.hpp>
    00032
    00042
    00043 namespace boost { namespace gil {
    00044
    00057
    00058 //                           CLASS point2
    00065
    00066 template <typename T>
    00067 class point2 {
    00068 public:
    00069     typedef T value_type;
    00070     template <std::size_t D> struct axis { typedef value_type coord_t; };
    00071     static const std::size_t num_dimensions=2;
    00072
    00073     point2()                : x(0),     y(0)    {}
    00074     point2(T newX, T newY)  : x(newX),  y(newY) {}
    00075     point2(const point2& p) : x(p.x), y(p.y) {}
    00076     ~point2() {}
    00077
    00078     point2& operator=(const point2& p)            { x=p.x; y=p.y; return *this; }
    00079
    00080     point2        operator<<(std::ptrdiff_t shift)         const   { return point2(x<<shift,y<<shift); }
    00081     point2        operator>>(std::ptrdiff_t shift)         const   { return point2(x>>shift,y>>shift); }
    00082     point2& operator+=(const point2& p)           { x+=p.x; y+=p.y; return *this; }
    00083     point2& operator-=(const point2& p)           { x-=p.x; y-=p.y; return *this; }
    00084     point2& operator/=(double t)                  { x/=t; y/=t; return *this; }
    00085
    00086     const T& operator[](std::size_t i)          const   { return this->*mem_array[i]; }
    00087           T& operator[](std::size_t i)                  { return this->*mem_array[i]; }
    00088
    00089     T x,y;
    00090 private:
    00091     // this static array of pointers to member variables makes operator[] safe and doesn't seem to exhibit any performance penalty
    00092     static T point2<T>::* const mem_array[num_dimensions];
    00093 };
    00094
    00095 template <typename T>
    00096 T point2<T>::* const point2<T>::mem_array[point2<T>::num_dimensions] = { &point2<T>::x, &point2<T>::y };
    00097
    00099 template <typename T> GIL_FORCEINLINE
    00100 bool operator==(const point2<T>& p1, const point2<T>& p2) { return (p1.x==p2.x && p1.y==p2.y); }
    00102 template <typename T> GIL_FORCEINLINE
    00103 bool operator!=(const point2<T>& p1, const point2<T>& p2) { return  p1.x!=p2.x || p1.y!=p2.y; }
    00105 template <typename T> GIL_FORCEINLINE
    00106 point2<T> operator+(const point2<T>& p1, const point2<T>& p2) { return point2<T>(p1.x+p2.x,p1.y+p2.y); }
    00108 template <typename T> GIL_FORCEINLINE
    00109 point2<T> operator-(const point2<T>& p) { return point2<T>(-p.x,-p.y); }
    00111 template <typename T> GIL_FORCEINLINE
    00112 point2<T> operator-(const point2<T>& p1, const point2<T>& p2) { return point2<T>(p1.x-p2.x,p1.y-p2.y); }
    00114 template <typename T> GIL_FORCEINLINE
    00115 point2<double> operator/(const point2<T>& p, double t)      { return t==0 ? point2<double>(0,0):point2<double>(p.x/t,p.y/t); }
    00117 template <typename T> GIL_FORCEINLINE
    00118 point2<T> operator*(const point2<T>& p, std::ptrdiff_t t)      { return point2<T>(p.x*t,p.y*t); }
    00120 template <typename T> GIL_FORCEINLINE
    00121 point2<T> operator*(std::ptrdiff_t t, const point2<T>& p)      { return point2<T>(p.x*t,p.y*t); }
    00122
    00124 template <std::size_t K, typename T> GIL_FORCEINLINE
    00125 const T& axis_value(const point2<T>& p) { return p[K]; }
    00126
    00128 template <std::size_t K, typename T> GIL_FORCEINLINE
    00129       T& axis_value(      point2<T>& p) { return p[K]; }
    00130
    00136
    00137 inline std::ptrdiff_t iround(float x ) { return static_cast<std::ptrdiff_t>(x + (x < 0.0f ? -0.5f : 0.5f)); }
    00138 inline std::ptrdiff_t iround(double x) { return static_cast<std::ptrdiff_t>(x + (x < 0.0 ? -0.5 : 0.5)); }
    00139 inline std::ptrdiff_t ifloor(float x ) { return static_cast<std::ptrdiff_t>(std::floor(x)); }
    00140 inline std::ptrdiff_t ifloor(double x) { return static_cast<std::ptrdiff_t>(std::floor(x)); }
    00141 inline std::ptrdiff_t iceil(float x )  { return static_cast<std::ptrdiff_t>(std::ceil(x)); }
    00142 inline std::ptrdiff_t iceil(double x)  { return static_cast<std::ptrdiff_t>(std::ceil(x)); }
    00143
    00153
    00154 inline point2<std::ptrdiff_t> iround(const point2<float >& p)  { return point2<std::ptrdiff_t>(iround(p.x),iround(p.y)); }
    00156 inline point2<std::ptrdiff_t> iround(const point2<double>& p)  { return point2<std::ptrdiff_t>(iround(p.x),iround(p.y)); }
    00158 inline point2<std::ptrdiff_t> ifloor(const point2<float >& p)  { return point2<std::ptrdiff_t>(ifloor(p.x),ifloor(p.y)); }
    00160 inline point2<std::ptrdiff_t> ifloor(const point2<double>& p)  { return point2<std::ptrdiff_t>(ifloor(p.x),ifloor(p.y)); }
    00162 inline point2<std::ptrdiff_t> iceil (const point2<float >& p)  { return point2<std::ptrdiff_t>(iceil(p.x), iceil(p.y)); }
    00164 inline point2<std::ptrdiff_t> iceil (const point2<double>& p)  { return point2<std::ptrdiff_t>(iceil(p.x), iceil(p.y)); }
    00165
    00171
    00172 template <typename T>
    00173 inline T align(T val, std::size_t alignment) {
    00174     return val+(alignment - val%alignment)%alignment;
    00175 }
    00176
    00180 template <typename ConstT, typename Value, typename Reference, typename ConstReference,
    00181           typename ArgType, typename ResultType, bool IsMutable>
    00182 struct deref_base : public std::unary_function<ArgType, ResultType> {
    00183     typedef ConstT         const_t;
    00184     typedef Value          value_type;
    00185     typedef Reference      reference;
    00186     typedef ConstReference const_reference;
    00187     BOOST_STATIC_CONSTANT(bool, is_mutable = IsMutable);
    00188 };
    00189
    00193 template <typename D1, typename D2>
    00194 class deref_compose : public deref_base<
    00195       deref_compose<typename D1::const_t, typename D2::const_t>,
    00196       typename D1::value_type, typename D1::reference, typename D1::const_reference,
    00197       typename D2::argument_type, typename D1::result_type, D1::is_mutable && D2::is_mutable>
    00198 {
    00199 public:
    00200     D1 _fn1;
    00201     D2 _fn2;
    00202
    00203     typedef typename D2::argument_type   argument_type;
    00204     typedef typename D1::result_type     result_type;
    00205
    00206     deref_compose() {}
    00207     deref_compose(const D1& x, const D2& y) : _fn1(x), _fn2(y) {}
    00208     deref_compose(const deref_compose& dc)  : _fn1(dc._fn1), _fn2(dc._fn2) {}
    00209     template <typename _D1, typename _D2> deref_compose(const deref_compose<_D1,_D2>& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {}
    00210
    00211     result_type operator()(argument_type x) const { return _fn1(_fn2(x)); }
    00212     result_type operator()(argument_type x)       { return _fn1(_fn2(x)); }
    00213 };
    00214
    00215 // reinterpret_cast is implementation-defined. Static cast is not.
    00216 template <typename OutPtr, typename In> GIL_FORCEINLINE
    00217       OutPtr gil_reinterpret_cast(      In* p) { return static_cast<OutPtr>(static_cast<void*>(p)); }
    00218
    00219 template <typename OutPtr, typename In> GIL_FORCEINLINE
    00220 const OutPtr gil_reinterpret_cast_c(const In* p) { return static_cast<const OutPtr>(static_cast<const void*>(p)); }
    00221
    00222 namespace detail {
    00223
    00229
    00230 template <class InputIter, class Size, class OutputIter>
    00231 std::pair<InputIter, OutputIter> _copy_n(InputIter first, Size count,
    00232                                          OutputIter result,
    00233                                          std::input_iterator_tag) {
    00234    for ( ; count > 0; --count) {
    00235       *result = *first;
    00236       ++first;
    00237       ++result;
    00238    }
    00239    return std::pair<InputIter, OutputIter>(first, result);
    00240 }
    00241
    00242 template <class RAIter, class Size, class OutputIter>
    00243 inline std::pair<RAIter, OutputIter>
    00244 _copy_n(RAIter first, Size count, OutputIter result, std::random_access_iterator_tag) {
    00245    RAIter last = first + count;
    00246    return std::pair<RAIter, OutputIter>(last, std::copy(first, last, result));
    00247 }
    00248
    00249 template <class InputIter, class Size, class OutputIter>
    00250 inline std::pair<InputIter, OutputIter>
    00251 _copy_n(InputIter first, Size count, OutputIter result) {
    00252    return _copy_n(first, count, result, typename std::iterator_traits<InputIter>::iterator_category());
    00253 }
    00254
    00255 template <class InputIter, class Size, class OutputIter>
    00256 inline std::pair<InputIter, OutputIter>
    00257 copy_n(InputIter first, Size count, OutputIter result) {
    00258     return detail::_copy_n(first, count, result);
    00259 }
    00260
    00262 template <typename T>
    00263 struct identity : public std::unary_function<T,T> {
    00264     const T& operator()(const T& val) const { return val; }
    00265 };
    00266
    00267 /*************************************************************************************************/
    00268
    00270 template <typename T1, typename T2>
    00271 struct plus_asymmetric : public std::binary_function<T1,T2,T1> {
    00272     T1 operator()(T1 f1, T2 f2) const {
    00273         return f1+f2;
    00274     }
    00275 };
    00276
    00277 /*************************************************************************************************/
    00278
    00280 template <typename T>
    00281 struct inc : public std::unary_function<T,T> {
    00282     T operator()(T x) const { return ++x; }
    00283 };
    00284
    00285 /*************************************************************************************************/
    00286
    00288 template <typename T>
    00289 struct dec : public std::unary_function<T,T> {
    00290     T operator()(T x) const { return --x; }
    00291 };
    00292
    00294 //         a given MPL RandomAccessSequence (or size if the type is not present)
    00295 template <typename Types, typename T>
    00296 struct type_to_index
    00297     : public mpl::distance<typename mpl::begin<Types>::type,
    00298                                   typename mpl::find<Types,T>::type>::type {};
    00299 } // namespace detail
    00300
    00301
    00302
    00305 template <typename ColorSpace, typename ChannelMapping = mpl::range_c<int,0,mpl::size<ColorSpace>::value> >
    00306 struct layout {
    00307     typedef ColorSpace      color_space_t;
    00308     typedef ChannelMapping  channel_mapping_t;
    00309 };
    00310
    00312 template <typename Value, typename T1, typename T2> // where value_type<T1>  == value_type<T2> == Value
    00313 void swap_proxy(T1& left, T2& right) {
    00314     Value tmp = left;
    00315     left = right;
    00316     right = tmp;
    00317 }
    00318
    00320 inline bool little_endian() {
    00321     short tester = 0x0001;
    00322     return  *(char*)&tester!=0;
    00323 }
    00325 inline bool big_endian() {
    00326     return !little_endian();
    00327 }
    00328
    00329 } }  // namespace boost::gil
    00330
    00331 #endif