HOWTO · Java

在 Java 中旋转图像

这篇文章说明了如何在 Java 中旋转图像

本页内容

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

在 Java 中使用 BufferedImage 和 Graphics2D.rotate() 旋转图像

第一种旋转图像的方法包括使用 AWT 包附带的 BufferedImage 和 Graphics2d 类。下面我们创建一个函数 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 对象。现在我们有了旋转的图像,我们需要使用 File 和 ImageIO.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 中旋转图像 - 逆时针旋转图像