Почему вращение 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;
}
}
Который отображает:
а затем отображает: