Pixel Array Manipulation vs. Multiple DrawImage Calls

Hello,

This is a question that I have had for a while. I am wondering if it is faster for a Java game to do rendering with a pixels array of integers and then update the pixels based on that. Another option is to use the Java2D Graphics class and create multiple bufferedimage’s and then call g.drawImage multiple times.

Overall, My question is: Is it faster to in the long run to manipulate a pixels array of integers for each rendering call that you make or is faster to call g.drawImage(); multiple times to render each bufferedimage that you create?

Thanks

I personally use pixel manipulation. That is because it is really powerfull in comparison with drawImage calls. I made a few tests on this and found out that after several drawImage calls my fps dropped really badly. Rendering everything pixel by pixel (if done well) gives you more control over the end product, and gives more performance.

When doing more complicated things such as lighting or particles I found it more usefull to manipulate each pixel than to use the drawImage function. I got more precise results out of it.

Please use the search bar.

Quick rundown:

First, do you need more performance? Is your renderer struggling? If not, don’t even ask this question.

Second, the two different methods serve different purposes: if you need to blit (draw) and image onto another (or the screen) drawImage is the way to go, and the fastest thing there is.
If you need to calculate each pixel individually (dynamic shadows, etc), then a pixel array is the way to go, the only alternative being lots of drawLine(x,y,x,y) calls.

So use a pixel array if the task cannot be done with drawImage, not just on a whim. Simplify your life.

Both use AWT. There’s no reason to use one instead of the other. You can use both.

I believe by “pixels array of integers” he means [icode]int[] data = ((DataBufferInt)image.getData().getDataBuffer()).getData();[/icode] and then manipulating [icode]data[/icode], which in fact does not use AWT, at least directly (you still have to draw the [icode]image[/icode] after playing with the array)

Although yes, you can certainly use both. They have different use cases; I’m not even sure why you would ever mess with an array to draw an image if 1. you already have an image, 2. with the array you have to draw the image afterwards anyway. Maybe I don’t completely understand OP’s question.

Exactly. You’ll have to draw the image in the end anyway (using AWT).

The overhead you’re sidestepping is doing a bunch of g.drawImage calls which in most cases won’t matter at all. There was a post about Swings behavior a while back - couldn’t find it.

Point is, sidestep the g.call overhead only if you have to -and if you are at a point where you have to - you’re either doing something very, very wrong or you should be using something much more robust (e.g., openGL).

The only other reason to manually manipulate the pixels are because of interest or boredom. A fine but somewhat redundant form of mental masturbation if only for pedagogical reasons.

Might indeed be the reason I use it :slight_smile:

If you’re blitting onto another BufferedImage then that statement isn’t true. Direct pixel manipulation is at least as fast and often faster - it’s exactly what the Graphics2D will be doing, but with less overhead. If you’re rendering to the screen or VolatileImage then drawImage will be much faster. The answer to the question depends on where the images are being drawn to.

Let’s make an example:

We’re running a game on 120 fps. Every frame I use 1 drawImage call (to put the final image to the screen). That image is contructed from a data array in which I’ve been working in since my last render cycle. Once the render is complete (i.e. I put all pixels in the right place of my data array) I use the drawImage call mentioned above. I’ve found that this is alot faster than using a drawImage call for every tile/object/mob/entity/etc.

[quote=“nsigma,post:8,topic:47896”]
… and from.

I have found that the easiest, simplest, and for the most part fastest way to draw an image is via the “blit”. If this is accelerated, it should be faster then direct manipulation.

2 reasons.

  1. If it is accelerated, it will use opengl/directx which is faster then software rasterizing which is pixel manipulation.

  2. Software rasterizing is slow. It will be faster then the “blit” if the “blit” is not accelerated as it will default to rasterization.

What can drop acceleration from images:

First you should be drawing using a buffer strategy or a volatile image. Drawing with a buffered images graphics object is not accelerated.

Grabbing the pixels from a bufferedimage will drop it from being accelerated. It is also slow.

Certain operations when drawing bufferedimages/volatile images drop into software. Things like drawArea/shape and different filtering settings. (AA, bi-cubic filtering, custom alpha composites)

Pixel manipulation via grabbing a buffered images pixels once, manipulating them and then drawing said buffered image will be faster if you want to do things that will drop acceleration as you can optimize better then the fall back the Java2D uses.

These seem rather contradictory, and I’m pretty sure the former is false. Hold on while I find some documentation.

EDIT: Not a lot of recent, up-to-date, or well tested data out there it seems.

Some other people’s opinions/findings:



http://www.jhlabs.com/ip/managed_images.html (don’t know how recent)

So it’s muddled still, but it seems that most things are accelerated on a BI, while a few things like Stumpy said are bad and will “decelerate” the image.

[quote]Overall, My question is: Is it faster to in the long run to manipulate a pixels array of integers for each rendering call that you make or is faster to call g.drawImage(); multiple times to render each bufferedimage that you create?
[/quote]
If you only draw a couple of images, using drawImage() woule be faster. However if you plan to draw thousands of images (especially small images), you are better off to “draw” all pixels to the bufferedImage. This way your only call drawImage() once rather than thousands of times.

Here, try drawing with a bufferedimage’s graphics object and then try drawing with a volatile image’s graphics contex. You can draw your own conclusion.

All BufferedImages are “Managed” Images be default. That is they start accelerated. You can draw buffered images onto accelerated surfaces quickly. An accelerated surface is basically a VolatileImage. You cannot draw to a bufferedimage quickly as it is not an accelerated surface.

In pseudo opengl:

BufferedImage = texture
VolatileImage = FBO/render target
Buffered Strategy is backed by a Volatile Image a believe.

So drawing to a texture that is not set up to be drawn to is slow.

BufferedImages support AA/filtering/other such effects. Some are slower then others. Shape/polygon rendering is slower then image bliting.

VolatileImages can be drawn as well but not all operations are “fast”.

All of this also depends on ones drivers as well.

I have done extensive trial and error testing much of this in my Retro project. So my proof behind what I say is not from documentation but experience. Realistically, NO one should be using java2D for anything other then a 4k contest.