Skip to main content

Drawing transparent image is incredibly slow - please help!

6 replies [Last post]
olly_olly
Offline
Joined: 2007-02-22

I've written an application that loads an image and draws a repeated grid of this image to the screen like a chessboard. When I use a jpeg or a png (with no transparency) I can draw 1000 of these instantaneously (or at least fast enough for my purposes). When I use a transparent image (for example I am testing with a coloured ball on a white background and then the same ball but with 'no' background), it takes approximately 17 seconds to draw the final image (of 1000 balls). This is a program that I was working on some time ago and as I remember it, it worked fine. Since I last used it I have reinstalled my OS and put on a newer version of NetBeans (and JDK). Is this a known problem or is there something else going on here?

I am running Windows XP. The image I was testing with is 185 x 185 pixels (so not big).

I essentially load the file and create a copy (as it is used elsewhere),

// Create an exact copy of the buffered image
WritableRaster raster = shapeImage.copyData( null );
BufferedImage shapeImageCopy = new BufferedImage( shapeImage.getColorModel(), raster, shapeImage.isAlphaPremultiplied(), null );

then I do an affine transform to get it the right size and then...

// Draw the image onto the canvas
g.drawRenderedImage(shapeImage, affine_scale);

The problem is purely with transparent png's but I need to use these! As I said, for jpeg and non-transparent pngs everything is absolutely fine.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
olly_olly
Offline
Joined: 2007-02-22

Dmitri -

Thanks for all the suggestions (Jan - you might be interested in what I found):

1) Tried this and made no difference
2) This was what I was doing! Sorry that was my bad post. I am copying everything to a BufferedImage and then writing this to the screen.
3) I tried using non-default pipelines - no difference
4) I tried disabling directdraw - no difference

I knew that before I reinstalled the PC, everything worked fine. So, I tried my program on my flat mate's PC with JRE 1.5.0_07... and it worked perfectly. Images were rendered almost instantaneously. I then uninstalled Netbeans 5.5 and the JDK and JRE 6 on my PC and installed Netbeans 5.5 with JRE/JDK 1.5.0_11 and... perfect. Everything works exactly as it should and there is no difference in speed between jpg and png or png with transparency. In my mind, that can only mean that between 1.5.0_11 and version 6, something has gone wrong with the handling of transparent .png files.

Could you please tell me what happens now? I don't want to have a program that only works under 1.5.0_11 and below. Why would this have happened? Is there anything I can do on my end (apart from using the 1.5.0_11 JRE)?

Thanks

Olly

Dmitri Trembovetski

Hello,

java2d@javadesktop.org wrote:
> Dmitri -
>
> Thanks for all the suggestions (Jan - you might be interested in what I found):
>
> 1) Tried this and made no difference
> 2) This was what I was doing! Sorry that was my bad post. I am copying everything to a BufferedImage and then writing this to the screen.
> 3) I tried using non-default pipelines - no difference
> 4) I tried disabling directdraw - no difference
>

Well, this is indeed something strange.
Could you please run your app with -Dsun.java2d.trace=count flag for a
bit and send out
the output?

Since you say you copy the loaded images into another BufferedImages
and then
copy them to a back-buffer (again, I'm assuming it's opaque), the
changes in
loading png files should not have made any difference (unless you copy
then on every frame).

Thank you,
Dmitri

> I knew that before I reinstalled the PC, everything worked fine. So, I tried my program on my flat mate's PC with JRE 1.5.0_07... and it worked perfectly. Images were rendered almost instantaneously. I then uninstalled Netbeans 5.5 and the JDK and JRE 6 on my PC and installed Netbeans 5.5 with JRE/JDK 1.5.0_11 and... perfect. Everything works exactly as it should and there is no difference in speed between jpg and png or png with transparency. In my mind, that can only mean that between 1.5.0_11 and version 6, something has gone wrong with the handling of transparent .png files.
>
> Could you please tell me what happens now? I don't want to have a program that only works under 1.5.0_11 and below. Why would this have happened? Is there anything I can do on my end (apart from using the 1.5.0_11 JRE)?
>
> Thanks
>
> Olly
> [Message sent by forum member 'olly_olly' (olly_olly)]
>
> http://forums.java.net/jive/thread.jspa?messageID=204903
>
> ===========================================================================
> To unsubscribe, send email to listserv@java.sun.com and include in the body
> of the message "signoff JAVA2D-INTEREST". For general help, send email to
> listserv@java.sun.com and include in the body of the message "help".
>

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".

olly_olly
Offline
Joined: 2007-02-22

Sure - I will try this and let you know but... sorry to be stupid, but how do I do this exactly and what is the output and if it's a log file where will I find it?

Thanks

Olly

jbfaden
Offline
Joined: 2006-04-25

I've seen this too, where bufferedImage.getRGB() is very very slow under java 1.6, but works as expected under java 1.5.

rah003
Offline
Joined: 2004-05-26

> I am running Windows XP. The image I was testing with is 185 x 185 pixels (so not big).

Interesting. I had similar experience about month ago, but on linux. Since it was the 64 version I thought it is related to rather imature graphics drivers and their rendering support on that platform. Also since running the test I was able to reduce those times for type 1 images (created by loading transparent png) by nearly 50% only by tweaking graphics card setting.

Here are some times for different JDKs I got there (testbed for all except last test was Ubuntu with 2.6.17 kernel, running on Acer Ferrari 3400 (AMD 64bit)):
[pre]
jdk 1.6 x64
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0-b105, mixed mode)
drawImage() Finished with avg for type 0: 20.875 ms, for type 1: 5522.383 ms and for type 2: 131.428 ms.
jdk 1.6 x32
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)
drawImage() Finished with avg for type 0: 13.606 ms, for type 1: 75.116 ms and for type 2: 15.860 ms.
jdk 1.5 x64
Java HotSpot(TM) 64-Bit Server VM (build 1.5.0_06-b05, mixed mode)
drawImage() Finished with avg for type 0: 30.743 ms, for type 1: 1213.126 ms and for type 2: 58.197 ms.

Win XP/Intel:
Java HotSpot(TM) Server VM (build 1.6.0-b105, mixed mode)
drawImage() Finished with avg for type 0: 8.340 ms, for type 1: 82.637 ms and for type 2: 11.822 ms.
[/pre]

You could clearly see that the windows machine in last test had by far best results, but also that on same linux results widely varied depending on what version of JVM was the test executed. I can post whole test case (plus exact configuration of that linux test machine) in case anyone is interested.

Cheers,
Jan

Dmitri Trembovetski

Hello,

yes, 17 seconds seems to be very excessive.

Here is a couple of suggestions:
1. instead of using raster when when creating a copy of your image,
just do a drawImage into a new BufferedImage:
shapeImageCopy =
graphicsConfig.createCompatibleImage(
shapeImage.getWidth(), shapeImage.getHeight(),
shapeImage.getTransparency());
Graphics2D g2d = (Graphics2D)shapeImageCopy.getGraphics();
g2d.setComposite(AlplaComposite.Src);
g2d.drawImage(shapeImage, 0, 0, null);

(note that if you're going to scale these images anyway,
it could be better to create scaled copy in the first
place, instead of scaling it on every drawImage)

This will ensure that there is a possibility of caching
this image in Vram (depending on the pipeline used),
while your current method prevented that.

2. Instead of copying your images to the screen as you're
apparently doing, copy them to an offscreen image,
(either a BufferedImage (opaque), or a VolatileImage, or
BufferStrategy) and then copy that image to the screen.
(use the double buffering technique).
When you render to the screen, in order to do the compositing
with the destination pixels we have to read them back from vram,
which is an expensive operation.

Depending on your choice of the pipeline and whether your images
are translucent or not, you may chose different types of
back-buffers.

The default pipelines do not accelerate alpha compositing
(and transforms), so your best choice would be a BufferedImage
for a back-buffer.

For OpenGL or D3D pipelines, BufferStrategy or VolatileImages
would be better.

3. try using one of the non-default pipelines in jdk6
OpenGL (-Dsun.java2d.opengl=True), or Direct3D (-Dsun.java2d.d3d=True)

4. Probably the simplest way - disable the use of DirectDraw by
setting -Dsun.java2d.noddraw=true . This will probably help
even without changing your application, but I still suggest
following the advices above.

Thank you,
Dmitri
Java2D Team

On Thu, Feb 22, 2007 at 08:33:46AM -0800, java2d@javadesktop.org wrote:
> I've written an application that loads an image and draws a repeated grid of this image to the screen like a chessboard. When I use a jpeg or a png (with no transparency) I can draw 1000 of these instantaneously (or at least fast enough for my purposes). When I use a transparent image (for example I am testing with a coloured ball on a white background and then the same ball but with 'no' background), it takes approximately 17 seconds to draw the final image (of 1000 balls). This is a program that I was working on some time ago and as I remember it, it worked fine. Since I last used it I have reinstalled my OS and put on a newer version of NetBeans (and JDK). Is this a known problem or is there something else going on here?
>
> I am running Windows XP. The image I was testing with is 185 x 185 pixels (so not big).
>
> I essentially load the file and create a copy (as it is used elsewhere),
>
> // Create an exact copy of the buffered image
> WritableRaster raster = shapeImage.copyData( null );
> BufferedImage shapeImageCopy = new BufferedImage( shapeImage.getColorModel(), raster, shapeImage.isAlphaPremultiplied(), null );
>
>
> then I do an affine transform to get it the right size and then...
>
> // Draw the image onto the canvas
> g.drawRenderedImage(shapeImage, affine_scale);
>
> The problem is purely with transparent png's but I need to use these! As I said, for jpeg and non-transparent pngs everything is absolutely fine.
> [Message sent by forum member 'olly_olly' (olly_olly)]
>
> http://forums.java.net/jive/thread.jspa?messageID=204839
>
> ===========================================================================
> To unsubscribe, send email to listserv@java.sun.com and include in the body
> of the message "signoff JAVA2D-INTEREST". For general help, send email to
> listserv@java.sun.com and include in the body of the message "help".

===========================================================================
To unsubscribe, send email to listserv@java.sun.com and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
listserv@java.sun.com and include in the body of the message "help".