2 Copyright 2005-2007 Adobe Systems Incorporated
4 Use, modification and distribution are subject to the Boost Software License,
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt).
8 See http://opensource.adobe.com/gil for most recent version including documentation.
11 /*************************************************************************************************/
13 #ifndef GIL_UTILITIES_H
14 #define GIL_UTILITIES_H
16 #include "gil_config.hpp"
18 #include <boost/config/no_tr1/cmath.hpp>
23 #include <boost/static_assert.hpp>
24 #include <boost/type_traits.hpp>
25 #include <boost/mpl/size.hpp>
26 #include <boost/mpl/distance.hpp>
27 #include <boost/mpl/begin.hpp>
28 #include <boost/mpl/find.hpp>
29 #include <boost/mpl/range_c.hpp>
30 #include <boost/iterator/iterator_adaptor.hpp>
31 #include <boost/iterator/iterator_facade.hpp>
33 ////////////////////////////////////////////////////////////////////////////////////////
35 /// \brief Various utilities not specific to the image library. Some are non-standard STL extensions or generic iterator adaptors
36 /// \author Lubomir Bourdev and Hailin Jin \n
37 /// Adobe Systems Incorporated
38 /// \date 2005-2007 \n Last updated on September 18, 2007
41 ////////////////////////////////////////////////////////////////////////////////////////
43 namespace boost
{ namespace gil
{
46 \addtogroup PointModel
50 point2<std::ptrdiff_t> p(3,2);
51 assert((p[0] == p.x) && (p[1] == p.y));
52 assert(axis_value<0>(p) == 3);
53 assert(axis_value<1>(p) == 2);
57 ////////////////////////////////////////////////////////////////////////////////////////
60 /// \brief 2D point both axes of which have the same dimension type
61 /// \ingroup PointModel
62 /// Models: Point2DConcept
64 ////////////////////////////////////////////////////////////////////////////////////////
70 template <std::size_t D
> struct axis
{ typedef value_type coord_t
; };
71 static const std::size_t num_dimensions
=2;
73 point2() : x(0), y(0) {}
74 point2(T newX
, T newY
) : x(newX
), y(newY
) {}
75 point2(const point2
& p
) : x(p
.x
), y(p
.y
) {}
78 point2
& operator=(const point2
& p
) { x
=p
.x
; y
=p
.y
; return *this; }
80 point2
operator<<(std::ptrdiff_t shift
) const { return point2(x
<<shift
,y
<<shift
); }
81 point2
operator>>(std::ptrdiff_t shift
) const { return point2(x
>>shift
,y
>>shift
); }
82 point2
& operator+=(const point2
& p
) { x
+=p
.x
; y
+=p
.y
; return *this; }
83 point2
& operator-=(const point2
& p
) { x
-=p
.x
; y
-=p
.y
; return *this; }
84 point2
& operator/=(double t
) { x
/=t
; y
/=t
; return *this; }
86 const T
& operator[](std::size_t i
) const { return this->*mem_array
[i
]; }
87 T
& operator[](std::size_t i
) { return this->*mem_array
[i
]; }
91 // this static array of pointers to member variables makes operator[] safe and doesn't seem to exhibit any performance penalty
92 static T point2
<T
>::* const mem_array
[num_dimensions
];
96 T point2
<T
>::* const point2
<T
>::mem_array
[point2
<T
>::num_dimensions
] = { &point2
<T
>::x
, &point2
<T
>::y
};
98 /// \ingroup PointModel
99 template <typename T
> GIL_FORCEINLINE
100 bool operator==(const point2
<T
>& p1
, const point2
<T
>& p2
) { return (p1
.x
==p2
.x
&& p1
.y
==p2
.y
); }
101 /// \ingroup PointModel
102 template <typename T
> GIL_FORCEINLINE
103 bool operator!=(const point2
<T
>& p1
, const point2
<T
>& p2
) { return p1
.x
!=p2
.x
|| p1
.y
!=p2
.y
; }
104 /// \ingroup PointModel
105 template <typename T
> GIL_FORCEINLINE
106 point2
<T
> operator+(const point2
<T
>& p1
, const point2
<T
>& p2
) { return point2
<T
>(p1
.x
+p2
.x
,p1
.y
+p2
.y
); }
107 /// \ingroup PointModel
108 template <typename T
> GIL_FORCEINLINE
109 point2
<T
> operator-(const point2
<T
>& p
) { return point2
<T
>(-p
.x
,-p
.y
); }
110 /// \ingroup PointModel
111 template <typename T
> GIL_FORCEINLINE
112 point2
<T
> operator-(const point2
<T
>& p1
, const point2
<T
>& p2
) { return point2
<T
>(p1
.x
-p2
.x
,p1
.y
-p2
.y
); }
113 /// \ingroup PointModel
114 template <typename T
> GIL_FORCEINLINE
115 point2
<double> operator/(const point2
<T
>& p
, double t
) { return t
==0 ? point2
<double>(0,0):point2
<double>(p
.x
/t
,p
.y
/t
); }
116 /// \ingroup PointModel
117 template <typename T
> GIL_FORCEINLINE
118 point2
<T
> operator*(const point2
<T
>& p
, std::ptrdiff_t t
) { return point2
<T
>(p
.x
*t
,p
.y
*t
); }
119 /// \ingroup PointModel
120 template <typename T
> GIL_FORCEINLINE
121 point2
<T
> operator*(std::ptrdiff_t t
, const point2
<T
>& p
) { return point2
<T
>(p
.x
*t
,p
.y
*t
); }
123 /// \ingroup PointModel
124 template <std::size_t K
, typename T
> GIL_FORCEINLINE
125 const T
& axis_value(const point2
<T
>& p
) { return p
[K
]; }
127 /// \ingroup PointModel
128 template <std::size_t K
, typename T
> GIL_FORCEINLINE
129 T
& axis_value( point2
<T
>& p
) { return p
[K
]; }
131 ////////////////////////////////////////////////////////////////////////////////////////
133 /// Rounding of real numbers / points to integers / integer points
135 ////////////////////////////////////////////////////////////////////////////////////////
137 inline std::ptrdiff_t iround(float x
) { return static_cast<std::ptrdiff_t>(x
+ (x
< 0.0f
? -0.5f
: 0.5f
)); }
138 inline std::ptrdiff_t iround(double x
) { return static_cast<std::ptrdiff_t>(x
+ (x
< 0.0 ? -0.5 : 0.5)); }
139 inline std::ptrdiff_t ifloor(float x
) { return static_cast<std::ptrdiff_t>(std::floor(x
)); }
140 inline std::ptrdiff_t ifloor(double x
) { return static_cast<std::ptrdiff_t>(std::floor(x
)); }
141 inline std::ptrdiff_t iceil(float x
) { return static_cast<std::ptrdiff_t>(std::ceil(x
)); }
142 inline std::ptrdiff_t iceil(double x
) { return static_cast<std::ptrdiff_t>(std::ceil(x
)); }
145 \addtogroup PointAlgorithm
149 assert(iround(point2<double>(3.1, 3.9)) == point2<std::ptrdiff_t>(3,4));
153 /// \ingroup PointAlgorithm
154 inline point2
<std::ptrdiff_t> iround(const point2
<float >& p
) { return point2
<std::ptrdiff_t>(iround(p
.x
),iround(p
.y
)); }
155 /// \ingroup PointAlgorithm
156 inline point2
<std::ptrdiff_t> iround(const point2
<double>& p
) { return point2
<std::ptrdiff_t>(iround(p
.x
),iround(p
.y
)); }
157 /// \ingroup PointAlgorithm
158 inline point2
<std::ptrdiff_t> ifloor(const point2
<float >& p
) { return point2
<std::ptrdiff_t>(ifloor(p
.x
),ifloor(p
.y
)); }
159 /// \ingroup PointAlgorithm
160 inline point2
<std::ptrdiff_t> ifloor(const point2
<double>& p
) { return point2
<std::ptrdiff_t>(ifloor(p
.x
),ifloor(p
.y
)); }
161 /// \ingroup PointAlgorithm
162 inline point2
<std::ptrdiff_t> iceil (const point2
<float >& p
) { return point2
<std::ptrdiff_t>(iceil(p
.x
), iceil(p
.y
)); }
163 /// \ingroup PointAlgorithm
164 inline point2
<std::ptrdiff_t> iceil (const point2
<double>& p
) { return point2
<std::ptrdiff_t>(iceil(p
.x
), iceil(p
.y
)); }
166 ////////////////////////////////////////////////////////////////////////////////////////
168 /// computing size with alignment
170 ////////////////////////////////////////////////////////////////////////////////////////
172 template <typename T
>
173 inline T
align(T val
, std::size_t alignment
) {
174 return val
+(alignment
- val
%alignment
)%alignment
;
177 /// \brief Helper base class for pixel dereference adaptors.
178 /// \ingroup PixelDereferenceAdaptorModel
180 template <typename ConstT
, typename Value
, typename Reference
, typename ConstReference
,
181 typename ArgType
, typename ResultType
, bool IsMutable
>
182 struct deref_base
: public std::unary_function
<ArgType
, ResultType
> {
183 typedef ConstT const_t
;
184 typedef Value value_type
;
185 typedef Reference reference
;
186 typedef ConstReference const_reference
;
187 BOOST_STATIC_CONSTANT(bool, is_mutable
= IsMutable
);
190 /// \brief Composes two dereference function objects. Similar to std::unary_compose but needs to pull some typedefs from the component types. Models: PixelDereferenceAdaptorConcept
191 /// \ingroup PixelDereferenceAdaptorModel
193 template <typename D1
, typename D2
>
194 class deref_compose
: public deref_base
<
195 deref_compose
<typename
D1::const_t
, typename
D2::const_t
>,
196 typename
D1::value_type
, typename
D1::reference
, typename
D1::const_reference
,
197 typename
D2::argument_type
, typename
D1::result_type
, D1::is_mutable
&& D2::is_mutable
>
203 typedef typename
D2::argument_type argument_type
;
204 typedef typename
D1::result_type result_type
;
207 deref_compose(const D1
& x
, const D2
& y
) : _fn1(x
), _fn2(y
) {}
208 deref_compose(const deref_compose
& dc
) : _fn1(dc
._fn1
), _fn2(dc
._fn2
) {}
209 template <typename _D1
, typename _D2
> deref_compose(const deref_compose
<_D1
,_D2
>& dc
) : _fn1(dc
._fn1
), _fn2(dc
._fn2
) {}
211 result_type
operator()(argument_type x
) const { return _fn1(_fn2(x
)); }
212 result_type
operator()(argument_type x
) { return _fn1(_fn2(x
)); }
215 // reinterpret_cast is implementation-defined. Static cast is not.
216 template <typename OutPtr
, typename In
> GIL_FORCEINLINE
217 OutPtr
gil_reinterpret_cast( In
* p
) { return static_cast<OutPtr
>(static_cast<void*>(p
)); }
219 template <typename OutPtr
, typename In
> GIL_FORCEINLINE
220 const OutPtr
gil_reinterpret_cast_c(const In
* p
) { return static_cast<const OutPtr
>(static_cast<const void*>(p
)); }
224 ////////////////////////////////////////////////////////////////////////////////////////
226 /// \brief copy_n taken from SGI STL.
228 ////////////////////////////////////////////////////////////////////////////////////////
230 template <class InputIter
, class Size
, class OutputIter
>
231 std::pair
<InputIter
, OutputIter
> _copy_n(InputIter first
, Size count
,
233 std::input_iterator_tag
) {
234 for ( ; count
> 0; --count
) {
239 return std::pair
<InputIter
, OutputIter
>(first
, result
);
242 template <class RAIter
, class Size
, class OutputIter
>
243 inline std::pair
<RAIter
, OutputIter
>
244 _copy_n(RAIter first
, Size count
, OutputIter result
, std::random_access_iterator_tag
) {
245 RAIter last
= first
+ count
;
246 return std::pair
<RAIter
, OutputIter
>(last
, std::copy(first
, last
, result
));
249 template <class InputIter
, class Size
, class OutputIter
>
250 inline std::pair
<InputIter
, OutputIter
>
251 _copy_n(InputIter first
, Size count
, OutputIter result
) {
252 return _copy_n(first
, count
, result
, typename
std::iterator_traits
<InputIter
>::iterator_category());
255 template <class InputIter
, class Size
, class OutputIter
>
256 inline std::pair
<InputIter
, OutputIter
>
257 copy_n(InputIter first
, Size count
, OutputIter result
) {
258 return detail::_copy_n(first
, count
, result
);
261 /// \brief identity taken from SGI STL.
262 template <typename T
>
263 struct identity
: public std::unary_function
<T
,T
> {
264 const T
& operator()(const T
& val
) const { return val
; }
267 /*************************************************************************************************/
269 /// \brief plus function object whose arguments may be of different type.
270 template <typename T1
, typename T2
>
271 struct plus_asymmetric
: public std::binary_function
<T1
,T2
,T1
> {
272 T1
operator()(T1 f1
, T2 f2
) const {
277 /*************************************************************************************************/
279 /// \brief operator++ wrapped in a function object
280 template <typename T
>
281 struct inc
: public std::unary_function
<T
,T
> {
282 T
operator()(T x
) const { return ++x
; }
285 /*************************************************************************************************/
287 /// \brief operator-- wrapped in a function object
288 template <typename T
>
289 struct dec
: public std::unary_function
<T
,T
> {
290 T
operator()(T x
) const { return --x
; }
293 /// \brief Returns the index corresponding to the first occurrance of a given given type in
294 // a given MPL RandomAccessSequence (or size if the type is not present)
295 template <typename Types
, typename T
>
297 : public mpl::distance
<typename
mpl::begin
<Types
>::type
,
298 typename
mpl::find
<Types
,T
>::type
>::type
{};
299 } // namespace detail
303 /// \ingroup ColorSpaceAndLayoutModel
304 /// \brief Represents a color space and ordering of channels in memory
305 template <typename ColorSpace
, typename ChannelMapping
= mpl::range_c
<int,0,mpl::size
<ColorSpace
>::value
> >
307 typedef ColorSpace color_space_t
;
308 typedef ChannelMapping channel_mapping_t
;
311 /// \brief A version of swap that also works with reference proxy objects
312 template <typename Value
, typename T1
, typename T2
> // where value_type<T1> == value_type<T2> == Value
313 void swap_proxy(T1
& left
, T2
& right
) {
319 /// \brief Run-time detection of whether the underlying architecture is little endian
320 inline bool little_endian() {
321 short tester
= 0x0001;
322 return *(char*)&tester
!=0;
324 /// \brief Run-time detection of whether the underlying architecture is big endian
325 inline bool big_endian() {
326 return !little_endian();
329 } } // namespace boost::gil