I'm trying to rotate the image around a reference point in Java using BufferedImage and AffineTransform, at first it seemed exactly what I needed, but it turns out it doesn't behave as expected. I need to do some rudimentary rotations, in multiples of 90, so I tried to do getQuadrantRotateInstance
, but, if the reference point is at 0,0 then I get a RasterFormatException: Transformed height (0) is less than or equal to 0.
var rotation = switch (transform) {
case TRANS_NONE -> 0;
case TRANS_ROT90 -> 1;
case TRANS_ROT180 -> 2;
case TRANS_ROT270 -> 3;
default -> throw new NotImplementedException();
};
var transform = AffineTransform.getQuadrantRotateInstance(rotation, referenceX, referenceY);
var operation = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
var rotated = operation.filter(source, null);
By the looks of it the image gets rotated out of the canvas (into negative coordinates), resulting in exception above.
What would be the proper solution to create a rotated variant of the image without cropping or rotating around a center point like existing solutions do?
Rotating an image by an angle around the center point:
private BufferedImage rotateImage(BufferedImage buffImage, double angle) {
double radian = Math.toRadians(angle);
double sin = Math.abs(Math.sin(radian));
double cos = Math.abs(Math.cos(radian));
int width = buffImage.getWidth();
int height = buffImage.getHeight();
int nWidth = (int) Math.floor((double) width * cos + (double) height * sin);
int nHeight = (int) Math.floor((double) height * cos + (double) width * sin);
BufferedImage rotatedImage = new BufferedImage(nWidth, nHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = rotatedImage.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
graphics.translate((nWidth - width) / 2, (nHeight - height) / 2);
// This is the rotation around the center point - change this line
graphics.rotate(radian, (double) (width / 2), (double) (height / 2));
graphics.drawImage(buffImage, 0, 0, null);
graphics.dispose();
return rotatedImage;
}
To change the origin point of the rotation see javadoc
of the method rotate.
Source: Creating simple captcha.