Efficient way to draw into a java.awt.graphics object - java

I'm trying to create an animation by dynamically generating frames at each step of the animation. Now as I need to run an algorithm to draw pixel by pixel the new frame and I'm using a BufferedImage that I access through its raster data.
However 90% of the time is spent inside java.awt.graphcis.drawImage() that I use to transfer the image into the content of a JFrame.
Is there a more efficient way to draw pixel by pixel inside a graphics object?

Try to use VolatileImage. Much faster than that is hard to do..

Related

opengl / JOGL - best way to draw textures

I thought about the best way to draw a picture in OpenGL / JOGL.
I currently program a Game and it is my goal to save the information about a picture in a text file instead of saving the picture.
My idea was to program a method that saves every pixel information (RGB) at the position of X and Y.
Then I draw every pixel and it is finished.
What you think about that idea?
You should simply use TextureIO to make a texture from your picture and use this texture with 4 vertices that have some texture coordinates while drawing. glReadPixels() is very slow, reading each pixel of a picture would take a lot of time, saving its content as a text file would require a lot of memory (saving it as a compressed image in a loss-less format like PNG might be worth a try), drawing each pixel one by one would be a lot slower than drawing a texture. derhass is right. You could vectorize your picture (make a SVG from it) but you would have to rasterize it after or you would have to implement some rendering of vectorized contents and it would be probably slower than using a texture. I'm not sure you really need an offscreen buffer.
I had a similar problem when I began working on my first person shooter. I wasn't using JOGL at the very beginning, I reused the source code of someone else, it relied on software rendering in an image, it was very slow. Then, I used JOGL to draw each pixel one by one instead of using Java2D, it was about 4 times faster on my machine but still very slow for me. At the end, I had to redesign the whole rendering to use OpenGL for what it is for as derhass would say, I used triangles, quads and textures. The performance became acceptable and this is what you should do, use OpenGL to draw primitives and clarify what you're trying to achieve so that we can help you a bit better.

Canvas Drawing using an image as place holder

I want to have a drawing canvas within my application which will display letter to free draw for practice. Something like the following:
OR
This is the first time I will be implementing this method so a few questions.
Can I have my own background for the canvas? (let's say a chalkboard?)
Do I have to create the letter as image and insert it onto the canvas as Bitmap?
I saw some tutorials but wasn't too clear on how to implement it within app.
I found a solution for you. Having more than 1 Canvas is not the answer (Although may work, I'm still new), but instead draw a seperate Bitmap on top of the first Bitmap (background).
Try this out for size: Overlying Bitmap
You should then be able to edit the overlaying Bitmap without affecting the original Bitmap.
Cheers!

Android Drawing Performance - canvas.drawRect vs Bitmap Drawing

I am writing a particle based game that is mainly built by drawing lots of colored shapes.
Question 1)
For most of the enemy units I am drawing 4 layered rectangles by setting the paint and then drawing the rectangle through the canvas.
I was wondering if it is better to draw using bitmaps, or to draw using the canvas drawing tools? I could easily make a single image of the enemy unit that I wish to draw.
Question 2)
For the images that I have to draw to the screen, I was wondering how I need to load them?
Right now I have tons of .png images loaded like this:
direction1 = BitmapFactory.decodeStream(assetMgr.open("direction1.png"));
I've read that RGB565 is the fasted image type to draw to the screen. Microsoft Paint has some saving options, but for the most part programs only save as a bitmap, not a type of bitmap. If I was to start using that new format would I:
Make new images and use the same loading code.
Use the same images and add something like Bitmap bmp =
Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); to
convert from the initial loaded format to the RGB565 format.
Make new images and change my loading code.
Thanks for any help! It is very appreciated.
None. It is always better to use OpenGL and the only downside is
that it requires more energy from a battery because it's hardware
accelerated.
RGB565 means that image uses 16 bits so that's the
option you should look for. Don't convert anything, just create them
in the format you will be using.
If the Bitmap aren't moving frame-by-frame, you should try to reduce invalidate() method call. The canvas should only be re-drawn when changes are made and should be updated.

Create an Image out of a larger Image

For a game I'm making I am storing all the sprites for the map inside one large(er) image. I want to be able to create an instance of Image for each image inside of the larger image that has all the sprites.
So how would I create an instance of Image from a set position of another Image.
The basic solution (if all tiles in your tilesheet have the same size) is to use the getSubimage(xpos, ypos, XSIZE, YSIZE) method from the class BufferedImage.
Otherwise, you'll have to store a set of position and size for all sprites in another file.
Your question is similar to this others one.
Since you are using the java.awt.Image-class i am guessing you are trying to create a reasonable game using AWT? You really should take a look at a different technology like http://en.wikipedia.org/wiki/Java_OpenGL. The problem you ran into (partitioning a sprite-sheet) is typical for a lot of other problems (rotation...) you will run into if you try to develop a game without something like Open-GL.
Considering only the problem at-hand: you can easily solve this in Open-GL by binding the whole sprite-sheet as texture (glBindTexture()) and giving for each glVertex() a glTexCoord2f(), no need to cut-out parts of the sprite-sheet.

draw image or draw filled circle?

We have an old Java Swing application. we need to display thousands, hundreds of thousands small circle spots on the canvas based on the real data. Right now we have an image file of a small circle spot. When we need it, we draw that image onto the canvas, thousands, hundreds of thousands times.
Now I am think it may be better (better performance and memory usage) to just draw a filled circle each time instead of load the image and draw it.
how about your opinion?
thanks,
You only need to load the template image once and hold it in memory and copy it to the canvas as needed using Graphics2D drawImage function. Drawing multiple filled circles may become expensive due to calls to the Flood-fill/Scan-fill algorithm as well as Bresenham to draw the circle. To optimize the rendering you can also decimate the rendered result or perform clustering, since the user will not really appreciate dense overlapping circles anyway.
To reduce render calls test the pixel where your template is going and pass a render if it is already coloured.
Here is a nice benchmarking applet.
It is almost certainly much faster to hold a single image and draw it many times than to make a call to draw a filled circle. Here is a recent presentation on the subject, showing that it is faster to draw an image than even a simple horizontal cross. http://developers.sun.com/learning/javaoneonline/j1sessn.jsp?sessn=TS-4170&yr=2009&track=javase
Time your code
It is most definitely faster to draw an image lots of times than drawing a circle or String lots of times and it's very easy to test. At the beginning of your paintComponent() method add the line:
paintComponent(){
long start = System.currentTimeMillis();
...
// draw 100,000 circles as images or circles
...
System.out.println("Rendering time: " +
(start - System.currentTimeMillis()) + " ms");
}
If the times turn out to be zero all the time, you can instead use System.nanoTime().
Paint to Cached Image
Another thing you can do is to paint these circles onto an image and only recreate the image when the content changes. If nothing has changed just draw that image onto the Graphics2D object instead of redrawing all of the circles. This is commonly called double buffering. You also can use Volatile Images to take advantage of hardware acceleration.
Create Compatible Images
You should also make sure you use images that are compatible with the user's monitor by using createCompatibleImage() as shown below:
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
// Create an image that does not support transparency
BufferedImage bimage = gc.createCompatibleImage(width, height, Transparency.OPAQUE);
// Create an image that supports transparent pixels
bimage = gc.createCompatibleImage(width, height, Transparency.BITMASK);
// Create an image that supports arbitrary levels of transparency
bimage = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
More Tips
I'd recommend the book Filthy Rich Clients. It has lots of great tips for speeding up swing. Especially look at chapters 4 and 5 about images and performance.
I don't now if this would be helpful but you can test which one works for you by testing worst case . But I think filled circle would be best .
A third way to do it is to use the unicode char for filled circle, &#x25CF, since you can bet that rendering thousands of chars (as in: a piece of text) is the most normal thing for any graphics engine.
It's hard to predict which is faster, because certain operations under certain circumstances are accelerated by the GPU hardware of the video card.
If the GPU is used to make the circle, then that would be much faster than the cpu copying pixels of a buffered circle as an image.
There is VolatileImage as well. Perhaps it's possible to make the image blits so that they end up being accelerated.
The only way to find out is to benchmark it yourself.

Categories

Resources