Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:37:00

0001 //
0002 // Copyright 2005-2007 Adobe Systems Incorporated
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 #ifndef BOOST_GIL_EXTENSION_NUMERIC_AFFINE_HPP
0009 #define BOOST_GIL_EXTENSION_NUMERIC_AFFINE_HPP
0010 
0011 #include <boost/gil/point.hpp>
0012 
0013 namespace boost { namespace gil {
0014 
0015 ////////////////////////////////////////////////////////////////////////////////////////
0016 ///
0017 /// Simple matrix to do 2D affine transformations. It is actually 3x3 but the last column is [0 0 1]
0018 ///
0019 ////////////////////////////////////////////////////////////////////////////////////////
0020 template <typename T>
0021 class matrix3x2 {
0022 public:
0023     matrix3x2() : a(1), b(0), c(0), d(1), e(0), f(0) {}
0024     matrix3x2(T A, T B, T C, T D, T E, T F) : a(A),b(B),c(C),d(D),e(E),f(F) {}
0025     matrix3x2(const matrix3x2& mat) : a(mat.a), b(mat.b), c(mat.c), d(mat.d), e(mat.e), f(mat.f) {}
0026     matrix3x2& operator=(const matrix3x2& m)           { a=m.a; b=m.b; c=m.c; d=m.d; e=m.e; f=m.f; return *this; }
0027 
0028     matrix3x2& operator*=(const matrix3x2& m)          { (*this) = (*this)*m; return *this; }
0029 
0030     static matrix3x2 get_rotate(T rads)                { T c=std::cos(rads); T s=std::sin(rads); return matrix3x2(c,s,-s,c,0,0); }
0031     static matrix3x2 get_translate(point<T> const& t)
0032     {
0033         return matrix3x2(1, 0, 0, 1, t.x, t.y);
0034     }
0035     static matrix3x2 get_translate(T x, T y)           { return matrix3x2(1  ,0,0,1  ,x,  y  ); }
0036     static matrix3x2 get_scale(point<T> const& s)
0037     {
0038         return matrix3x2(s.x, 0, 0, s.y, 0, 0);
0039     }
0040     static matrix3x2 get_scale(T x, T y)           { return matrix3x2(x,  0,0,y,  0  ,0  ); }
0041     static matrix3x2 get_scale(T s)                { return matrix3x2(s  ,0,0,s  ,0  ,0  ); }
0042 
0043     T a,b,c,d,e,f;
0044 };
0045 
0046 template <typename T> BOOST_FORCEINLINE
0047 matrix3x2<T> operator*(const matrix3x2<T>& m1, const matrix3x2<T>& m2) {
0048     return matrix3x2<T>(
0049                 m1.a * m2.a + m1.b * m2.c,
0050                 m1.a * m2.b + m1.b * m2.d,
0051                 m1.c * m2.a + m1.d * m2.c,
0052                 m1.c * m2.b + m1.d * m2.d,
0053                 m1.e * m2.a + m1.f * m2.c + m2.e,
0054                 m1.e * m2.b + m1.f * m2.d + m2.f );
0055 }
0056 
0057 template <typename T, typename F>
0058 BOOST_FORCEINLINE
0059 point<F> operator*(point<T> const& p, matrix3x2<F> const& m)
0060 {
0061     return { m.a*p.x + m.c*p.y + m.e, m.b*p.x + m.d*p.y + m.f };
0062 }
0063 
0064 ////////////////////////////////////////////////////////////////////////////////////////
0065 /// Define affine mapping that transforms the source coordinates by the affine transformation
0066 ////////////////////////////////////////////////////////////////////////////////////////
0067 /*
0068 template <typename MapFn>
0069 concept MappingFunctionConcept {
0070     typename mapping_traits<MapFn>::result_type;   where PointNDConcept<result_type>;
0071 
0072     template <typename Domain> { where PointNDConcept<Domain> }
0073     result_type transform(MapFn&, const Domain& src);
0074 };
0075 */
0076 
0077 template <typename T> struct mapping_traits;
0078 
0079 template <typename F>
0080 struct mapping_traits<matrix3x2<F>>
0081 {
0082     using result_type =  point<F>;
0083 };
0084 
0085 template <typename F, typename F2>
0086 BOOST_FORCEINLINE
0087 point<F> transform(matrix3x2<F> const& mat, point<F2> const& src)
0088 {
0089     return src * mat;
0090 }
0091 
0092 /// Returns the inverse of the given affine transformation matrix
0093 ///
0094 /// \warning Floating point arithmetic, use Boost.Rational if precision maters
0095 template <typename T>
0096 boost::gil::matrix3x2<T> inverse(boost::gil::matrix3x2<T> m)
0097 {
0098     T const determinant = m.a * m.d - m.b * m.c;
0099 
0100     boost::gil::matrix3x2<T> res;
0101     res.a = m.d / determinant;
0102     res.b = -m.b / determinant;
0103     res.c = -m.c / determinant;
0104     res.d = m.a / determinant;
0105     res.e = (m.c * m.f - m.d * m.e) / determinant;
0106     res.f = (m.b * m.e - m.a * m.f) / determinant;
0107 
0108     return res;
0109 }
0110 
0111 /// \fn gil::matrix3x2 center_rotate
0112 /// \tparam T     Data type for source image dimensions
0113 /// \tparam F     Data type for angle through which image is to be rotated
0114 /// @param  dims  dimensions of source image
0115 /// @param  rads  angle through which image is to be rotated
0116 /// @return   A transformation matrix for rotating the source image about its center
0117 /// \brief    rotates an image from its center point
0118 ///           using consecutive affine transformations.
0119 template<typename T, typename F>
0120 boost::gil::matrix3x2<F> center_rotate(boost::gil::point<T> dims,F rads)
0121 {
0122     const F PI = F(3.141592653589793238);
0123     const F c_theta = std::abs(std::cos(rads));
0124     const F s_theta = std::abs(std::sin(rads));
0125 
0126     // Bound checks for angle rads
0127     while(rads + PI < 0)
0128     {
0129         rads = rads + PI;
0130     }
0131 
0132     while(rads > PI)
0133     {
0134         rads = rads - PI;
0135     }
0136 
0137     // Basic Rotation Matrix
0138     boost::gil::matrix3x2<F> rotate = boost::gil::matrix3x2<F>::get_rotate(rads);
0139 
0140     // Find distance for translating the image into view
0141     boost::gil::matrix3x2<F> translation(0,0,0,0,0,0);
0142     if(rads > 0)
0143     {
0144         translation.b = s_theta;
0145     }
0146     else
0147     {
0148         translation.c = s_theta;
0149     }
0150 
0151     if(std::abs(rads) > PI/2)
0152     {
0153         translation.a = c_theta;
0154         translation.d = c_theta;
0155     }
0156 
0157     // To bring the complete image into view
0158     boost::gil::matrix3x2<F> translate =
0159         boost::gil::matrix3x2<F>::get_translate(-1 * dims * translation);
0160 
0161     // To fit inside the source dimensions
0162     boost::gil::matrix3x2<F> scale =
0163         boost::gil::matrix3x2<F>::get_scale(
0164             s_theta * dims.y / dims.x + c_theta ,
0165             s_theta * dims.x / dims.y + c_theta
0166         );
0167 
0168     return scale *  translate * rotate;
0169 }
0170 
0171 }} // namespace boost::gil
0172 
0173 #endif