Should I explicitly dispose the Graphics object?
Asked Answered
C

3

6

The javadoc said:

For efficiency, programmers should call dispose when finished using a Graphics object only if it was created directly from a component or another Graphics object.

So in the following code, should I call graphics.dispose() before returning? Or, can I?

{  ...  
BufferedImage result = new BufferedImage(toWidth, toHeight, BufferedImage.TYPE_INT_RGB);  

java.awt.Graphics graphics=result.getGraphics();

graphics.drawImage(im.getScaledInstance(toWidth, toHeight, java.awt.Image.SCALE_SMOOTH), 0, 0, null);  

return result;  
}

The BufferedImage result is returned and used elsewhere.

Cooler answered 26/3, 2015 at 8:46 Comment(8)
Since result and it's associated graphics object (graphics) go out of scope after the method call, I'd say yes.Entomophilous
Java returns Objects by reference. So if he disposes the graphics object, can he use it again for the returned object? I have no idea, maybe someone can answer this as well.Galloromance
@Galloromance If he disposes it, he can't use it anymore.Maureen
@Kayaman, so he shouldn't dispose it in this method, as he returns the BufferedImage and may wants to use it later. Correct?Galloromance
what are the results of disposing it in this method, and then calling getGraphics() again on the returned result?Margiemargin
Yes, the result is returned and used elsewhere.Cooler
@Galloromance No. He should dispose of the Graphics object, and if he wants to reuse it, get it again from the BufferedImage.Maureen
@Kayaman, yes I just realized that and posted a small example to show this behaviourGalloromance
T
8

The Graphics object can be disposed and should be disposed.

The getGraphics call of BufferedImage internally delegates to createGraphics, so there is no difference. The createGraphics call eventually delegates to the respective GraphicsEnvironment implementation, where (for the SunGraphicsEnvironment) it creates a new instance of a SunGraphics2D.

Finally, the dispose method of SunGraphics2D says the following:

  /**
   * This object has no resources to dispose of per se, but the
   * doc comments for the base method in java.awt.Graphics imply
   * that this object will not be useable after it is disposed.
   * So, we sabotage the object to prevent further use to prevent
   * developers from relying on behavior that may not work on
   * other, less forgiving, VMs that really need to dispose of
   * resources.
   */
  public void dispose() {
      surfaceData = NullSurfaceData.theInstance;
      invalidatePipe();
  }

which also gives a justification of why dispose indeed should be called (even if it is not strictly necessary in the default implementations)

Tightlipped answered 26/3, 2015 at 9:7 Comment(0)
G
1
public class Main{

    public static void main(String[] args) {
        BufferedImage img = get();

        Graphics g = img.getGraphics();

        //g.drawOval(5, 5, 5, 5); //this statement will work (you'll see the cirle)

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write( img, "jpg", baos );

            baos.flush();
            byte[] imageInByte = baos.toByteArray();
            baos.close();

            Files.write(Paths.get("test2.png"), imageInByte);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    public static BufferedImage get(){
        BufferedImage res = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);

        Graphics g = res.getGraphics();

        g.drawRect(0, 0, 20, 20);

        g.dispose();

        g.drawOval(5, 5, 5, 5); //this statement won't work, you'll only see the rect

        return res;
    }


}

As you can see, you can savely (and should) dispose the graphics in your method.

You can't use the graphics object in the method afterwards, so when you run the code, there won't be a circle in the picture. But if you comment out g.drawOval(5,5,5,5) in the method, but comment in the same statement in the main-Method, you will see a circle. So you can use it afterwards.

Galloromance answered 26/3, 2015 at 9:5 Comment(0)
H
0

Because due to JavaDoc getGpahics() method forwards to createGraphics() you should dispose the Graphics object at the end of your method.

Huckaback answered 26/3, 2015 at 9:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.