java 快速旋转缓冲图像
java rotating bufferedimages fast
我开发了一款游戏,旋转图片目前在一帧的计算过程中占用了大部分时间。为了优化,我正在寻找旋转缓冲图像的最快方法。我已经尝试了下面显示的两种方法。
最慢的方法:
public static BufferedImage rotate(BufferedImage imgOld, int deg){ //Parameter for this method are the picture to rotate and the rotation in degrees
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(deg), (int)(imgOld.getWidth()/2), (int)(imgOld.getHeight()/2)); //initialize and configure transformation
BufferedImage imgNew = new BufferedImage(imgOld.getWidth(), imgOld.getHeight(), imgOld.getType()); //create new bufferedimage with the properties of the image to rotate
Graphics2D g = (Graphics2D) imgNew.getGraphics(); //create Graphics
g.setTransform(at); //apply transformation
g.drawImage(imgOld, 0, 0, null); //draw rotated image
g.dispose();
imgOld.flush();
return imgNew;
}
稍微快一点的方法:
public static BufferedImage rotate(BufferedImage imgOld, int deg){ //parameter same as method above
BufferedImage imgNew = new BufferedImage(imgOld.getWidth(), imgOld.getHeight(), imgOld.getType()); //create new buffered image
Graphics2D g = (Graphics2D) imgNew.getGraphics(); //create new graphics
g.rotate(QaDMath.toRadians(deg), imgOld.getWidth()/2, imgOld.getHeight()/2); //configure rotation
g.drawImage(imgOld, 0, 0, null); //draw rotated image
return imgNew; //return rotated image
}
}
我发现许多与旋转图像相关的主题,但没有一个讨论最快、最多的解决方案。
我希望我没有错过任何主题,这不是重复的。
希望有比我更熟练的人知道解决方案
我猜想部分问题是您不断创建新的 BufferedImages 来进行旋转。这导致您绘制两次,一次是在 BufferedImage 上绘制,第二次是在框架上绘制 BufferedImage。
您可以尝试只绘制旋转的现有 BufferedImage。例如,您可以使用 Rotated Icon 然后使用
绘制图标
rotated.paintIcon(...);
每当您需要旋转图像时,您只需使用:
rotated.setDegrees(...);
简单示例:
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class Rotation3 extends JPanel
{
private Icon icon;
private RotatedIcon rotated;
private int degrees;
public Rotation3(Image image)
{
icon = new ImageIcon( image );
rotated = new RotatedIcon(icon, 0);
rotated.setCircularIcon( true );
setDegrees( 0 );
setPreferredSize( new Dimension(600, 600) );
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
double radians = Math.toRadians( degrees );
// translate x/y so Icon rotated around a specific point (300, 300)
int x = 300 - (rotated.getIconWidth() / 2);
int y = 300 - (rotated.getIconHeight() / 2);
rotated.paintIcon(this, g, x, y);
g.setColor(Color.RED);
g.fillOval(295, 295, 10, 10);
}
public void setDegrees(int degrees)
{
this.degrees = degrees;
rotated.setDegrees(degrees);
repaint();
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
String path = "dukewavered.gif";
ClassLoader cl = Rotation3.class.getClassLoader();
BufferedImage bi = ImageIO.read(cl.getResourceAsStream(path));
final Rotation3 r = new Rotation3(bi);
final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
slider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
int value = slider.getValue();
r.setDegrees( value );
}
});
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(r));
f.add(slider, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
catch(IOException e)
{
System.out.println(e);
}
}
});
}
}
只需拖动滑块即可查看旋转。
我开发了一款游戏,旋转图片目前在一帧的计算过程中占用了大部分时间。为了优化,我正在寻找旋转缓冲图像的最快方法。我已经尝试了下面显示的两种方法。
最慢的方法:
public static BufferedImage rotate(BufferedImage imgOld, int deg){ //Parameter for this method are the picture to rotate and the rotation in degrees
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(deg), (int)(imgOld.getWidth()/2), (int)(imgOld.getHeight()/2)); //initialize and configure transformation
BufferedImage imgNew = new BufferedImage(imgOld.getWidth(), imgOld.getHeight(), imgOld.getType()); //create new bufferedimage with the properties of the image to rotate
Graphics2D g = (Graphics2D) imgNew.getGraphics(); //create Graphics
g.setTransform(at); //apply transformation
g.drawImage(imgOld, 0, 0, null); //draw rotated image
g.dispose();
imgOld.flush();
return imgNew;
}
稍微快一点的方法:
public static BufferedImage rotate(BufferedImage imgOld, int deg){ //parameter same as method above
BufferedImage imgNew = new BufferedImage(imgOld.getWidth(), imgOld.getHeight(), imgOld.getType()); //create new buffered image
Graphics2D g = (Graphics2D) imgNew.getGraphics(); //create new graphics
g.rotate(QaDMath.toRadians(deg), imgOld.getWidth()/2, imgOld.getHeight()/2); //configure rotation
g.drawImage(imgOld, 0, 0, null); //draw rotated image
return imgNew; //return rotated image
}
}
我发现许多与旋转图像相关的主题,但没有一个讨论最快、最多的解决方案。 我希望我没有错过任何主题,这不是重复的。
希望有比我更熟练的人知道解决方案
我猜想部分问题是您不断创建新的 BufferedImages 来进行旋转。这导致您绘制两次,一次是在 BufferedImage 上绘制,第二次是在框架上绘制 BufferedImage。
您可以尝试只绘制旋转的现有 BufferedImage。例如,您可以使用 Rotated Icon 然后使用
绘制图标rotated.paintIcon(...);
每当您需要旋转图像时,您只需使用:
rotated.setDegrees(...);
简单示例:
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.*;
public class Rotation3 extends JPanel
{
private Icon icon;
private RotatedIcon rotated;
private int degrees;
public Rotation3(Image image)
{
icon = new ImageIcon( image );
rotated = new RotatedIcon(icon, 0);
rotated.setCircularIcon( true );
setDegrees( 0 );
setPreferredSize( new Dimension(600, 600) );
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
double radians = Math.toRadians( degrees );
// translate x/y so Icon rotated around a specific point (300, 300)
int x = 300 - (rotated.getIconWidth() / 2);
int y = 300 - (rotated.getIconHeight() / 2);
rotated.paintIcon(this, g, x, y);
g.setColor(Color.RED);
g.fillOval(295, 295, 10, 10);
}
public void setDegrees(int degrees)
{
this.degrees = degrees;
rotated.setDegrees(degrees);
repaint();
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
String path = "dukewavered.gif";
ClassLoader cl = Rotation3.class.getClassLoader();
BufferedImage bi = ImageIO.read(cl.getResourceAsStream(path));
final Rotation3 r = new Rotation3(bi);
final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
slider.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
int value = slider.getValue();
r.setDegrees( value );
}
});
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(r));
f.add(slider, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
catch(IOException e)
{
System.out.println(e);
}
}
});
}
}
只需拖动滑块即可查看旋转。