Rotate BufferedImage in Java

Simple method that correctly rotates a BufferedImage.

The code you find on the web usually has lots of bugs:

  • Does not create image of correct size.
  • Does not use correct offset.
  • Unnecessarily rotates by .
  • Does not work for negative angles (e.g. -90°).
  • Does not consider BufferedImage.TYPE_CUSTOM.
  • Does not dispose Graphics2D.

Or it just doesn’t work. Mine is tested and works fine. Some are overly complicated using AffineTransform. That works, but is not necessary. Then there are methods that allow to rotate at any angle, while mine only works for multiples of 90°. It also automatically returns the original image if rotation is a multiple of 360° (including 0°).

Obviously, you should use an Enum for the angle, so that it is clear what angles are actually supported but I tried to keep it simple. This also has the advantage that you can use -90 instead of 270. Feel free to change the code when you use it.

The Code:
package ch.claude_martin.foo;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class SomeClass {
	public static void main(String[] args) throws IOException {
		var input = "C:/picture.jpg";
		var output = "C:/rotated_picture.jpg";
		var img = ImageIO.read(new File(input));
		var rotated = rotateBufferedImage(img, -90);
		ImageIO.write(rotated, "jpg", new File(output));
	}

	/**
	 * Rotates an image. Note that an angle of -90 is equal to 270.
	 * 
	 * @param img   The image to be rotated
	 * @param angle The angle in degrees (must be a multiple of 90°).
	 * @return The rotated image, or the original image, if the effective angle is
	 *         0°.
	 */
	public static BufferedImage rotateBufferedImage(BufferedImage img, int angle) {
		if (angle < 0) {
			angle = 360 + (angle % 360);
		}
		if ((angle %= 360) == 0) {
			return img;
		}
		final boolean r180 = angle == 180;
		if (angle != 90 && !r180 && angle != 270)
			throw new IllegalArgumentException("Invalid angle.");
		final int w = r180 ? img.getWidth() : img.getHeight();
		final int h = r180 ? img.getHeight() : img.getWidth();
		final int type = img.getType() == BufferedImage.TYPE_CUSTOM ? BufferedImage.TYPE_INT_ARGB : img.getType();
		final BufferedImage rotated = new BufferedImage(w, h, type);
		final Graphics2D graphic = rotated.createGraphics();
		graphic.rotate(Math.toRadians(angle), w / 2d, h / 2d);
		final int offset = r180 ? 0 : (w - h) / 2;
		graphic.drawImage(img, null, offset, -offset);
		graphic.dispose();
		return rotated;
	}

}
Code on Pastebin:

https://pastebin.com/SnKS7kip

My first inline class for Java

I’ve once made a simple helper class for a set of bytes stored as an integer bitfield. So the idea is that each of the 32bits is used to represent if the ordinal number is in the set or not. This only works for the bytes 0 to 31.
Now this is an “inline class” – something we will get with Project Valhalla.
Here’s the branch of my project:
https://github.com/claudemartin/smallset/tree/valhalla

For this to work you need a JDK with a preview of Project Valhalla. Check java.net for that: http://jdk.java.net/valhalla/

Just download that JDK, clone my branch, build using Ant, and see what you can do with it. It’s actually a good example of an inline class, because it is just an integer (primitive) value but has methods (like a referenced type would). It doesn’t need object identity, but should still behave like an object. For example the sets are comparable. The type actually implements the Comparable interface.

Note that this might not work with newer JDKs. I used JDK 14 + valhalla from java.net and the feature might look quite different in newer releases of Java.

Java Assignments are evaluated Left to Right

I think I’ve just found a mistake in the Java Tutorial.

Maybe I’m just being pedantic, but I think I’ve just found a mistake in the Java Tutorial. It claims:

All binary operators except for the assignment operators are evaluated from left to right; assignment operators are evaluated right to left.

The Java™ Tutorials » Language Basics » Operators

What is this supposed to mean? Evaluation from right to left would mean that when you have a line like the following you get the rightmost expression evaluated first:

int x = 42;
x += getNumber();
// The above would be equivalent to:
x = getNumber() + x;

But that’s not how Java actually evaluates this expression. And the JLS 12 (2019-02-08) clearly states in 15.26.2 that “the value of the left-hand operand is saved and then the right-hand operand is evaluated.”

Continue reading “Java Assignments are evaluated Left to Right”

Is Java easy?

Java isn’t easy. It’s often more complex than needed. But being easy for beginners shouldn’t be a design goal with high priority.

Should a programming language be easy?

I don’t know why so many educational establishments use Java to teach programming. They often start with Java in the first semester. Even the Oracle tutorials expect the reader to already know some basics.  Java was designed for programmers who already know C/C++ as seen in this example.

The main method is similar to the main function in C and C++; it’s the entry point for your application and will subsequently invoke all the other methods required by your program. [Lesson: A Closer Look at the “Hello World!” Application]

Continue reading “Is Java easy?”

Recursive FizzBuzz

FizzBuzz in two lines of code.

The only import you need is one for System.out:

import static java.lang.System.out;

Simple two-liner:

static void f(int a, int z) {
	out.println(a % 15 < 1 ? "FizzBuzz" : a % 3 < 1 ? "Fizz" : a % 5 < 1 ? "Buzz" : a);
	if (a < z) f(1 + a, z);
}

Without using the literal “FizzBuzz”:

static void g(int a, int z) {
  int x = 0;
  if (a % 3 < 1) { out.print("Fizz"); ++x; }
  if (a % 5 < 1) { out.print("Buzz"); ++x; }
  if (x < 1) out.print(a);
  out.println();
  if (a < z) g(1 + a, z);
}

Note that I use x<1 instead of x==0 to save a single character.