在 Java 中旋轉影象

Rupam Yadav 2023年1月30日 2021年10月2日
  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 javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

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 javax.imageio.ImageIO;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;

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 中旋轉影象 - 逆時針旋轉影象

Author: 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