用AffineTransform旋转图像
我有class级叫Airplane
。 在这个类里面我有variablesimg
这是一个BufferedImage
types。 更重要的是,我得到了类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); }