Sign in to follow this  

[java] Fastest way to draw to the screen

This topic is 3647 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to create a cellular automaton, with each cell 1 pixel in size. What is the best way to update the screen? My current implementation works like this: a buffer generated by Canvas.createImage() the graphics object is obtained from the image buffer. The graphics object is modified by each cell with a call to Graphics.fillRect(). The paint and update meathods use Graphics.drawImage() to draw the image buffer to the screen. However, as implemented my program is very slow. Is there a better way to update the screen? I've heard that BufferedImage has faster methods than Graphics.fillRect() to update individual pictures. Java also seems to have a lot of tools for "image generator" objects. What are my options? Which is the best in my case? [Edited by - King Mir on December 5, 2007 2:15:52 PM]

Share this post


Link to post
Share on other sites
Here are some guidelines for using BufferedImages and modifying individual pixels (You especially need to look at #3):

1. Create your BufferedImage using

java.awt.GraphicsConfiguration.createCompatableImage(int width, int height, int transparency).

2. Use

BufferedImage.getRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)

if you want to get the contents of a BufferedImage in an array. It sounds like you would not need to use this, though.

3. Use

BufferedImage.setRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize)

to set the contents of a BufferedImage.

If you do everything correctly, the image should stay hardware accelerated (at least for the BufferedImage data in memory, not the data that you are modifying).

One problem is that using the graphics that can be returned by BufferedImage.getGraphics() may cause the image to stop being hardware accelerated.

Greggles

[edit](forgot something)
If the image is of the image type RGB or ARGB, then you should use the following:

(int [])image.getRaster().getDataElements(int x, int y, int width, int height, int[] rgb );

image.getRaster().setDataElements(int x, int y, int width, int height, int[] rgb);

Also, I'm not sure about that BufferedImage.getGraphics() thing. I think it may only apply in certain situations and it may not be because of the Graphics but the way the data is set in the image. So, if you do want to use it then try it out and see if it slows down the app.
[/edit]

Share this post


Link to post
Share on other sites
Must you use "pure" Java? OpenGL seems more suitable to the task at hand. Either write a simple JNI function to update a JPanel, or use a OGL binding, such as JOGL or LWJGL.

Although, as of JDK 6, usage of hardware accelerated images isn't the pain it used to be ;)

Rodrigo

Share this post


Link to post
Share on other sites
Quote:
Original post by Son of Cain
Must you use "pure" Java? OpenGL seems more suitable to the task at hand. Either write a simple JNI function to update a JPanel, or use a OGL binding, such as JOGL or LWJGL.

Although, as of JDK 6, usage of hardware accelerated images isn't the pain it used to be ;)

Rodrigo
I want this to be a web applet, but If there's some way to get OpenGL to work with that I am open to the idea. I haven't ever worked with OpenGL, so pure Java has the advantage of being slightly more familiar. But what's most important is speed, not ease of use.

@elFarto
Thanks I'll take a look.

Share this post


Link to post
Share on other sites
the fastest way to draw to the screen is to draw a volatileImage. Its much faster than draw bufferedImage. I get up to 600 fps at a GeForce 6600GT with volatileImage. With bufferedImage i had around 30 fps and with Image about 120 fps. I had test this in a little 2D-Invaders-Game (look at http://www.hs-merseburg.de/~meck/projekte/invaders/invaders.html).

Both, Image and VolatileImage, are much faster than BufferedImage. For Browser-Games is the Image the best. For OpenGL-Rendering the VolatileImage. BufferedImage is only good for Stills.

[Edited by - keenha on December 15, 2007 4:13:08 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Son of Cain
My guess: setRGB() is faster, because it deals with an image that is hardware accelerated. Buffer strategy is used mainly for double buffering.
With bufferedImage I still have to call g.drawImage(bufferImage, 0, 0, this), so I am still implementing double buffering. Unless there's some other way to draw the image to the screen, that I don't know about.

@keenha
Ok, so Image is the way to go for browser games. That's what I had at first. Damn.

[Edited by - King Mir on December 16, 2007 3:40:41 PM]

Share this post


Link to post
Share on other sites
Even faster is to directly manipulate a BufferedImage's pixel data.

e.g.



// create the Buffered Image to be rendered to
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
imageGraphics=image.getGraphics();

// get the reference to the BufferedImage's data buffer
imagePixelData = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();

// set pixel at (xPos,yPos) with colour components as floats between 0 and 1
imagePixelData[yPos*width+xPos]= (int) (red*255)<<16 | (int) (green*255)<<8 | (int) (blue*255);


// set pixel at (xPos,yPos) with colour components as ints between 0 and 255
imagePixelData[yPos*width+xPos]= red<<16 | green<<8 | blue;

Share this post


Link to post
Share on other sites
Quote:
Original post by moogie
Even faster is to directly manipulate a BufferedImage's pixel data.

e.g.



// create the Buffered Image to be rendered to
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
imageGraphics=image.getGraphics();

// get the reference to the BufferedImage's data buffer
imagePixelData = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();

// set pixel at (xPos,yPos) with colour components as floats between 0 and 1
imagePixelData[yPos*width+xPos]= (int) (red*255)<<16 | (int) (green*255)<<8 | (int) (blue*255);


// set pixel at (xPos,yPos) with colour components as ints between 0 and 255
imagePixelData[yPos*width+xPos]= red<<16 | green<<8 | blue;

Shouldn't that be just as fast as setRGB(), or is setRGB() also doing something else that I am not aware of?

Share this post


Link to post
Share on other sites
Quote:
Original post by King Mir
Shouldn't that be just as fast as setRGB(), or is setRGB() also doing something else that I am not aware of?


I would think that it depends how you are using the function. If you are calling the setRBG( int x, int y, int color ), and you are trying to clear the buffer of a 1024x768 image, that would be 786,432 method calls, which is slower than setting each array value.

Share this post


Link to post
Share on other sites

This topic is 3647 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this