import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class RotateImage {

    /**
     * <a href="https://stackoverflow.com/questions/37758061/rotate-a-buffered-image-in-java">link</a>
     *
     * @param image - input image
     * @param angle - angle in degrees
     * @return - input image rotated by angle
     */
    public static BufferedImage rotateImageByDegrees(BufferedImage image, double angle)
    {
        double rads = Math.toRadians(angle);
        double sin = Math.abs(Math.sin(rads));
        double cos = Math.abs(Math.cos(rads));
        int width = image.getWidth();
        int height = image.getHeight();
        int newWidth = (int) Math.floor(width * cos + height * sin);
        int newHeight = (int) Math.floor(height * cos + width * sin);

        BufferedImage rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = rotated.createGraphics();
        AffineTransform transform = new AffineTransform();
        transform.translate((newWidth - width) / 2.0, (newHeight - height) / 2.0);

        int x = width / 2;
        int y = height / 2;

        transform.rotate(rads, x, y);
        g.setTransform(transform);
        g.drawImage(image, 0, 0, null);
        g.setColor(Color.RED);
        g.drawRect(0, 0, newWidth - 1, newHeight - 1);
        g.dispose();

        return rotated;
    }

    public static void main(String[] args) throws IOException
    {
        BufferedImage inputImage = ImageIO.read(new File("input_image.jpg"));
        BufferedImage outputImage = RotateImage.rotateImageByDegrees(inputImage, 45);
        ImageIO.write(outputImage, "jpg", new File("output_image.jpg"));
    }
}
