用AffineTransform旋转图像

我有class级叫Airplane 。 在这个类里面我有variablesimg这是一个BufferedImagetypes。 更重要的是,我得到了类WorldMap ,它覆盖了函数paintComponent(Graphics g)

 @Override public void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g; g2d.drawImage(mapa, 0, 0, getWidth(), getHeight(), null); drawAirplanes(g2d); } 

函数drawAirplanes()看起来像这样:

 private void drawAirplane(Graphics2D g){ for(Samolot i: s){ i.rotateAirplane(); g.drawImage(i.getImg(),i.getX(),i.getY(),(int)i.getDim().getWidth(),(int)i.getDim().getHeight(), null); } } 

它只需要1)旋转飞机(BufferedImage里面的飞机对象)2)吸引他。

我的Airplane.rotateAirplane()函数如下所示:

  public void rotateSamolot() { AffineTransform tx = new AffineTransform(); tx.translate(10,10); //10, 10 is height and width of img divide by 2 tx.rotate(Math.PI / 2); tx.translate(-10,-10); AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); BufferedImage newImage =new BufferedImage(20, 20, img.getType()); //20, 20 is a height and width of img ofc op.filter(img, newImage); this.img = newImage; } 

ofc当我运行我的程序只有mapa对象被绘制。 当我删除这条车道

this.img = newImage;

我也得到了我的飞机,但没有旋转。

主要的问题(我可以看到)是Graphics上下文的转换,它抵消了旋转将发生的位置。

我认为默认情况下旋转出现在Graphics上下文的左上angular(0x0的位置是你已经转换的东西),这可能会导致图像旋转出帧(或可见区)

你应该提供一个“锚点”,旋转发生的地方,通常,中心是我个人的喜好。

下面的例子只是一个主图像(由于尺寸限制,我不得不缩放它,但你可能不需要这个)。 然后,我使用它来生成一个“旋转”的实例,这个实例的大小可以让图像适合在其中。这对于trig来说非常有趣 – 我从某个地方窃取了代码,所以相信这个开发人员。

这个例子允许你点击任何地方,它会改变旋转轴,所以你可以看到发生了什么事情。 默认位置是窗格的中心…

纺织

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class SampleRotation { public static void main(String[] args) { new SampleRotation(); } public SampleRotation() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } final RotationPane rotationPane = new RotationPane(); final JSlider slider = new JSlider(0, 100); slider.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { double angle = 720d * (slider.getValue() / 100d); rotationPane.setAngle(angle); } }); slider.setValue(0); JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(rotationPane); frame.add(slider, BorderLayout.SOUTH); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class RotationPane extends JPanel { private BufferedImage img; private BufferedImage rotated; private double angle; private Point clickPoint; public RotationPane() { try { img = ImageIO.read(new File("/Users/swhitehead/Dropbox/MegaTokyo/issue459.jpg")); BufferedImage scaled = new BufferedImage(img.getWidth() / 2, img.getHeight() / 2, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = scaled.createGraphics(); g2d.setTransform(AffineTransform.getScaleInstance(0.5d, 0.5d)); g2d.drawImage(img, 0, 0, this); g2d.dispose(); img = scaled; setAngle(0d); } catch (IOException ex) { ex.printStackTrace(); } addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { clickPoint = e.getPoint(); repaint(); } }); } public void setAngle(double angle) { this.angle = angle; double rads = Math.toRadians(getAngle()); double sin = Math.abs(Math.sin(rads)), cos = Math.abs(Math.cos(rads)); int w = img.getWidth(); int h = img.getHeight(); int newWidth = (int) Math.floor(w * cos + h * sin); int newHeight = (int) Math.floor(h * cos + w * sin); rotated = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = rotated.createGraphics(); AffineTransform at = new AffineTransform(); at.translate((newWidth - w) / 2, (newHeight - h) / 2); int x = clickPoint == null ? w / 2 : clickPoint.x; int y = clickPoint == null ? h / 2 : clickPoint.y; at.rotate(Math.toRadians(getAngle()), x, y); g2d.setTransform(at); g2d.drawImage(img, 0, 0, this); g2d.setColor(Color.RED); g2d.drawRect(0, 0, newWidth - 1, newHeight - 1); g2d.dispose(); repaint(); } public double getAngle() { return angle; } @Override public Dimension getPreferredSize() { return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(this), img.getHeight(this)); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); if (rotated != null) { Graphics2D g2d = (Graphics2D) g.create(); int x = (getWidth() - rotated.getWidth()) / 2; int y = (getHeight() - rotated.getHeight()) / 2; g2d.drawImage(rotated, x, y, this); g2d.setColor(Color.RED); x = clickPoint == null ? getWidth() / 2 : clickPoint.x; y = clickPoint == null ? getHeight()/ 2 : clickPoint.y; x -= 5; y -= 5; g2d.drawOval(x, y, 10, 10); g2d.dispose(); } } } } 

这是对我有用(有点从这里和那里复制):

 public BufferedImage rotateImag (BufferedImage imag, int n) { //n rotation in gradians double rotationRequired = Math.toRadians (n); double locationX = imag.getWidth() / 2; double locationY = imag.getHeight() / 2; AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY); AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); BufferedImage newImage =new BufferedImage(imag.getWidth(), imag.getHeight(), imag.getType()); //20, 20 is a height and width of imag ofc op.filter(imag, newImage); //this.img = newImage; return(newImage); }