Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4464621

VolatileImage is very slow with read operations (translucency and scaling)

XMLWordPrintable

    • 2d
    • beta3
    • x86
    • windows_98, windows_2000



      Name: bsC130419 Date: 05/31/2001


      java version "1.4.0-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-beta-b65)
      Java HotSpot(TM) Client VM (build 1.4.0-beta-b65, mixed mode)

      VolatileImages are wonderful once if they have simple content, but creating and
      drawing on them using certain Graphics2D facilities can incur a hefty
      performance penalty that makes them unusuable in certain important cases. When
      testing the JDK1.4, I discovered a major performance drop in an application of
      mine that makes extensive use of double buffering. After recoding to take
      advantage of VolatileImages, the performance was even worse, which was
      certainly not what I expected.

      The problem is I draw extensively with AlphaComposites so that users can drag
      objects over a background and still see the background beneath the dragged
      objects. This is an important GUI idiom which Java really should not make
      impossible to implement.

        To determine where the problem lies, I wrote a short program that draws 1200
      colored rectangles (200x200) into a normal BufferedImage created by
      Component.createImage(w,h) and into a VolatileImage returned by
      Component.createVolatileImage(w,h). I did this twice, once with a standard
      solid color and once with a composite.

      The results (in milliseconds) are listed below for my Windows 2000 475MHz
      laptop:

          Times measured for drawing rectangles on top of each other using a
            SOLID color:
          standard image: 1102
          volatile image: 30

          Times measured for drawing rectangles on top of each other using a
            COMPOSITE (AlphaComposite) color:
          standard image: 5097
          volatile image: 21271 (!!!)

      As happy as I am about the speed up with the solid colors, the VolatileImage
      consistently takes 4 times as long as the BufferedImage when an AlphaComposite
      is used, which is bad, especially when the area of the rectangle gets larger.

      The (quickly and badly written) program that produced these results follows. I
      put the test in the paintComponent method so you can causing the window to draw
      itself runs the tests:

      import java.awt.*;
      import java.awt.image.*;
      import javax.swing.*;

      public class TestImageTypes {
          
          public static void main(String args[]) {
      JFrame app = new JFrame("Image Type Tester");
      boolean f = true;
      if (args.length>0 && args[0].equals("-solid")) f = false;
      else System.out.println("Testing composite color speeds.\n(java
      TestImageTypes -solid to test solid color speeds.)\n");
      app.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      app.getContentPane().add(new Tester(f));
      app.pack();
      app.setVisible(true);
          }
      }

      class Tester extends JPanel {
          static AlphaComposite myAlpha = AlphaComposite.getInstance
      (AlphaComposite.SRC_OVER, 0.65f);
          static Color myColor = new Color(124,23,188);
          Image im;
          VolatileImage vi;
          Graphics2D g1, g2;
          boolean flag;
          
          public Tester(boolean f) {
      flag = f;
          }
          
          public void createImages() {
      vi = this.createVolatileImage(200,200);
      g2 = (Graphics2D)vi.getGraphics();
      im = this.createImage(200,200);
      g1 = (Graphics2D)im.getGraphics();
          }
          
          private void recreateImage() {
      GraphicsConfiguration gc = this.getGraphicsConfiguration();
      if ((vi.validate(gc)) == VolatileImage.IMAGE_INCOMPATIBLE) {
      g2.dispose();
      vi = this.createVolatileImage(200,200);
      }
          }
          
          
          public void paintIt(Graphics2D g) {
      g.setColor(Color.white);
      g.fillRect(0,0,200,200);
      if (flag) g.setComposite(myAlpha);
      g.setColor(myColor);
      for (int x = 0; x<100; x++) {
      g.fillRect(x,0,100,200);
      }
      if (flag) g.setComposite(AlphaComposite.SrcOver);
          }
          
          public Dimension getPreferredSize() {
      return new Dimension(200,200);
          }
          
          public void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (vi == null) createImages();
      int i;
      long s = System.currentTimeMillis();
      for (i = 0; i<12; i++) {
      paintIt(g1);
      }
      System.out.println("standard image: "+(System.currentTimeMillis() - s));
      recreateImage();
      s = System.currentTimeMillis();
      for (i = 0; i<12; i++) {
      paintIt(g2);
      }
      System.out.println("volatile image: "+(System.currentTimeMillis() - s));
      g.drawImage(im, 0, 0, this);
          }
          
      }
      (Review ID: 125368)
      ======================================================================

      This is also affecting performance of Swing apps that use translucency effects
      (e.g., the calendar demo of JavaOne 2001).

      ------------------

      Updated the synopsis to reflect that this problem also affects scaling to
      a VolatileImage object, as described in bug 4504148.

      ###@###.### 2001-09-20

            chaasesunw Chet Haase (Inactive)
            bstrathesunw Bill Strathearn (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: