12

I have a transparent BufferedImage created with the following code(not relevant how it is created, I think):

            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();

            Rectangle screen = transformationContext.getScreen();

            // Create an image that supports transparent pixels
            return gc.createCompatibleImage((int) screen.getWidth(), (int) screen.getHeight(),
                    Transparency.BITMASK);

How do I clear the image(empty image in the same state as it was created) in the fastest way possible without recreating the image? Recreating the image puts a burden on GC, pausing the VM and freezing the UI.

adrian.tarau
  • 3,124
  • 2
  • 26
  • 29

2 Answers2

20

Got it :) used clearRect instead of fill with a transparent color.

            graphics = (Graphics2D) offlineBuffer.getGraphics();
            graphics.setBackground(new Color(255, 255, 255, 0));
            Rectangle screen = transformationContext.getScreen();
            graphics.clearRect(0,0, (int)screen.getWidth(), (int)screen.getHeight());
adrian.tarau
  • 3,124
  • 2
  • 26
  • 29
  • 6
    `clearRect` is said to be deprecated since 1.1 although it isn't tagged as such (maybe because annotations didn't exist yet?). The preferred way is now: `graphics.setComposite(AlphaComposite.Clear); graphics.fillRect(0, 0, SIZE, SIZE); graphics.setComposite(AlphaComposite.SrcOver);` (assuming SrcOver was the composite you used before, and is the default) This is actually close to the implementation of `clearRect`. – Mark Jeronimus Apr 25 '12 at 05:33
  • there is no deprecation tag in the java doc, so I presume it's still valid – adrian.tarau May 10 '12 at 13:27
  • @adrian.tarau that's what he's referring to; annotations. The javadocs are generated automatically; since the `@Deprecated` annotation isn't in the code (it hadn't existed yet) then it wasn't in the javadocs. – Qix - MONICA WAS MISTREATED Dec 18 '12 at 01:57
  • This works but it seems the text rendering is affected by the bacground color chosen when anti aliasing is enabled. I got a better result with `new Color(0, 0, 0, 0)`. – Emmanuel Bourg Jan 29 '21 at 14:04
9

One relatively fast way, but I don't know if it's the fastest (and I'd like to see other answers) is to have another picture that you never modify and that is always "fully cleared" / "fully transparent" and then you do a raster copy, say you named that copy CLEAR:

imageYouWantToClear.setData( CLEAR.getRaster() );

Note that working with graphics can be very tricky when it comes to performances because there are a lot of not-very-well-documented behavior. For example your images (say the CLEAR one) may be hardware-accelerated but you'd then lose hardware-acceleration as soon as you'd use a mutating method (like say a setRgb()) and it would prove very difficult to realize that you just lost the benefit of hardware acceleration.

I think that the best place to find infos on the subject of performant BufferedImage would be in the Java game-programmers and Java game-API-programmers community/forums.

Btw make sure that both your BufferedImage are using the 'compatible' mode: TYPE_INT_ARGB may be fine on Windows but not on OS X, etc. so you want to create them doing something like:

GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);

Ouch the Law-of-Demeter hurts, thanks Java ;)

SyntaxT3rr0r
  • 27,745
  • 21
  • 87
  • 120
  • Thanks WizardOfOdds but keeping another image(which needs to be recreated when the "active" image is recreated because the bounds change) will increase memory usage(think of 1600x1200 screen resolution). clearRect does the trick and it seems pretty fast. – adrian.tarau Mar 02 '10 at 23:01
  • I tried this with Java 8 on Windows 10 but that was ~50x slower than `clearRect()`. – Emmanuel Bourg Jan 29 '21 at 13:10