Java2D rendering with BufferedImage RGB data

I was wondering if I could obtain a buffered image and create another “psuedo” image from that by using the first image’s color data to construct an image made up of 1 x 1 rectangles, representing the pixels of the buffered image. I’m not too sure if it would be faster than to use just regular buffered images. I figured it would be a different way of rendering and maybe get some performance gains.

I’m not entirely sure what you’re asking, but you can obtain the color data of a BufferedImage with this:

 data = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

That will give you an integer array (you can change it to give a byte array, etc.), with each integer corresponding to the BufferedImage’s type, e.g. TYPE_INT_ARGB for ARGB packed integers.

Modifying this array with also change the image, as it is a reference to the image’s raster.
This should be faster than Graphics.drawSomething() for some operations, but it won’t be huge. If you’re concerned about performance, don’t be using Java2D :point:

It may be a different way of rendering, but I don’t think there would be any benefit, and in fact may be detrimental. It’s a lot quicker to assign a color value to an array element (if pixel level manipulation is required) than to assign multiple values to a rectangle object. There are other reasons to avoid this approach, but in the end, you want to work with the API, not against, or around it.

As BurntPizza said, if performance is your top concern, consider a different API than Java2D. Personally, I haven’t hit the wall with Java2D yet. I get around 1200+ FPS on a fairly modern machine at 1024x768 resolution with every pixel being touched during my rendering loop. Even my craptastic 7 year old laptop with integrated Intel video still manages to crank out 120 FPS in the same scenario. The only sure way to know is to try out a few different approaches, and see what works best for you. :slight_smile:

Do you mind sharing your approach, it would be greatly appreciated. I’ve hit a huge wall and I’m sure there’s something else I could do without having to move onto other API’s. I would love to get that kind of performance at that resolution, but as soon as I start rendering a couple hundred images, the FPS starts sinking dramatically.

I DO know that when finicking around in Java2D looking for performance, it is very easy to ‘trip a tripwire’ and send the renderer into software rendering (making your image unmanaged), which vastly slows down everything. Another approach with Java2D is using BufferStrategy, which circumvents using BufferedImages, and, in my experience, is slightly faster. It is best used for fullscreen mode applications, however.

I don’t do anything special. I mostly read up on Java’s active rendering trail which covers BufferStrategy, as mentioned by BurntPizza, and implemented my rendering process accordingly. I’ve had good results in both full screen exclusive, and windowed mode. As a side note, I could have sworn that I read BufferStrategy uses BufferedImages behind the scenes, but I may be wrong.

According to the API docs, many of Java2D’s transformation and blending functions are backed by the D3D or OpenGL subsystems when available. I attribute the high level of performance I see to this. Without knowing specifics though, the difference in performance between my experiences and yours could be due to the way you cache images (sprite sheets vs. individual images), differences in game loop logic, or any number of other things. I would say look through the docs to see if you may be doing something that’s easy to correct. However, as BurntPizza said, there are some tripwires with using Java2D that could result in less than desirable performance in a given case. Maybe I’ve just been lucky in the fact that I haven’t tripped enough of them to blow my performance to pieces. :persecutioncomplex:

It may, but either way, it takes care of it for you and it is likely to do it well, and that is nice.

IIRC, I think it is mainly (or at least used to be) certain drawing operations (like transforms or compositing) or setData() etc, operations on buffered images that it didn’t like.

These are the old 1.5 docs, but I think the data is still valid. I do definitely remember that pixel level manipulations prevent Java2D from accelerating the images.

Yea, it was mostly low level pixel operations that did that, but I believe that the .getRaster().getDataBuffer() etc. stuff does successfully get around this, albeit then you have to work with color packing and manually indexing and such. So for BufferedImages, that is the best option for pixel-by-pixel access to the image, am I correct?

I think you’re correct. If I’m recalling correctly, which given the hour here I may not be, I think the preferred way to do direct pixel manipulations was to use create an image that was compatible with your BufferStrategy, then grab the pixel data for that image via the “raster/alpha data” methods and manipulate it. Once the pixel level manipulation was done, you render the final product to the back buffer and flip. This keeps the strategy itself accelerated even if the “scratch image” isn’t. Direct manipulation of the back buffer is definitely a no-no. :o

Agreed. But using the pixel array should keep the scratch image accelerated and thus help with the process, otherwise not very many gains would be had, as you still have to render to the strategy.

According to this (admittedly older forum post), directly accessing the image data will most certainly un-accelerate your scratch image. It would seem to make sense, since that thread mentions Java having no real way of knowing what was modified and therefore no real way of knowing how to optimize the operations. I’m far from a guru on the subject though. I would love to find out a definitive answer from someone who has studied the rendering code a bit more since I have heard people say the same thing as you have. Excellent discussion. ;D

[quote=“CodeHead,post:6,topic:42585”]
The main problem with Java2D’s performance is that it’s extremely unreliable. Your test machines might be giving you high performance, but any number of other test machines might slow to a crawl. You have very little control over what pipeline it chooses, or whether it uses hardware acceleration as you would expect (or at all).

I have seen this happen where my professor could only run my game at 2 FPS; even though I was getting 60+ FPS on my own test devices. His computer was pretty new and had good specs.

In the end; if you hope to target more than just your own computers, it’s not worth risking it with Java2D. :wink:

When it came to changing the pixels of a BufferedImage, I just took the shortcut way and always did getGraphics() then drew directly to it while keeping a backup of the original loaded image somewhere in memory. Of course I only did this occasionally due to the memory duplication.

Java2D does give you direct control over which pipeline you can use and what settings http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSG-Desktop/html/java2d.html#gcghe

Only thing I can really recommend if you want to increase performance in your Java2D game is to be sure that anything off screen you systematically cull. If you’re not accounting for the frame’s dimensions and your current camera location, in your render loop you might still be rendering things that are not even being seen.

You can request it, but no guarantees. Also notice on Mac, the VM flags don’t have any effect (at least not in any of my tests). You just need to hope it’s using hardware acceleration; and not doing anything stupid under the hood.