[英]Java2D Performance Issues
我在Java2D方面表现有些古怪。 我知道sun.java2d.opengl VM参数可以为2D启用3D加速,但是即使使用该参数也有一些奇怪的问题。
这是我运行的测试结果:
在JComponent上绘制具有32x32像素图块的25x18地图
图片1 = .bmp格式,图片2 = .png格式
使用.BMP图像的120 FPS 1
使用.PNG图像2的13 FPS
使用.BMP图像的12 FPS 1
使用.PNG图像2的700 FPS
如果没有加速,我假设我在软件中执行的每个drawImage()都会发生某种转换,并且在.PNG情况下会大幅降低FPS。 但是,为什么会随着加速而切换结果(而PNG实际上执行得异常快)? 疯了!
.BMP图像1转换为TYPE_INT_RGB的图像类型。 .PNG图像2转换为TYPE_CUSTOM的图像类型。 为了在有和没有opengl加速的情况下获得一致的速度,我必须创建一个图像类型为TYPE_INT_ARGB的新BufferedImage,并将图像1或图像2绘制到该新图像上。
这是运行结果:
使用.BMP图像的120 FPS 1
使用.PNG图像2的120 FPS
使用.BMP图像的700 FPS 1
使用.PNG图像2的700 FPS
我真正的问题是,我是否可以假设TYPE_INT_ARGB是所有系统和平台的本机图像类型? 我假设这个值可能会有所不同。 我是否可以通过某种方式获取本机值,以便始终创建新的BufferedImages以获得最佳性能?
提前致谢...
我想我找到了一种解决方案,方法是研究过多的Google搜索并将它们拼凑起来。
这里是注释和所有内容:
private BufferedImage toCompatibleImage(BufferedImage image)
{
// obtain the current system graphical settings
GraphicsConfiguration gfxConfig = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
/*
* if image is already compatible and optimized for current system
* settings, simply return it
*/
if (image.getColorModel().equals(gfxConfig.getColorModel()))
return image;
// image is not optimized, so create a new image that is
BufferedImage newImage = gfxConfig.createCompatibleImage(
image.getWidth(), image.getHeight(), image.getTransparency());
// get the graphics context of the new image to draw the old image on
Graphics2D g2d = newImage.createGraphics();
// actually draw the image and dispose of context no longer needed
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
// return the new optimized image
return newImage;
}
在我以前的文章中,GraphicsConfiguration是保存在系统上创建优化图像所需的信息。 看来效果很好,但我认为Java会自动为您执行此操作。 显然,您对Java不太满意。 :)我想我最终回答了自己的问题。 哦,希望它能对我见过的尝试将Java用于2D游戏的某些人有所帮助。
好吧,这是旧文章,但是我想分享我在不使用BufferedImage的情况下使用Swing / AWT直接绘图的发现。
直接绘制到int []缓冲区时,最好进行3D绘制。 完成图像后,可以使用ImageProducer实例(如MemoryImageSource )来生成图像。 我假设您知道如何在不使用Graphics / Graphics2的情况下直接执行绘图。
/**
* How to use MemoryImageSource to render images on JPanel
* Example by A.Borges (2015)
*/
public class MyCanvas extends JPanel implements Runnable {
public int pixel[];
public int width;
public int height;
private Image imageBuffer;
private MemoryImageSource mImageProducer;
private ColorModel cm;
private Thread thread;
public MyCanvas() {
super(true);
thread = new Thread(this, "MyCanvas Thread");
}
/**
* Call it after been visible and after resizes.
*/
public void init(){
cm = getCompatibleColorModel();
width = getWidth();
height = getHeight();
int screenSize = width * height;
if(pixel == null || pixel.length < screenSize){
pixel = new int[screenSize];
}
mImageProducer = new MemoryImageSource(width, height, cm, pixel,0, width);
mImageProducer.setAnimated(true);
mImageProducer.setFullBufferUpdates(true);
imageBuffer = Toolkit.getDefaultToolkit().createImage(mImageProducer);
if(thread.isInterrupted() || !thread.isAlive()){
thread.start();
}
}
/**
* Do your draws in here !!
* pixel is your canvas!
*/
public /* abstract */ void render(){
// rubisch draw
int[] p = pixel; // this avoid crash when resizing
if(p.length != width * height) return;
for(int x=0; x < width; x++){
for(int y=0; y<height; y++){
int color = (((x + i) % 255) & 0xFF) << 16; //red
color |= (((y + j) % 255) & 0xFF) << 8; //green
color |= (((y/2 + x/2 - j) % 255) & 0xFF) ; //blue
p[ x + y * width] = color;
}
}
i += 1;
j += 1;
}
private int i=1,j=256;
@Override
public void run() {
while (true) {
// request a JPanel re-drawing
repaint();
try {Thread.sleep(5);} catch (InterruptedException e) {}
}
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// perform draws on pixels
render();
// ask ImageProducer to update image
mImageProducer.newPixels();
// draw it on panel
g.drawImage(this.imageBuffer, 0, 0, this);
}
/**
* Overrides ImageObserver.imageUpdate.
* Always return true, assuming that imageBuffer is ready to go when called
*/
@Override
public boolean imageUpdate(Image image, int a, int b, int c, int d, int e) {
return true;
}
}// end class
注意,我们需要MemoryImageSource和Image的唯一实例。 除非您已调整了JPanel的大小,否则不要为每个帧创建新的Image或新的ImageProducer。 参见上面的init()方法。
在渲染线程中,询问repaint() 。 在Swing上, repaint()将调用重写的paintComponent() ,并在其中调用render()方法,然后要求imageProducer更新图像。 完成Image后,使用Graphics.drawImage()进行绘制。
要获得兼容的Image,请在创建Image时使用正确的ColorModel 。 我使用GraphicsConfiguration.getColorModel() :
/**
* Get Best Color model available for current screen.
* @return color model
*/
protected static ColorModel getCompatibleColorModel(){
GraphicsConfiguration gfx_config = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
return gfx_config.getColorModel();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.