Search code examples
javaimagebufferedimage

Rotate BufferedImage


I'm following a textbook and have become stuck at a particular point.

This is a console application.

I have the following class with a rotate image method:

public class Rotate {
    public ColorImage rotateImage(ColorImage theImage) {
        int height = theImage.getHeight();
        int width = theImage.getWidth();
        //having to create new obj instance to aid with rotation
        ColorImage rotImage = new ColorImage(height, width);
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                Color pix = theImage.getPixel(x, y);
                rotImage.setPixel(height - y - 1, x, pix);
            }
        }
        //I want this to return theImage ideally so I can keep its state
        return rotImage;
    }
}

The rotation works, but I have to create a new ColorImage (class below) and this means I am creating a new object instance (rotImage) and losing the state of the object I pass in (theImage). Presently, it's not a big deal as ColorImage does not house much, but if I wanted it to house the state of, say, number of rotations it has had applied or a List of something I'm losing all that.

The class below is from the textbook.

public class ColorImage extends BufferedImage {
    public ColorImage(BufferedImage image) {
        super(image.getWidth(), image.getHeight(), TYPE_INT_RGB);
        int width = image.getWidth();
        int height = image.getHeight();
        for (int y = 0; y < height; y++)
            for (int x = 0; x < width; x++)
                setRGB(x, y, image.getRGB(x, y));
    }

    public ColorImage(int width, int height) {
        super(width, height, TYPE_INT_RGB);
    }

    public void setPixel(int x, int y, Color col) {
        int pixel = col.getRGB();
        setRGB(x, y, pixel);
    }

    public Color getPixel(int x, int y) {
        int pixel = getRGB(x, y);
        return new Color(pixel);
    }
}

My question is, how can I rotate the image I pass in so I can preserve its state?


Solution

  • Unless you limit yourself to square images or to 180° rotations, you need a new object, as the dimensions would have changed. The dimensions of a BufferedImage object, once created, are constant.

    If I wanted it to house the state of, say, number of rotations it has had applied or a List of something I'm losing all that

    You can create another class to hold that other information along with the ColorImage/BufferedImage, then limit the ColorImage/BufferedImage class itself to holding only the pixels. An example:

    class ImageWithInfo {
        Map<String, Object> properties; // meta information
        File file; // on-disk file that we loaded this image from
        ColorImage image; // pixels
    }
    

    Then you can replace the pixels object freely, while preserving the other state. It's often helpful to favor composition over inheritance. In brief that means, instead of extending a class, create a separate class that contains the original class as a field.

    Also note that the rotation implementation from your book seems to be mainly for learning purposes. It's fine for that, but will show its performance limitations if you manipulate very big images or for continuous graphics rotation at animation speeds.