Learning and Applying Mathematics using Computing

Image Rotation

This post is a quick diversion, on request from a user on the Greenfoot site. They asked how to rotate an image, which is actually quite a simple task, given what we have already covered about rotation and polar coordinates.

The idea behind rotating an image is this: create a new image, and go through every pixel on the new image. For that destination pixel, calculate a source position by rotating the position backwards. Then pick out that pixel from the original image, and use that colour to fill in the new pixel.

Assume you want to rotate an image clockwise by 140 degrees. You go through the pixels: for example, the coloured pixel on the new image on the left, below. To work out what colour to use, you convert the centre of that pixel into polar coordinates, relative to the centre of the image (assuming you want to rotate around the centre). Then subtract 140 degrees from the rotation, but keep the distance from the centre the same. Wherever this new coordinate is (once you’ve converted back to cartesian coordinates), use that pixel as the colour:

That leads to the following source code:

    public void rotateImage(int rotateBy)
    {
        GreenfootImage rotated = new GreenfootImage(original.getWidth(), original.getHeight());
        
        double centreX = (double)original.getWidth() / 2;
        double centreY = (double)original.getHeight() / 2;
        
        for (int x = 0; x < rotated.getWidth(); x++)
        {
            for (int y = 0; y < rotated.getHeight(); y++)
            {
                double dir = calculateDirection(x - centreX, y - centreY);
                double mag = calculateMagnitude(x - centreX, y - centreY);
                
                dir = dir - rotateBy;
                
                int origX = (int)(centreX + calculateX(dir, mag));
                int origY = (int)(centreY + calculateY(dir, mag));
                
                if (origX >= 0 && origX < original.getWidth() &&
                    origY >= 0 && origY < original.getHeight())
                {
                    rotated.setColorAt(x, y, original.getColorAt(origX, origY));
                }
            }
        }
        
        setImage(rotated);
    }

This is what is known as a nearest-neighbour rotation: for each pixel we are picking the single closest pixel to use as the colour. Better rotation algorithms (especially for small images) do a blend of pixels from the original image. But you can have a play with this simple image rotation code via the scenario on the Greenfoot site.

Exercises

Our image rotation isn’t perfect — here’s some challenge exercises for you to improve it:

  1. The image has its corners cut off when it is rotated. Think about why this is, and work out how large you need to make the destination image to avoid this ever happening (hint: the longest dimension across a rectangle is from one corner to the other)?
  2. Rather than make the image as large as possible, can you work out exactly how big it needs to be, given the degrees to rotate by?
  3. Currently the image rotates around the centre of the original. Can you modify the code to rotate around an arbitrary point in the original image? (Note: this will mess with the previous adjustments to make the destination image be large enough!)
  4. One way to make a swirl effect is to make the rotation amount proportional to the distance from the centre. Try it, and see if you can make images like this:

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 253 other followers