Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I rotate an image?

See also: Why is my image rotation algorithm not working?

This question isn't language specific, and is a math problem. I will however use some C++ code to explain what I need as I'm not too hot on math.

Here's how the image is composed:

ImageMatrix image;
image[0][0][0] = 1;
image[0][1][0] = 2;
image[0][2][0] = 1;
image[1][0][0] = 0;
image[1][1][0] = 0;
image[1][2][0] = 0;
image[2][0][0] = -1;
image[2][1][0] = -2;
image[2][2][0] = -1;

Here's the prototype for the function I'm trying to create:

ImageMatrix rotateImage(ImageMatrix image, double angle);

I'd like to rotate only the first two indices (rows and columns) but not the channel.

like image 666
Nick Bolton Avatar asked Mar 29 '09 18:03

Nick Bolton


3 Answers

The usual way to solve this is by doing it backwards. Instead of calculating where each pixel in the input image ends up in the output image, you calculate where each pixel in the output image is located in the input image (by rotationg the same amount in the other direction. This way you can be sure that all pixels in the output image will have a value.

output = new Image(input.size())

for each pixel in input:
{
  p2 = rotate(pixel, -angle);
  value = interpolate(input, p2)
  output(pixel) = value
}

There are different ways to do interpolation. For the formula of rotation I think you should check https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions

But just to be nice, here it is (rotation of point (x,y) angle degrees/radians):

 newX = cos(angle)*x - sin(angle)*y
 newY = sin(angle)*x + cos(angle)*y
like image 85
Hannes Ovrén Avatar answered Nov 15 '22 11:11

Hannes Ovrén


To rotate an image, you create 3 points:

A----B 
|
|
C

and rotate that around A. To get the new rotated image you do this:

  • rotate ABC around A in 2D, so this is a single euler rotation
  • traverse in the rotated state from A to B. For every pixel you traverse also from left to right over the horizontal line in the original image. So if the image is an image of width 100, height 50, you'll traverse from A to B in 100 steps and from A to C in 50 steps, drawing 50 lines of 100 pixels in the area formed by ABC in their rotated state.

This might sound complicated but it's not. Please see this C# code I wrote some time ago: rotoZoomer by me

When drawing, I alter the source pointers a bit to get a rubber-like effect, but if you disable that, you'll see the code rotates the image without problems. Of course, on some angles you'll get an image which looks slightly distorted. The sourcecode contains comments what's going on so you should be able to grab the math/logic behind it easily.

If you like Java better, I also have made a java version once, 14 or so years ago ;) -> http://www.xs4all.nl/~perseus/zoom/zoom.java

like image 24
Frans Bouma Avatar answered Nov 15 '22 12:11

Frans Bouma


Note there's another solution apart from rotation matrices, that doesn't loose image information through aliasing. You can separate 2D image rotation into skews and scalings, which preserve the image quality.

Here's a simpler explanation

like image 2
heeen Avatar answered Nov 15 '22 10:11

heeen