Skip to content

Commit

Permalink
Rotation of image by any arbitrary angle from its center (#565)
Browse files Browse the repository at this point in the history
* basic rotation function for theta between +/- 180 deg
* added scaling matrix for same dimensions and added bound checks for theta
  • Loading branch information
gkumar28 committed Mar 9, 2021
1 parent 745d033 commit 392ac49
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
62 changes: 61 additions & 1 deletion include/boost/gil/extension/numeric/affine.hpp
Expand Up @@ -108,6 +108,66 @@ boost::gil::matrix3x2<T> inverse(boost::gil::matrix3x2<T> m)
return res;
}

/// \fn gil::matrix3x2 center_rotate
/// \tparam T Data type for source image dimensions
/// \tparam F Data type for angle through which image is to be rotated
/// @param dims dimensions of source image
/// @param rads angle through which image is to be rotated
/// @return A transformation matrix for rotating the source image about its center
/// \brief rotates an image from its center point
/// using consecutive affine transformations.
template<typename T, typename F>
boost::gil::matrix3x2<F> center_rotate(boost::gil::point<T> dims,F rads)
{
const F PI = F(3.141592653589793238);
const F c_theta = std::abs(std::cos(rads));
const F s_theta = std::abs(std::sin(rads));

// Bound checks for angle rads
while(rads + PI < 0)
{
rads = rads + PI;
}

while(rads > PI)
{
rads = rads - PI;
}

// Basic Rotation Matrix
boost::gil::matrix3x2<F> rotate = boost::gil::matrix3x2<F>::get_rotate(rads);

// Find distance for translating the image into view
boost::gil::matrix3x2<F> translation(0,0,0,0,0,0);
if(rads > 0)
{
translation.b = s_theta;
}
else
{
translation.c = s_theta;
}

if(std::abs(rads) > PI/2)
{
translation.a = c_theta;
translation.d = c_theta;
}

// To bring the complete image into view
boost::gil::matrix3x2<F> translate =
boost::gil::matrix3x2<F>::get_translate(-1 * dims * translation);

// To fit inside the source dimensions
boost::gil::matrix3x2<F> scale =
boost::gil::matrix3x2<F>::get_scale(
s_theta * dims.y / dims.x + c_theta ,
s_theta * dims.x / dims.y + c_theta
);

return scale * translate * rotate;
}

}} // namespace boost::gil

#endif
#endif
16 changes: 16 additions & 0 deletions test/extension/numeric/matrix3x2.cpp
Expand Up @@ -201,6 +201,21 @@ void test_matrix3x2_inverse()
BOOST_TEST_WITH(p.y, p2.y, with_tolerance<double>(1e-9));
}

void test_matrix3x2_center_rotate()
{
gil::point<double> dimension(100.0,100.0);
gil::matrix3x2<double> m1;

m1 = gil::center_rotate(dimension, HALF_PI);

BOOST_TEST_WITH(m1.a , std::cos(HALF_PI) , with_tolerance<double>(1e-9));
BOOST_TEST_EQ (m1.b , 1);
BOOST_TEST_EQ (m1.c , -1);
BOOST_TEST_WITH(m1.d , std::cos(HALF_PI) , with_tolerance<double>(1e-9));
BOOST_TEST_EQ (m1.e , 100);
BOOST_TEST_WITH(m1.f , std::cos(HALF_PI) , with_tolerance<double>(1e-9));
}

int main()
{
test_matrix3x2_default_constructor();
Expand All @@ -215,6 +230,7 @@ int main()
test_matrix3x2_get_translate();
test_matrix3x2_transform();
test_matrix3x2_inverse();
test_matrix3x2_center_rotate();

return ::boost::report_errors();
}

0 comments on commit 392ac49

Please sign in to comment.