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

source code of boost/boost/gil/utilities.hpp