Rotate image in memory by an arbitrary angle

Today I stumbled over a question which answer seemed to be easy: How to rotate an image in memory by an arbitrary angle? I had to find out that most examples out there are only for square images, rotations in 90 degree steps or are simply not working at all. It looks like most code snippets were copied from one to another without ever testing it!

This bothered me so much, that I sat down and worked out an example that really works.

It rotates an image by an arbitrary angle in degrees, with positive values to rotate clockwise and negative values to rotate counterclockwise.

The tricky part was to calculate the new image size, that fits exactly (well, as exactly as Java’s double can) the rotated image.

So, here it is:

	/**
	 * Rotates an image by an arbitrary amount of degrees around its center. A
	 * positive value for <code>degrees</code> will rotate the image clockwise,
	 * a negative value counterclockwise. An image will be returned with a size
	 * that exactly fits the rotated image.
	 * 
	 * @param src
	 *            The source image to rotate.
	 * @param degrees
	 *            The amount in degrees to rotate, a positive value rotates
	 *            clockwise, a negative counterclockwise.
	 * @return A new <code>BufferdImage</code> with a new size that exactly fits
	 *         the rotated image.
	 */
	public static BufferedImage rotateImage(BufferedImage src, double degrees) {
		double radians = Math.toRadians(degrees);

		int srcWidth = src.getWidth();
		int srcHeight = src.getHeight();

		double sin = Math.abs(Math.sin(radians));
		double cos = Math.abs(Math.cos(radians));
		int newWidth = (int) Math.floor(srcWidth * cos + srcHeight * sin);
		int newHeight = (int) Math.floor(srcHeight * cos + srcWidth * sin);

		BufferedImage result = new BufferedImage(newWidth, newHeight,
				src.getType());
		Graphics2D g = result.createGraphics();
		g.translate((newWidth - srcWidth) / 2, (newHeight - srcHeight) / 2);
		g.rotate(radians, srcWidth / 2, srcHeight / 2);
		g.drawRenderedImage(src, null);

		return result;
	}
Advertisements
%d bloggers like this: