Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a hardware-accelerated image with Java2D?

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...

like image 997
Paulo Lopes Avatar asked Mar 03 '10 19:03

Paulo Lopes


2 Answers

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.

like image 116
Paulo Lopes Avatar answered Oct 25 '22 08:10

Paulo Lopes


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
like image 34
Ascalonian Avatar answered Oct 25 '22 07:10

Ascalonian