views:

135

answers:

5

I'm trying to create a fast image generator that does lots of 2d transformations and shape rendering, so I'm trying to use a BufferedImage and then acquire the Graphics2D object to perform all my drawing. My main concern now is to make is really fast so I'm creating a BufferedImage like this:

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
BufferedImage bImage = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
Graphics2D graphics = bImage.createGraphics();

However if I do:

System.out.println(bImage.getCapabilities(gc).isAccelerated());

The output is always false, even if I start the JVM with -Dsun.java2d.opengl=True which prints the line:

OpenGL pipeline enabled for default config on screen 0

I'm doing a BufferedImage because in the end I want to save it to a PNG file with ImageIO.write(bImage, "PNG", file);

I can create a VolatileImage which will say that it is accelerated but ImageIO doesn't like it when trying to save, saying that that image cannot be casted to RenderedImage. Any ideas on how to get an accelerated image that can be stored to disk? Also I don't want to create a VolatileImage and the copy to a BufferedImage to save since my images are really big and I'll run into out of memory issues...

+1  A: 

Try adding this to your command line:

-Dsun.java2d.accthreshold=0

EDIT

I did some reading on this after you said the above didn't work. Try changing the True on the OpenGL parameter to be all lowercase.

-Dsun.java2d.opengl=true
Ascalonian
Adding that parameter, unfortunately does not change anything.
Paulo Lopes
Being lowercase has no impact. From the documentation an uppercase True enabled the OpenGL pipeline with debug information e.g. it prints: OpenGL pipeline enabled for default config on screen 0, with lowercase, it is the same behaviour but without the debug information being printed out.
Paulo Lopes
I just went and Googled some docs about this and that is what they said. I guess lesson learned for trying to help on something you don't know.
Ascalonian
A: 

If speed really matters for you, you should consider using graphic hardware directly.

I could suggest you CUDA: a C library for using massively parallel NVIDA GPUs. Take a look to JCUDA for using it from JAVA (http://www.jcuda.org/)

CUDA is very popular in the parellel processing world, but at the price of buying a NVIDIA card.

cibercitizen1
A: 

I bet this only works on Windows

kovica
A: 

Here is how it works:

The way you create the image is correct. But Java does not accelerate the image right away. There is a threshold of render calls that need to be directed at your image after which the image will be accelerated. But if you set the following,

-Dsun.java2d.accthreshold=0

your image should be accelerated the moment you create it.

You might still have to use the image somehow for it to become accelerated. For example, i have the following code piece that is used to copy a loaded image (loading through ImageIO will give you an image that can not be accelerated) into my new BufferedImage.

Graphics2D g2d = bufferedImage.createGraphics();
g2d.drawImage(image,0,0,null);
g2d.dispose();

Before this code segment, the BufferedImage is not accelerated, afterwards it is.

But beware, if you manipulate the image data directly (i.e. not through Java-2d) your image will no longer be cached in VRAM and you have to copy it over to a new Managed Image in order to regain your acceleration.

Stefan Schmidt
+1  A: 

From my investigation and reading the Sun/Oracle 2D tutorial this is what I've found:

To create an accelerated image one can either use the volatile image, which is created as a pbuffer. There are advantages and disadvantages, VolatileImages are fast until you try to get the raster pixel data. At that moment they become a normal bufferedImage. Also they are volatile and there is no guarantee that it will be available in the end of your rendering. To do this you execute:

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
VolatileImage vImage = gc.createCompatibleVolatileImage(width, height, Transparency.TRANSLUCENT);

This will get you a accelerated image, however it is not possible to use the ImageIO to write it directly to say a PNG file.

In order to use a normal BufferedImage you need to do something like:

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
BufferedImage img = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
img.setAccelerationPriority(1);

This creates a BufferedImage which is not accelerated but you give the hint to the JVM that is should by passing 1 in setAccelerationPriority. This you can read on the 2D trail of the Java Tutorial.

Paulo Lopes