[java] Fastest Way to Draw Translucent Images

Started by
11 comments, last by GameDev.net 17 years, 7 months ago
Hey everyone. I'm working on a 2D game that uses semi-transparent overlay images. The overlay images have 2 alpha values, 0 and 0.5. The code works and the images are drawn on top of my game board. However, its putting a lot of stress on my system when a lot of these images are displayed at once (if they are filling up half my screen, there is considerable lag). I think there is a faster way to draw my images, but I can't figure out what it is. Here is the code I use to load the images.
static BufferedImage getImage(String name) {
	BufferedImage image;
	try {
		image = ImageIO.read(new File(name));
	}
	catch (Exception e) {
		System.err.println("Error loading image file " + name + ".");
		image = new BufferedImage(1,1,BufferedImage.TYPE_INT_ARGB);
	}
	return image;
}
The image is then drawn onto the screen using g.drawImage() . Any ideas on how I could speed this up? If anyone needs more information please let me know. Thanks!
Advertisement
you could use opengl (LWJGL for example).
Ideally I'd prefer to not use OpenGL or DirectX if possible...
When I was working with Java2D there was a rather unique solution I found to this. I used an opaque BufferedImage the size of the screen that I would draw everything to (might have been volatile, not completely sure... sorry use LWJGL now), and then drawing this to the back buffer using an gfx.drawImage(img,0,0,null) call. The "gfx" reference was a Graphics2D obj that I got from a double-buffering BufferStrategy.

So simply its:
1: render everything to an opaque image acting as a fake back buffer (you might want to check image properties to ensure that it is opaque)
2: draw the image to the real back buffer
3: continue normally as if your rendering had just finished

I was never completely sure why it worked better (very significantly actually, improving from 25 to 60 FPS) but I was using it to draw a translucent gradient across the bottom part of the screen in a full screen game. I think that it might do something different with the blending of translucency (perhaps calculating as each thing is rendered to the third buffer?). You might want to give it a try.
You could cache the BufferedImage instead of calling ImageIO.read everytime.

for instance you could have an hashmap where the key is the file name and the value is the BufferedImage. The first time you call getImage for a specific file you will read it since it is not in the cache and after that you would fetch the reference to that already read image.

static Map cache = new HashMap();static BufferedImage getImage(String name) {  BufferedImage image = (BufferedImage )cache.get(name);  if( image == null)  {    try {      image = ImageIO.read(new File(name));    }    catch (Exception e) {      System.err.println("Error loading image file " + name + ".");      image = new BufferedImage(1,1,BufferedImage.TYPE_INT_ARGB);    }    cache.put(name,image);  }  return image;}


But if the image are really big and you have a lot you will run out of space pretty quickly. So I guess you might want to choose what you put in the cache(ie: frequently used image, small images).
Paclaw
Also are you using -Dsun.java2d.translaccel=true?
Paclaw
Make sure all source images you are drawing with are compatable with the surface you are drawing to. To do this, call createImage() on the component you are drawing on to get an image with the same properties. Then copy your loaded image to this new image. Keep the new image for drawing and discard the loaded image. Any image that is not format compatable to the surface you are drawing to will disable image acceleration.
"None of us learn in a vacuum; we all stand on the shoulders of giants such as Wirth and Knuth and thousands of others. Lend your shoulders to building the future!" - Michael Abrash[JavaGaming.org][The Java Tutorial][Slick][LWJGL][LWJGL Tutorials for NeHe][LWJGL Wiki][jMonkey Engine]
I have some problem, when i draw an opaque image is very fast, but when images are translucent all become very slow...
I managed my image whit this code:
public void optimizing(GraphicsConfiguration cfg) {
BufferedImage newBuffer=cfg.createCompatibleImage(imm.getWidth(),imm.getHeight(),imm.TRANSLUCENT);
Graphics2D bg2=newBuffer.createGraphics();
bg2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
bg2.drawImage(imm,0,0,null);
imm.flush();
imm=null;
imm=newBuffer;
bg2.dispose();
}

But draw translucent image are very slow anyway... whit -Dsun.java2d.translaccel=true is more slow...

There are any way?
I have some problem, when i draw an opaque image is very fast, but when images are translucent all become very slow...
I managed my image whit this code:
public void optimizing(GraphicsConfiguration cfg) {		BufferedImage newBuffer=cfg.createCompatibleImage(imm.getWidth(),imm.getHeight(),imm.TRANSLUCENT);		Graphics2D bg2=newBuffer.createGraphics();		bg2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);		bg2.drawImage(imm,0,0,null);		imm.flush();		imm=null;		imm=newBuffer;		bg2.dispose();}

But draw translucent image are very slow anyway... whit -Dsun.java2d.translaccel=true is more slow...

There are any way?
Could you post an example of your rendering code? It would be very helpful to diagnosing the problem.

This topic is closed to new replies.

Advertisement