在 Java 中旋转图像

Rupam Yadav 2023年10月12日
  1. 在 Java 中使用 BufferedImageGraphics2D.rotate() 旋转图像
  2. 在 Java 中使用仿射变换旋转图像
在 Java 中旋转图像

本文将介绍我们如何使用两种原生方式在 Java 中旋转图像。

在 Java 中使用 BufferedImageGraphics2D.rotate() 旋转图像

第一种旋转图像的方法包括使用 AWT 包附带的 BufferedImageGraphics2d 类。下面我们创建一个函数 rotateImage(),它接收一个 BufferedImage 对象作为参数并返回一个旋转的 BufferedImage 对象。

rotateImage() 中,我们使用 getWidth()getHeight()getType() 方法获取图像的宽度、高度和类型。现在我们调用 BufferedImage() 构造函数并将三个变量作为参数传递,它返回一个 BufferedImage 对象 newImageFromBuffer

我们使用 createGraphics() 方法创建新的旋转图像,该方法返回一个 Graphics2D 对象 graphics2D。使用这个对象,我们调用带有三个参数的 rotate() 函数;第一个是旋转图像的角度,因为我们想要将它旋转 90 度,我们通过 Math.radians(90),第二个和第三个参数是 x 和 y 坐标。

最后,我们调用 graphics2D.drawImage() 来绘制旋转图像,它有四个参数,即 BufferedImage 对象、要应用的过滤器以及 x 和 y 坐标。然后我们返回 newImageFromBuffer 对象。

main 函数中,我们使用 File 读取文件,然后使用 ImageIO.read() 将其转换为 BufferedImage 对象。现在我们调用 rotateImage() 函数并传递返回的 BufferedImage 对象并存储旋转后的 BufferedImage 对象。现在我们有了旋转的图像,我们需要使用 FileImageIO.write() 创建一个新文件来存储它,该文件采用 BufferedImage 对象,其扩展名是空文件的位置。

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

public class RotateImage {
  public static BufferedImage rotateImage(BufferedImage imageToRotate) {
    int widthOfImage = imageToRotate.getWidth();
    int heightOfImage = imageToRotate.getHeight();
    int typeOfImage = imageToRotate.getType();

    BufferedImage newImageFromBuffer = new BufferedImage(widthOfImage, heightOfImage, typeOfImage);

    Graphics2D graphics2D = newImageFromBuffer.createGraphics();

    graphics2D.rotate(Math.toRadians(90), widthOfImage / 2, heightOfImage / 2);
    graphics2D.drawImage(imageToRotate, null, 0, 0);

    return newImageFromBuffer;
  }

  public static void main(String[] args) {
    try {
      BufferedImage originalImage = ImageIO.read(new File("mountains.jpeg"));

      BufferedImage subImage = rotateImage(originalImage);

      File rotatedImageFile = new File("C:\\Users\\User1\\Documents\\mountainsRotated.jpeg");

      ImageIO.write(subImage, "jpg", rotatedImageFile);

      System.out.println("New Rotated Image File Path: " + rotatedImageFile.getPath());

    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

输出:

New Rotated Image File Path: C:\Users\User1\Documents\mountainsRotated.jpeg

原图:

在 java 中旋转图像 - 原始图像

旋转图像:

在 java 中旋转图像 - 旋转图像

在 Java 中使用仿射变换旋转图像

此示例使用 AffineTransform 类,该类将图像从其原始 2D 坐标线性映射到其他 2D 坐标,而不会损失原始质量。在下面的程序中,我们三个方法,一是读取和调用其他函数,二是顺时针旋转图像,最后一个函数是逆时针旋转图像。

rotateImage() 函数中,我们使用 new File() 读取图像,并使用 ImageIO.read() 将其转换为 BufferedImage 对象。然后我们创建另一个 BufferedImage 对象,该对象保留原始图像的属性并将其称为 output。接下来,我们调用 rotateImageClockWise() 方法并在其中传递原始 BufferedImage,该方法返回 AffineTransorm 类的对象。

rotateImageClockWise() 接收 image 并获取高度和宽度。我们创建一个 AffineTransform 对象 affineTransform 并使用它调用 rotate() 方法。在 rotate() 中,我们传递三个参数;第一个是以弧度为单位的旋转角度,这里我们传递 Math.PI / 2,最后两个参数是 x 和 y 坐标,它们是图像宽度和高度的一半。

现在,随着图像的旋转,我们使用 translate() 函数在新坐标中平移图像,该函数采用两个参数:x 方向旋转的距离和 y 方向旋转的距离。我们使用 (imageWidth - imageHeight) / 2 计算 x 和 y 参数。

要逆时针旋转图像,我们可以在 rotate() 中调用方法 rotateImageCounterClockwise() 而不是 rotateImageClockWise()

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

public class RotateImage {
  private static final String INPUT_FILE_NAME = "mountains.jpeg";
  private static final String OUTPUT_FILE_NAME = "mountainsRotated.jpeg";

  private AffineTransform rotateImageClockWise(BufferedImage image) {
    int imageWidth = image.getWidth();
    int imageHeight = image.getHeight();

    AffineTransform affineTransform = new AffineTransform();
    affineTransform.rotate(Math.PI / 2, imageWidth / 2, imageHeight / 2);

    double offset = (imageWidth - imageHeight) / 2;
    affineTransform.translate(offset, offset);
    return affineTransform;
  }

  private AffineTransform rotateImageCounterClockwise(BufferedImage image) {
    int imageWidth = image.getWidth();
    int imageHeight = image.getHeight();

    AffineTransform affineTransform = new AffineTransform();
    affineTransform.rotate(-Math.PI / 2, imageWidth / 2, imageHeight / 2);

    double offset = (imageWidth - imageHeight) / 2;
    affineTransform.translate(-offset, -offset);

    return affineTransform;
  }

  private void rotateImage() throws Exception {
    BufferedImage bufferedImage = ImageIO.read(new File(INPUT_FILE_NAME));

    BufferedImage output = new BufferedImage(
        bufferedImage.getHeight(), bufferedImage.getWidth(), bufferedImage.getType());

    AffineTransform affineTransform = rotateImageClockWise(bufferedImage);
    AffineTransformOp affineTransformOp =
        new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);
    affineTransformOp.filter(bufferedImage, output);

    ImageIO.write(output, "jpg", new File(OUTPUT_FILE_NAME));
  }

  public static void main(String[] args) {
    try {
      RotateImage rotateImage = new RotateImage();
      rotateImage.rotateImage();

    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

输出:

原图:

在 java 中旋转图像 - 原始图像

图像顺时针旋转:

在 java 中旋转图像 - 顺时针旋转图像

图像逆时针旋转:

在 java 中旋转图像 - 逆时针旋转图像

作者: Rupam Yadav
Rupam Yadav avatar Rupam Yadav avatar

Rupam Saini is an android developer, who also works sometimes as a web developer., He likes to read books and write about various things.

LinkedIn

相关文章 - Java Image