Почему вращение Affine на 90/270 градусов не сохраняет правильные размеры, а изменяет размеры ширины и высоты до того же размера в пикселях?

Что я пытаюсь сделать:

Я хочу преобразовать изображение, повернув его на 90, 180 или 270 градусов.


Что происходит:

По какой-то причине, когда я поворачиваю изображение 640x360 пикселей на 90 градусов, я получаю изображение 500x500 вместо изображения 360x640, поэтому изображение по каким-то причинам масштабируется...

Я также попробовал изображение размером 5000 x 2000 или около того, и я получил изображение 4800x4800 в результате поворота.

180 работает правильно и выдает тот же размер, что и без вращения, но 90 и 270 не работают...


Что я заметил

Я заметил, что градусы не совпадают со значением в радианах, поэтому я пытаюсь использовать радианы.

Я заметил, что с помощью Math.toRadians(90) приводит к вращению по часовой стрелке, а не к вращению по часовой стрелке... Мне интересно, почему положительное вращение происходит по часовой стрелке, а не против часовой стрелки?


Код:

public static BufferedImage rotateImage(BufferedImage image) throws IOException

{
        AffineTransform transform = new AffineTransform();


        transform.rotate(Math.PI/2, image.getWidth()/2, image.getHeight()/2);
        AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
        image = op.filter(image, null);



             ImageIO.write(image,"PNG",new File("C:\\a.png"));
             return image;
}

Любой совет приветствуется, спасибо за ваше время!

1 ответ

К сожалению, мои уравнения для центрирования вращения неверны в предыдущем примере. Подвести итоги:

  • Вы должны повернуть в повернутый BufferedImage, то есть BufferedImage, ширина и высота которого меняются с исходного изображения.
  • Вы не можете вращаться вокруг центра, а скорее вокруг точки, которая поместит новое изображение в точку 0, 0. Это центр большой оси, centerX = Math.max(w0, h0) / 2;или малая ось, centerX = Math.min(w0, h0) / 2; в зависимости от того, вращаетесь ли вы в 1-й или 3-й квадрант. Например,

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

public class TestAffineTransform {
    private static final String IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/thumb"
            + "/4/42/MerryOldSanta.jpg/220px-MerryOldSanta.jpg";
    private static BufferedImage originalImg;

    public static void main(String[] args) {
        try {
            URL imgUrl = new URL(IMG_PATH);
            originalImg = ImageIO.read(imgUrl);
            BufferedImage nextRotImg = transform(originalImg, 1);

            final Icon originalIcon = new ImageIcon(originalImg);
            final Icon nextRotIcon = new ImageIcon(nextRotImg);

            SwingUtilities.invokeLater(() -> {
                JOptionPane.showMessageDialog(null, originalIcon);
                JOptionPane.showMessageDialog(null, nextRotIcon);
            });
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(-1);
        }

    }

    public static BufferedImage transform(BufferedImage image, int numquadrants) {
        int w0 = image.getWidth();
        int h0 = image.getHeight();
        int w1 = w0;
        int h1 = h0;

        int centerX = w0 / 2;
        int centerY = h0 / 2;

        if (numquadrants % 2 == 1) {
            w1 = h0;
            h1 = w0;

            if (numquadrants % 4 == 1) {
                centerX = Math.max(w0, h0) / 2;
            } else {
                centerX = Math.min(w0, h0) / 2;
            }

            centerY = centerX;
        }

        AffineTransform affineTransform = new AffineTransform();
        affineTransform.setToQuadrantRotation(numquadrants, centerX, centerY);

        AffineTransformOp opRotated = new AffineTransformOp(affineTransform, AffineTransformOp.TYPE_BILINEAR);

        BufferedImage transformedImage = new BufferedImage(w1, h1, image.getType());

        opRotated.filter(image, transformedImage);
        return transformedImage;
    }

}

Который отображает:

Святой Ник

а затем отображает:

Святой Ник 2

Другие вопросы по тегам