Chris@16
|
1 /*
|
Chris@16
|
2 Copyright 2005-2007 Adobe Systems Incorporated
|
Chris@16
|
3
|
Chris@16
|
4 Use, modification and distribution are subject to the Boost Software License,
|
Chris@16
|
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 http://www.boost.org/LICENSE_1_0.txt).
|
Chris@16
|
7
|
Chris@16
|
8 See http://opensource.adobe.com/gil for most recent version including documentation.
|
Chris@16
|
9 */
|
Chris@16
|
10
|
Chris@16
|
11 /*************************************************************************************************/
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef GIL_UTILITIES_H
|
Chris@16
|
14 #define GIL_UTILITIES_H
|
Chris@16
|
15
|
Chris@16
|
16 #include "gil_config.hpp"
|
Chris@16
|
17 #include <functional>
|
Chris@16
|
18 #include <boost/config/no_tr1/cmath.hpp>
|
Chris@16
|
19 #include <cstddef>
|
Chris@16
|
20 #include <algorithm>
|
Chris@16
|
21 #include <utility>
|
Chris@16
|
22 #include <iterator>
|
Chris@16
|
23 #include <boost/static_assert.hpp>
|
Chris@16
|
24 #include <boost/type_traits.hpp>
|
Chris@16
|
25 #include <boost/mpl/size.hpp>
|
Chris@16
|
26 #include <boost/mpl/distance.hpp>
|
Chris@16
|
27 #include <boost/mpl/begin.hpp>
|
Chris@16
|
28 #include <boost/mpl/find.hpp>
|
Chris@16
|
29 #include <boost/mpl/range_c.hpp>
|
Chris@16
|
30 #include <boost/iterator/iterator_adaptor.hpp>
|
Chris@16
|
31 #include <boost/iterator/iterator_facade.hpp>
|
Chris@16
|
32
|
Chris@16
|
33 ////////////////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
34 /// \file
|
Chris@16
|
35 /// \brief Various utilities not specific to the image library. Some are non-standard STL extensions or generic iterator adaptors
|
Chris@16
|
36 /// \author Lubomir Bourdev and Hailin Jin \n
|
Chris@16
|
37 /// Adobe Systems Incorporated
|
Chris@16
|
38 /// \date 2005-2007 \n Last updated on September 18, 2007
|
Chris@16
|
39 ///
|
Chris@16
|
40 ///
|
Chris@16
|
41 ////////////////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
42
|
Chris@16
|
43 namespace boost { namespace gil {
|
Chris@16
|
44
|
Chris@16
|
45 /**
|
Chris@16
|
46 \addtogroup PointModel
|
Chris@16
|
47
|
Chris@16
|
48 Example:
|
Chris@16
|
49 \code
|
Chris@16
|
50 point2<std::ptrdiff_t> p(3,2);
|
Chris@16
|
51 assert((p[0] == p.x) && (p[1] == p.y));
|
Chris@16
|
52 assert(axis_value<0>(p) == 3);
|
Chris@16
|
53 assert(axis_value<1>(p) == 2);
|
Chris@16
|
54 \endcode
|
Chris@16
|
55 */
|
Chris@16
|
56
|
Chris@16
|
57 ////////////////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
58 // CLASS point2
|
Chris@16
|
59 ///
|
Chris@16
|
60 /// \brief 2D point both axes of which have the same dimension type
|
Chris@16
|
61 /// \ingroup PointModel
|
Chris@16
|
62 /// Models: Point2DConcept
|
Chris@16
|
63 ///
|
Chris@16
|
64 ////////////////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
65
|
Chris@16
|
66 template <typename T>
|
Chris@16
|
67 class point2 {
|
Chris@16
|
68 public:
|
Chris@16
|
69 typedef T value_type;
|
Chris@16
|
70 template <std::size_t D> struct axis { typedef value_type coord_t; };
|
Chris@16
|
71 static const std::size_t num_dimensions=2;
|
Chris@16
|
72
|
Chris@16
|
73 point2() : x(0), y(0) {}
|
Chris@16
|
74 point2(T newX, T newY) : x(newX), y(newY) {}
|
Chris@16
|
75 point2(const point2& p) : x(p.x), y(p.y) {}
|
Chris@16
|
76 ~point2() {}
|
Chris@16
|
77
|
Chris@16
|
78 point2& operator=(const point2& p) { x=p.x; y=p.y; return *this; }
|
Chris@16
|
79
|
Chris@16
|
80 point2 operator<<(std::ptrdiff_t shift) const { return point2(x<<shift,y<<shift); }
|
Chris@16
|
81 point2 operator>>(std::ptrdiff_t shift) const { return point2(x>>shift,y>>shift); }
|
Chris@16
|
82 point2& operator+=(const point2& p) { x+=p.x; y+=p.y; return *this; }
|
Chris@16
|
83 point2& operator-=(const point2& p) { x-=p.x; y-=p.y; return *this; }
|
Chris@16
|
84 point2& operator/=(double t) { x/=t; y/=t; return *this; }
|
Chris@16
|
85
|
Chris@16
|
86 const T& operator[](std::size_t i) const { return this->*mem_array[i]; }
|
Chris@16
|
87 T& operator[](std::size_t i) { return this->*mem_array[i]; }
|
Chris@16
|
88
|
Chris@16
|
89 T x,y;
|
Chris@16
|
90 private:
|
Chris@16
|
91 // this static array of pointers to member variables makes operator[] safe and doesn't seem to exhibit any performance penalty
|
Chris@16
|
92 static T point2<T>::* const mem_array[num_dimensions];
|
Chris@16
|
93 };
|
Chris@16
|
94
|
Chris@16
|
95 template <typename T>
|
Chris@16
|
96 T point2<T>::* const point2<T>::mem_array[point2<T>::num_dimensions] = { &point2<T>::x, &point2<T>::y };
|
Chris@16
|
97
|
Chris@16
|
98 /// \ingroup PointModel
|
Chris@16
|
99 template <typename T> GIL_FORCEINLINE
|
Chris@16
|
100 bool operator==(const point2<T>& p1, const point2<T>& p2) { return (p1.x==p2.x && p1.y==p2.y); }
|
Chris@16
|
101 /// \ingroup PointModel
|
Chris@16
|
102 template <typename T> GIL_FORCEINLINE
|
Chris@16
|
103 bool operator!=(const point2<T>& p1, const point2<T>& p2) { return p1.x!=p2.x || p1.y!=p2.y; }
|
Chris@16
|
104 /// \ingroup PointModel
|
Chris@16
|
105 template <typename T> GIL_FORCEINLINE
|
Chris@16
|
106 point2<T> operator+(const point2<T>& p1, const point2<T>& p2) { return point2<T>(p1.x+p2.x,p1.y+p2.y); }
|
Chris@16
|
107 /// \ingroup PointModel
|
Chris@16
|
108 template <typename T> GIL_FORCEINLINE
|
Chris@16
|
109 point2<T> operator-(const point2<T>& p) { return point2<T>(-p.x,-p.y); }
|
Chris@16
|
110 /// \ingroup PointModel
|
Chris@16
|
111 template <typename T> GIL_FORCEINLINE
|
Chris@16
|
112 point2<T> operator-(const point2<T>& p1, const point2<T>& p2) { return point2<T>(p1.x-p2.x,p1.y-p2.y); }
|
Chris@16
|
113 /// \ingroup PointModel
|
Chris@16
|
114 template <typename T> GIL_FORCEINLINE
|
Chris@16
|
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); }
|
Chris@16
|
116 /// \ingroup PointModel
|
Chris@16
|
117 template <typename T> GIL_FORCEINLINE
|
Chris@16
|
118 point2<T> operator*(const point2<T>& p, std::ptrdiff_t t) { return point2<T>(p.x*t,p.y*t); }
|
Chris@16
|
119 /// \ingroup PointModel
|
Chris@16
|
120 template <typename T> GIL_FORCEINLINE
|
Chris@16
|
121 point2<T> operator*(std::ptrdiff_t t, const point2<T>& p) { return point2<T>(p.x*t,p.y*t); }
|
Chris@16
|
122
|
Chris@16
|
123 /// \ingroup PointModel
|
Chris@16
|
124 template <std::size_t K, typename T> GIL_FORCEINLINE
|
Chris@16
|
125 const T& axis_value(const point2<T>& p) { return p[K]; }
|
Chris@16
|
126
|
Chris@16
|
127 /// \ingroup PointModel
|
Chris@16
|
128 template <std::size_t K, typename T> GIL_FORCEINLINE
|
Chris@16
|
129 T& axis_value( point2<T>& p) { return p[K]; }
|
Chris@16
|
130
|
Chris@16
|
131 ////////////////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
132 ///
|
Chris@16
|
133 /// Rounding of real numbers / points to integers / integer points
|
Chris@16
|
134 ///
|
Chris@16
|
135 ////////////////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
136
|
Chris@16
|
137 inline std::ptrdiff_t iround(float x ) { return static_cast<std::ptrdiff_t>(x + (x < 0.0f ? -0.5f : 0.5f)); }
|
Chris@16
|
138 inline std::ptrdiff_t iround(double x) { return static_cast<std::ptrdiff_t>(x + (x < 0.0 ? -0.5 : 0.5)); }
|
Chris@16
|
139 inline std::ptrdiff_t ifloor(float x ) { return static_cast<std::ptrdiff_t>(std::floor(x)); }
|
Chris@16
|
140 inline std::ptrdiff_t ifloor(double x) { return static_cast<std::ptrdiff_t>(std::floor(x)); }
|
Chris@16
|
141 inline std::ptrdiff_t iceil(float x ) { return static_cast<std::ptrdiff_t>(std::ceil(x)); }
|
Chris@16
|
142 inline std::ptrdiff_t iceil(double x) { return static_cast<std::ptrdiff_t>(std::ceil(x)); }
|
Chris@16
|
143
|
Chris@16
|
144 /**
|
Chris@16
|
145 \addtogroup PointAlgorithm
|
Chris@16
|
146
|
Chris@16
|
147 Example:
|
Chris@16
|
148 \code
|
Chris@16
|
149 assert(iround(point2<double>(3.1, 3.9)) == point2<std::ptrdiff_t>(3,4));
|
Chris@16
|
150 \endcode
|
Chris@16
|
151 */
|
Chris@16
|
152
|
Chris@16
|
153 /// \ingroup PointAlgorithm
|
Chris@16
|
154 inline point2<std::ptrdiff_t> iround(const point2<float >& p) { return point2<std::ptrdiff_t>(iround(p.x),iround(p.y)); }
|
Chris@16
|
155 /// \ingroup PointAlgorithm
|
Chris@16
|
156 inline point2<std::ptrdiff_t> iround(const point2<double>& p) { return point2<std::ptrdiff_t>(iround(p.x),iround(p.y)); }
|
Chris@16
|
157 /// \ingroup PointAlgorithm
|
Chris@16
|
158 inline point2<std::ptrdiff_t> ifloor(const point2<float >& p) { return point2<std::ptrdiff_t>(ifloor(p.x),ifloor(p.y)); }
|
Chris@16
|
159 /// \ingroup PointAlgorithm
|
Chris@16
|
160 inline point2<std::ptrdiff_t> ifloor(const point2<double>& p) { return point2<std::ptrdiff_t>(ifloor(p.x),ifloor(p.y)); }
|
Chris@16
|
161 /// \ingroup PointAlgorithm
|
Chris@16
|
162 inline point2<std::ptrdiff_t> iceil (const point2<float >& p) { return point2<std::ptrdiff_t>(iceil(p.x), iceil(p.y)); }
|
Chris@16
|
163 /// \ingroup PointAlgorithm
|
Chris@16
|
164 inline point2<std::ptrdiff_t> iceil (const point2<double>& p) { return point2<std::ptrdiff_t>(iceil(p.x), iceil(p.y)); }
|
Chris@16
|
165
|
Chris@16
|
166 ////////////////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
167 ///
|
Chris@16
|
168 /// computing size with alignment
|
Chris@16
|
169 ///
|
Chris@16
|
170 ////////////////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
171
|
Chris@16
|
172 template <typename T>
|
Chris@16
|
173 inline T align(T val, std::size_t alignment) {
|
Chris@16
|
174 return val+(alignment - val%alignment)%alignment;
|
Chris@16
|
175 }
|
Chris@16
|
176
|
Chris@16
|
177 /// \brief Helper base class for pixel dereference adaptors.
|
Chris@16
|
178 /// \ingroup PixelDereferenceAdaptorModel
|
Chris@16
|
179 ///
|
Chris@16
|
180 template <typename ConstT, typename Value, typename Reference, typename ConstReference,
|
Chris@16
|
181 typename ArgType, typename ResultType, bool IsMutable>
|
Chris@16
|
182 struct deref_base : public std::unary_function<ArgType, ResultType> {
|
Chris@16
|
183 typedef ConstT const_t;
|
Chris@16
|
184 typedef Value value_type;
|
Chris@16
|
185 typedef Reference reference;
|
Chris@16
|
186 typedef ConstReference const_reference;
|
Chris@16
|
187 BOOST_STATIC_CONSTANT(bool, is_mutable = IsMutable);
|
Chris@16
|
188 };
|
Chris@16
|
189
|
Chris@16
|
190 /// \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
|
191 /// \ingroup PixelDereferenceAdaptorModel
|
Chris@16
|
192 ///
|
Chris@16
|
193 template <typename D1, typename D2>
|
Chris@16
|
194 class deref_compose : public deref_base<
|
Chris@16
|
195 deref_compose<typename D1::const_t, typename D2::const_t>,
|
Chris@16
|
196 typename D1::value_type, typename D1::reference, typename D1::const_reference,
|
Chris@16
|
197 typename D2::argument_type, typename D1::result_type, D1::is_mutable && D2::is_mutable>
|
Chris@16
|
198 {
|
Chris@16
|
199 public:
|
Chris@16
|
200 D1 _fn1;
|
Chris@16
|
201 D2 _fn2;
|
Chris@16
|
202
|
Chris@16
|
203 typedef typename D2::argument_type argument_type;
|
Chris@16
|
204 typedef typename D1::result_type result_type;
|
Chris@16
|
205
|
Chris@16
|
206 deref_compose() {}
|
Chris@16
|
207 deref_compose(const D1& x, const D2& y) : _fn1(x), _fn2(y) {}
|
Chris@16
|
208 deref_compose(const deref_compose& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {}
|
Chris@16
|
209 template <typename _D1, typename _D2> deref_compose(const deref_compose<_D1,_D2>& dc) : _fn1(dc._fn1), _fn2(dc._fn2) {}
|
Chris@16
|
210
|
Chris@16
|
211 result_type operator()(argument_type x) const { return _fn1(_fn2(x)); }
|
Chris@16
|
212 result_type operator()(argument_type x) { return _fn1(_fn2(x)); }
|
Chris@16
|
213 };
|
Chris@16
|
214
|
Chris@16
|
215 // reinterpret_cast is implementation-defined. Static cast is not.
|
Chris@16
|
216 template <typename OutPtr, typename In> GIL_FORCEINLINE
|
Chris@16
|
217 OutPtr gil_reinterpret_cast( In* p) { return static_cast<OutPtr>(static_cast<void*>(p)); }
|
Chris@16
|
218
|
Chris@16
|
219 template <typename OutPtr, typename In> GIL_FORCEINLINE
|
Chris@16
|
220 const OutPtr gil_reinterpret_cast_c(const In* p) { return static_cast<const OutPtr>(static_cast<const void*>(p)); }
|
Chris@16
|
221
|
Chris@16
|
222 namespace detail {
|
Chris@16
|
223
|
Chris@16
|
224 ////////////////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
225 ///
|
Chris@16
|
226 /// \brief copy_n taken from SGI STL.
|
Chris@16
|
227 ///
|
Chris@16
|
228 ////////////////////////////////////////////////////////////////////////////////////////
|
Chris@16
|
229
|
Chris@16
|
230 template <class InputIter, class Size, class OutputIter>
|
Chris@16
|
231 std::pair<InputIter, OutputIter> _copy_n(InputIter first, Size count,
|
Chris@16
|
232 OutputIter result,
|
Chris@16
|
233 std::input_iterator_tag) {
|
Chris@16
|
234 for ( ; count > 0; --count) {
|
Chris@16
|
235 *result = *first;
|
Chris@16
|
236 ++first;
|
Chris@16
|
237 ++result;
|
Chris@16
|
238 }
|
Chris@16
|
239 return std::pair<InputIter, OutputIter>(first, result);
|
Chris@16
|
240 }
|
Chris@16
|
241
|
Chris@16
|
242 template <class RAIter, class Size, class OutputIter>
|
Chris@16
|
243 inline std::pair<RAIter, OutputIter>
|
Chris@16
|
244 _copy_n(RAIter first, Size count, OutputIter result, std::random_access_iterator_tag) {
|
Chris@16
|
245 RAIter last = first + count;
|
Chris@16
|
246 return std::pair<RAIter, OutputIter>(last, std::copy(first, last, result));
|
Chris@16
|
247 }
|
Chris@16
|
248
|
Chris@16
|
249 template <class InputIter, class Size, class OutputIter>
|
Chris@16
|
250 inline std::pair<InputIter, OutputIter>
|
Chris@16
|
251 _copy_n(InputIter first, Size count, OutputIter result) {
|
Chris@16
|
252 return _copy_n(first, count, result, typename std::iterator_traits<InputIter>::iterator_category());
|
Chris@16
|
253 }
|
Chris@16
|
254
|
Chris@16
|
255 template <class InputIter, class Size, class OutputIter>
|
Chris@16
|
256 inline std::pair<InputIter, OutputIter>
|
Chris@16
|
257 copy_n(InputIter first, Size count, OutputIter result) {
|
Chris@16
|
258 return detail::_copy_n(first, count, result);
|
Chris@16
|
259 }
|
Chris@16
|
260
|
Chris@16
|
261 /// \brief identity taken from SGI STL.
|
Chris@16
|
262 template <typename T>
|
Chris@16
|
263 struct identity : public std::unary_function<T,T> {
|
Chris@16
|
264 const T& operator()(const T& val) const { return val; }
|
Chris@16
|
265 };
|
Chris@16
|
266
|
Chris@16
|
267 /*************************************************************************************************/
|
Chris@16
|
268
|
Chris@16
|
269 /// \brief plus function object whose arguments may be of different type.
|
Chris@16
|
270 template <typename T1, typename T2>
|
Chris@16
|
271 struct plus_asymmetric : public std::binary_function<T1,T2,T1> {
|
Chris@16
|
272 T1 operator()(T1 f1, T2 f2) const {
|
Chris@16
|
273 return f1+f2;
|
Chris@16
|
274 }
|
Chris@16
|
275 };
|
Chris@16
|
276
|
Chris@16
|
277 /*************************************************************************************************/
|
Chris@16
|
278
|
Chris@16
|
279 /// \brief operator++ wrapped in a function object
|
Chris@16
|
280 template <typename T>
|
Chris@16
|
281 struct inc : public std::unary_function<T,T> {
|
Chris@16
|
282 T operator()(T x) const { return ++x; }
|
Chris@16
|
283 };
|
Chris@16
|
284
|
Chris@16
|
285 /*************************************************************************************************/
|
Chris@16
|
286
|
Chris@16
|
287 /// \brief operator-- wrapped in a function object
|
Chris@16
|
288 template <typename T>
|
Chris@16
|
289 struct dec : public std::unary_function<T,T> {
|
Chris@16
|
290 T operator()(T x) const { return --x; }
|
Chris@16
|
291 };
|
Chris@16
|
292
|
Chris@16
|
293 /// \brief Returns the index corresponding to the first occurrance of a given given type in
|
Chris@16
|
294 // a given MPL RandomAccessSequence (or size if the type is not present)
|
Chris@16
|
295 template <typename Types, typename T>
|
Chris@16
|
296 struct type_to_index
|
Chris@16
|
297 : public mpl::distance<typename mpl::begin<Types>::type,
|
Chris@16
|
298 typename mpl::find<Types,T>::type>::type {};
|
Chris@16
|
299 } // namespace detail
|
Chris@16
|
300
|
Chris@16
|
301
|
Chris@16
|
302
|
Chris@16
|
303 /// \ingroup ColorSpaceAndLayoutModel
|
Chris@16
|
304 /// \brief Represents a color space and ordering of channels in memory
|
Chris@16
|
305 template <typename ColorSpace, typename ChannelMapping = mpl::range_c<int,0,mpl::size<ColorSpace>::value> >
|
Chris@16
|
306 struct layout {
|
Chris@16
|
307 typedef ColorSpace color_space_t;
|
Chris@16
|
308 typedef ChannelMapping channel_mapping_t;
|
Chris@16
|
309 };
|
Chris@16
|
310
|
Chris@16
|
311 /// \brief A version of swap that also works with reference proxy objects
|
Chris@16
|
312 template <typename Value, typename T1, typename T2> // where value_type<T1> == value_type<T2> == Value
|
Chris@16
|
313 void swap_proxy(T1& left, T2& right) {
|
Chris@16
|
314 Value tmp = left;
|
Chris@16
|
315 left = right;
|
Chris@16
|
316 right = tmp;
|
Chris@16
|
317 }
|
Chris@16
|
318
|
Chris@16
|
319 /// \brief Run-time detection of whether the underlying architecture is little endian
|
Chris@16
|
320 inline bool little_endian() {
|
Chris@16
|
321 short tester = 0x0001;
|
Chris@16
|
322 return *(char*)&tester!=0;
|
Chris@16
|
323 }
|
Chris@16
|
324 /// \brief Run-time detection of whether the underlying architecture is big endian
|
Chris@16
|
325 inline bool big_endian() {
|
Chris@16
|
326 return !little_endian();
|
Chris@16
|
327 }
|
Chris@16
|
328
|
Chris@16
|
329 } } // namespace boost::gil
|
Chris@16
|
330
|
Chris@16
|
331 #endif
|