JDK-5073407 : Major buffered image render speed regression
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 1.1.2,5.0,6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000,windows_xp
  • CPU: x86
  • Submitted: 2004-07-13
  • Updated: 2005-01-04
  • Resolved: 2004-09-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
5.0u2Fixed 6 mustangFixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description

Name: rmT116609			Date: 07/13/2004


FULL PRODUCT VERSION :
java version "1.5.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b57)
Java HotSpot(TM) Client VM (build 1.5.0-beta3-b57, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

EXTRA RELEVANT SYSTEM CONFIGURATION :
Nvidia Geforce 2 GTS

A DESCRIPTION OF THE PROBLEM :
painting  TYPE_3BYTE_BGR bufferedImages onto a JPanel extremely slow.  Painfully slow compared with 1.4.2. and even 1.5 beta 1

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Simply paint any TYPE_3BYTE_BGR BufferedImage onto a JPanel adding a scale affine to the graphics in paintComponent. Attach a JSlider  to the scale value in the affine.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Sliding the JSlider causes the image zoom in and out on the panel. Using 1.4.2 this is silky smooth.
ACTUAL -
The zoom change is extremely  jerky and slow on 1.5 beta 3

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class ImageTest extends JFrame
{
    AffineTransform Trns;
    BufferedImage Img;

    JSlider VwZmSlider;
    JPanel PaintPanel;

    protected void setZoom(double newZoom)
    {
        Trns.setToScale(newZoom, newZoom);
    }

    public ImageTest()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Trns = new AffineTransform();
        Img = new BufferedImage(500, 500, BufferedImage.TYPE_3BYTE_BGR);

        PaintPanel = new JPanel()
        {
            protected void paintComponent(Graphics g)
            {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D)g;

                g2d.transform(Trns);
                g2d.drawImage(Img, 0, 0, this);
            }
        };

        Dimension Size = new Dimension(500, 500);
        PaintPanel.setPreferredSize(Size);
        PaintPanel.setMinimumSize(Size);
        PaintPanel.setMaximumSize(Size);

        VwZmSlider = new JSlider(0, 100, 50);
        VwZmSlider.addChangeListener(new ChangeListener()
        {
            public void stateChanged(ChangeEvent changeEvent)
            {
                int val = VwZmSlider.getValue();
                switch (val)
                {
                    case 0:
                        setZoom(0.1);
                        break;

                    case 15:
                        setZoom(0.5);
                        break;

                    case 30:
                        setZoom(0.75);
                        break;

                    case 50:
                        setZoom(1.0);
                        break;

                    case 70:
                        setZoom(1.5);
                        break;

                    case 85:
                        setZoom(2.0);
                        break;

                    case 100:
                        setZoom(3.0);
                        break;

                    default:
                        if (val > 0 && val < 15)
                        {
                            setZoom(((0.39 / 14.0) * (val - 1)) + 0.1);
                        }
                        else if (val > 15 && val < 30)
                        {
                            setZoom(((0.24 / 14.0) * (val - 15)) + 0.5);
                        }
                        else if (val > 30 && val < 50)
                        {
                            setZoom(((0.24 / 19.0) * (val - 30)) + 0.75);
                        }
                        else if (val > 50 && val < 70)
                        {
                            setZoom(((0.49 / 19.0) * (val - 50)) + 1.0);
                        }
                        else if (val > 70 && val < 85)
                        {
                            setZoom(((0.49 / 14.0) * (val - 70)) + 1.5);
                        }
                        else
                        {
                            setZoom(((0.99 / 14.0) * (val - 85)) + 2.0);
                        }
                        break;
                }
                PaintPanel.repaint();
            }
        });

        JPanel FillPanel = new JPanel();
        FillPanel.setLayout(new BorderLayout());

        FillPanel.add(PaintPanel, BorderLayout.CENTER);
        FillPanel.add(VwZmSlider, BorderLayout.SOUTH);

        getContentPane().add(FillPanel);
        pack();
        show();
    }

    public static void main(String[] args)
    {
        new ImageTest();
    }
}
---------- END SOURCE ----------
(Incident Review ID: 285594) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: dragon mustang FIXED IN: mustang INTEGRATED IN: mustang
30-09-2004

WORK AROUND The following conditional code in the paint method can be used to regain the pre-1.5.0 performance: if (workaround) { int w = (int) (500 * Trns.getScaleX()); int h = (int) (500 * Trns.getScaleY()); g2d.drawImage(Img, 0, 0, w, h, this); } else { g2d.transform(Trns); g2d.drawImage(Img, 0, 0, this); } If "workaround" is set to true then the performance will be on par with 1.4.2 even running on a 1.5.0 runtime. If "workaround" is set to false, then the performance regression in 1.5.0 will occur. ###@###.### 2004-09-28
28-09-2004

EVALUATION First manifested in 1.5-b36. More specifically, it first appeared in Java2D's nightly build on 2003-12-18.tiger (/net/jcg-x86-01/export3/Java2DBuilds/2003-12-18.tiger/). Webrev: /net/jcg-x86-01/export3/Java2DBuilds/2003-12-18.tiger/webrev Likely to be caused by the fix for 4916948: DrawImage does not interpolate with a translation-only AffineTransform since it seems to be only transform-related fix in this putback. ###@###.### 2004-07-13 Too late for tiger ###@###.### 2004-07-22 This performance regression is due to a recent change to be stricter about the mathematics of scaling and transforming images. One area of the math that was tightened up was that if the user installs a non-integer translation and requests bilinear or bicubic interpolation then we no longer round the location to a pixel boundary and decide to punt to a non-interpolating algorithm based on the rounded location. This change was made for correctness. The other area that was changed was that if we transform the bounds of an image and end up with non-integer coordinates for where its transformed corners lie then we no longer round those to integer boundaries either. This last change affects the code even if the default nearest-neighbor interpolation algorithm is used because the non-integer locations of the corners of the image can slightly change the stepping parameters used to choose which pixel to copy to the destination. If the sub-pixel locations are ignored then a program which smoothly zoomed and translated an image by small amounts of less than a pixel would exhibit an unnatural quantized step-like pattern to where the image apeared and which pixels were chosen. All of this stricter math is important for accuracy and it shouldn't cost us any performance since it is all in the setup code rather than in the inner loops of the image rendering routines, but the problem with the first pass at integrating the new code is that some of the internal interfaces were not set up to take floating point coordinates and so could only be used if the transformed image happened to end up falling with its corners exactly on integer boundaries. If the image fell on non-integer coordinates then we would punt to the general image transformation code which was much slower. There are a number of fixes we can do, but it is too late to integrate any of them into Tiger: - Change the code so that it is only strict if the RENDERING hint is set to QUALITY (or set to anything other than SPEED). This lets the user control the tradeoff between performance and accuracy. This fix is the simplest to integrate. - Change the internal interfaces on the code that we have to punt on to take floating point coordinates so that there is no performance loss even when the math is stricter. Upgrading the setup for these functions to floating point code is a small amount of code, but harder to get "right" than simply checking the RENDERING hint as in the first solution. - Implement new "general image transform" code that works more directly with our internal image formats so that the cost of punting to it is lower. This is a large amount of work, but we are already doing this anyway so it would be a matter of which release we can get this integrated into. This work is too extensive to go into Tiger, or any patches made for Tiger - it would need to wait for the next primary release after Tiger to be released. A prototype of the second solution shows that we can have both the accuracy of the new stricter calculations and have it perform as well as the 1.4 code which rounded everything to integers. If there is a patch release for Tiger then we will have to evaluate if we trust the code enough to use as a patch or see if we want to integrate a RENDERING hint workaround instead... ###@###.### 2004-08-07 The loops were udpated to take floating point coordinates for the destination rectangle and so we can now use them even if the scaled image does not fall on pixel boundaries. At the same time, some older inaccuracies in dealing with large image scales were taken care of. See 4631382 for more info. ###@###.### 2004-09-11
11-09-2004