java 旋转 BufferedImage 的问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2257141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Problems rotating BufferedImage
提问by perp
I have some problems with rotating images in Java using the AffineTransform class.
我在使用 AffineTransform 类在 Java 中旋转图像时遇到了一些问题。
I have the following method for creating a rotated (90 degrees) copy of an image:
我有以下方法来创建图像的旋转(90 度)副本:
private BufferedImage createRotatedCopy(BufferedImage img, Rotation rotation) {
int w = img.getWidth();
int h = img.getHeight();
BufferedImage rot = new BufferedImage(h, w, BufferedImage.TYPE_INT_RGB);
double theta;
switch (rotation) {
case CLOCKWISE:
theta = Math.PI / 2;
break;
case COUNTERCLOCKWISE:
theta = -Math.PI / 2;
break;
default:
throw new AssertionError();
}
AffineTransform xform = AffineTransform.getRotateInstance(theta, w / 2, h / 2);
Graphics2D g = (Graphics2D) rot.createGraphics();
g.drawImage(img, xform, null);
g.dispose();
return rot;
}
Rotation is a simple enum with the values NONE, CLOCKWISE and COUNTERCLOCKWISE.
Rotation 是一个简单的枚举,值为 NONE、CLOCKWISE 和 COUNTERCLOCKWISE。
The symptoms of my problems are displayed here:
我的问题的症状显示在这里:
http://perp.se/so/rotate_problems.html
http://perp.se/so/rotate_problems.html
So, the rotation works OK, but the resulting images aren't anchored to the correct coordinates (or how one should put it). And since I don't really know what the heck I'm doing in the first place (my linear algebra is weak), I don't know how to solve this on my own.
因此,旋转工作正常,但生成的图像没有锚定到正确的坐标(或应该如何放置)。因为我一开始真的不知道我在做什么(我的线性代数很弱),我不知道如何自己解决这个问题。
I've tried with some random fiddling with the AffineTransform instance, but it hasn't helped me (of course). I've tried googling (and searching SO), but all examples I've seen basically use the same approach as I do... which doesn't work for me.
我已经尝试对 AffineTransform 实例进行一些随机摆弄,但它并没有帮助我(当然)。我试过谷歌搜索(和搜索 SO),但我见过的所有例子基本上都使用与我相同的方法......这对我不起作用。
Thankful for advice.
感谢您的建议。
回答by finnw
If you must express the transform as a single rotation, the anchor point depends on the direction of rotation: Either (w/2, w/2)or (h/2, h/2).
如果你必须表达转化为一个单一的旋转,定位点取决于旋转方向:要么(w/2, w/2)或(h/2, h/2)。
But it's probably simpler to express as translate; rotate; translate, e.g.
但表达为可能更简单translate; rotate; translate,例如
AffineTransform xform = new AffineTransform();
xform.translate(0.5*h, 0.5*w);
xform.rotate(theta);
xform.translate(-0.5*w, -0.5*h);
Also consider using getQuadrantRotateInstanceinstead of getRotateInstance.
还可以考虑使用getQuadrantRotateInstance代替getRotateInstance.
回答by David Tinker
Since you only need 90 degree rotation you can avoid using the AffineTransform stuff:
由于您只需要 90 度旋转,您可以避免使用 AffineTransform 的东西:
public BufferedImage rotate90DX(BufferedImage bi) {
int width = bi.getWidth();
int height = bi.getHeight();
BufferedImage biFlip = new BufferedImage(height, width, bi.getType());
for(int i=0; i<width; i++)
for(int j=0; j<height; j++)
biFlip.setRGB(height-1-j, width-1-i, bi.getRGB(i, j));
return biFlip;
}
This also avoids cutting off edges of rectangular images.
这也避免了切割矩形图像的边缘。
回答by camickr
You could try an alternative appoach and create an Icon from the image and then use a Rotated Icon.
您可以尝试另一种方法并从图像创建一个 Icon ,然后使用Rotated Icon。
Or you can try this old code I found in the Sun forums:
或者你可以试试我在 Sun 论坛上找到的这个旧代码:
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import javax.imageio.*;
import javax.swing.*;
public class RotateImage {
public static void main(String[] args) throws IOException {
URL url = new URL("https://blogs.oracle.com/jag/resource/JagHeadshot-small.jpg");
BufferedImage original = ImageIO.read(url);
GraphicsConfiguration gc = getDefaultConfiguration();
BufferedImage rotated1 = tilt(original, -Math.PI/2, gc);
BufferedImage rotated2 = tilt(original, +Math.PI/4, gc);
BufferedImage rotated3 = tilt(original, Math.PI, gc);
display(original, rotated1, rotated2, rotated3);
}
public static BufferedImage tilt(BufferedImage image, double angle, GraphicsConfiguration gc) {
double sin = Math.abs(Math.sin(angle)), cos = Math.abs(Math.cos(angle));
int w = image.getWidth(), h = image.getHeight();
int neww = (int)Math.floor(w*cos+h*sin), newh = (int)Math.floor(h*cos+w*sin);
int transparency = image.getColorModel().getTransparency();
BufferedImage result = gc.createCompatibleImage(neww, newh, transparency);
Graphics2D g = result.createGraphics();
g.translate((neww-w)/2, (newh-h)/2);
g.rotate(angle, w/2, h/2);
g.drawRenderedImage(image, null);
return result;
}
public static GraphicsConfiguration getDefaultConfiguration() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
return gd.getDefaultConfiguration();
}
public static void display(BufferedImage im1, BufferedImage im2, BufferedImage im3, BufferedImage im4) {
JPanel cp = new JPanel(new GridLayout(2,2));
addImage(cp, im1, "original");
addImage(cp, im2, "rotate -PI/2");
addImage(cp, im3, "rotate +PI/4");
addImage(cp, im4, "rotate PI");
JFrame f = new JFrame("RotateImage");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setContentPane(cp);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
static void addImage(Container cp, BufferedImage im, String title) {
JLabel lbl = new JLabel(new ImageIcon(im));
lbl.setBorder(BorderFactory.createTitledBorder(title));
cp.add(lbl);
}
}
回答by Buhake Sindi
I don't know if this might be your issue.
我不知道这是否可能是你的问题。
AffineTransform xform = AffineTransform.getRotateInstance(theta, w / 2, h / 2);
Why not try?
为什么不试试?
AffineTransform xform = AffineTransform.getRotateInstance(theta);
OR
或者
g.transform(AffineTransform.getRotateInstance(theta));
g.drawImage(img, 0, 0, w/2, h/2, null, null);

