How to Rotate an Image Using Affine Transform in Java

Java awt package contains a number of classes for image processing. AffineTransform class can be used for a number of 2D graphics processing requirements. The following Java source code demonstrates the use of AffineTransform to perform 90 degree image rotations. This example preserves the full image after the rotation. If you use the following code for arbitrary rotations, the image may be cut off.

How to Rotate an Image Using Affine Transform in Java

For 90 degree rotations program sets the new image width to the height of the old image and the new image height to the width of the old image. Since the rotation anchor point is is the center of the image, we move the image (using translate transform) depending on whether we rotate clockwise or counter clockwise.

For performing arbitrary rotations, new image dimensions and translation requires mathematical calculations.

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

// Rotates an image 90 degrees clockwise/counter clockwise using AffineTransform in Java
// Preserves the full image.
public class ImageRotationDemo {
    private static final String PATH_TO_IMAGE="/Users/jj/";
    private static final String INPUT_FILE_NAME="input.png";
    private static final String OUTPUT_FILE_NAME = "output.png";
    
    public static void main(String[] args ) throws Exception{
        ImageRotationDemo demo = new ImageRotationDemo();
        demo.rotateImage();
    }

    private void rotateImage() throws Exception {
        BufferedImage source = ImageIO.read(new File(PATH_TO_IMAGE+INPUT_FILE_NAME));
        
        BufferedImage output = new BufferedImage(source.getHeight(), source.getWidth(), source.getType());
           
        AffineTransformOp op = new AffineTransformOp(rotateCounterClockwise90(source), AffineTransformOp.TYPE_BILINEAR);
        op.filter(source, output);

        ImageIO.write(output, "png", new File(PATH_TO_IMAGE+OUTPUT_FILE_NAME));
        
    }
    
    // Rotates clockwise 90 degrees. Uses rotation on center and then translating it to origin
    private AffineTransform rotateClockwise90(BufferedImage source) {
        AffineTransform transform = new AffineTransform();
        transform.rotate(Math.PI/2, source.getWidth()/2, source.getHeight()/2);
        double offset = (source.getWidth()-source.getHeight())/2;
        transform.translate(offset,offset);
        return transform;
    }
    
    // Rotates counter clockwise 90 degrees. Uses rotation on center and then translating it to origin
    private AffineTransform rotateCounterClockwise90(BufferedImage source) {
        AffineTransform transform = new AffineTransform();
        transform.rotate(-Math.PI/2, source.getWidth()/2, source.getHeight()/2);
        double offset = (source.getWidth()-source.getHeight())/2;
        transform.translate(-offset,-offset);
        return transform;
    }
    
}