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

getBounds call on graphics.getDeviceConfiguration() returning cached information

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 6u16, 7, 7u45, 8, 8u31, 9
    • Fix Version/s: 9
    • Component/s: client-libs
    • Labels:
    • Subcomponent:
      2d
    • Resolved In Build:
      b89
    • CPU:
      x86
    • OS:
      windows_7

      Backports

        Description

        FULL PRODUCT VERSION :
        java version "1.7.0_45", java version "1.6.0_06". Since it is a simple bug I am sure it is there in java 8 also.

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows [Version 6.1.7601]

        A DESCRIPTION OF THE PROBLEM :
        When I call graphics.getDeviceConfiguration().getBounds() on a Graphics2D object got on a BufferedImage read from a file I continue to get the previous image dimensions after reading a new image.

        Please see details with sample program in steps to reproduce.


        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Below is a sample program which prints image bounds of jpeg files passed as command line args.

        Try calling it with paths to 2 images of different dimensions (Example: java GraphicsBug image1.jpg image2.jpg. The dimension of the first image is printed the second time also.

        import java.awt.Graphics2D;
        import java.awt.image.BufferedImage;
        import java.io.File;
        import java.io.IOException;

        import javax.imageio.ImageIO;
        import javax.imageio.ImageReader;
        import javax.imageio.stream.ImageInputStream;


        public class GraphicsBug {

            public static void loadJpeg(String imagePath) throws IOException {
                ImageReader reader;
                File srcImageFile = new File(imagePath);
                ImageInputStream iis = ImageIO.createImageInputStream(srcImageFile);
                reader = (ImageReader) ImageIO.getImageReaders(iis).next();
                reader.setInput(iis);
                BufferedImage image = reader.read(0);
                Graphics2D graphics = image.createGraphics();
                System.out.println("Image Bounds from Graphics = " + graphics.getDeviceConfiguration().getBounds());
            }

            public static void main(String [] args) throws IOException {
                for (int i = 0; i < args.length; i++) {
                    loadJpeg(args[i]);
                }
            }
        }


        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The correct image dimensions should be printed for each image. Below are two runs with Expected results:

        java GraphicsBug image1.jpg image2.jpg

        Image Bounds from Graphics = java.awt.Rectangle[x=0,y=0,width=496,height=64]
        Image Bounds from Graphics = java.awt.Rectangle[x=0,y=0,width=672,height=80]

        java GraphicsBug image2.jpg
        Image Bounds from Graphics = java.awt.Rectangle[x=0,y=0,width=672,height=80]
        ACTUAL -
        In the first run with 2 images the dimensions of the 1st image is duplicated:

        java GraphicsBug image1.jpg image2.jpg
        Image Bounds from Graphics = java.awt.Rectangle[x=0,y=0,width=496,height=64]
        Image Bounds from Graphics = java.awt.Rectangle[x=0,y=0,width=496,height=64]


        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.awt.Graphics2D;
        import java.awt.image.BufferedImage;
        import java.io.File;
        import java.io.IOException;

        import javax.imageio.ImageIO;
        import javax.imageio.ImageReader;
        import javax.imageio.stream.ImageInputStream;


        public class GraphicsBug {

            public static void loadJpeg(String imagePath) throws IOException {
                ImageReader reader;
                File srcImageFile = new File(imagePath);
                ImageInputStream iis = ImageIO.createImageInputStream(srcImageFile);
                reader = (ImageReader) ImageIO.getImageReaders(iis).next();
                reader.setInput(iis);
                BufferedImage image = reader.read(0);
                Graphics2D graphics = image.createGraphics();
                System.out.println("Image Bounds from Graphics = " + graphics.getDeviceConfiguration().getBounds());
            }

            // Pass Paths to 2 or more images with different dimensions and see the bound printed
            public static void main(String [] args) throws IOException {
                for (int i = 0; i < args.length; i++) {
                    loadJpeg(args[i]);
                }
            }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Do not use graphics.getDeviceConfiguration to get the image bounds get it directly from image.getWidth() and image.getHeight()

          Issue Links

            Activity

            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/aafc0a279f95
            User: lana
            Date: 2015-10-28 19:24:44 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/aafc0a279f95 User: lana Date: 2015-10-28 19:24:44 +0000
            Hide
            lbourges Laurent Bourgès added a comment -
            Is this change described in JDK9 release notes ?

            JOSM encountered that API behaviour change and the application code has been fixed to use graphics.getClipBounds() instead of graphics.getDeviceConfiguration().getBounds().

            It was figured out as an infinite dashed line was emitted from 0 to Integer.MAX_INT = 2E9 causing the application to hang / slow down.

            See https://josm.openstreetmap.de/ticket/15535
            Show
            lbourges Laurent Bourgès added a comment - Is this change described in JDK9 release notes ? JOSM encountered that API behaviour change and the application code has been fixed to use graphics.getClipBounds() instead of graphics.getDeviceConfiguration().getBounds(). It was figured out as an infinite dashed line was emitted from 0 to Integer.MAX_INT = 2E9 causing the application to hang / slow down. See https://josm.openstreetmap.de/ticket/15535
            Hide
            serb Sergey Bylokhov added a comment -
            I do not see a reason why the provided solution returns non-real values. This is a virtual graphic device which can have any possible bounds including MAX_INT, and this virtual device is used for a number of BufferedImages which can have different size. To depend on this value is the same thing as to depend on a bounds of the screen when draw something to the window on the screen or to draw to the VolatileImage.

            But the hang in the code below looks like a problem in our code. It is unclear why we allow the user to draw(or to try to draw) such huge lines, when obviously the clip is much smaller.
                g2.draw(normline); // <- infinite loop here (100% cpu)
            Show
            serb Sergey Bylokhov added a comment - I do not see a reason why the provided solution returns non-real values. This is a virtual graphic device which can have any possible bounds including MAX_INT, and this virtual device is used for a number of BufferedImages which can have different size. To depend on this value is the same thing as to depend on a bounds of the screen when draw something to the window on the screen or to draw to the VolatileImage. But the hang in the code below looks like a problem in our code. It is unclear why we allow the user to draw(or to try to draw) such huge lines, when obviously the clip is much smaller.     g2.draw(normline); // <- infinite loop here (100% cpu)
            Hide
            lbourges Laurent Bourgès added a comment -
            I agree Sergey's comment that this API behavior change enlightened a bug in the Java2D renderer, i.e in the Marlin renderer for JDK9.
            However this clipping issue exists for a long time: both Ductus & Pisces suffer the same problem on JDK8.

            The coming Marlin 0.8.2 patch provides new clipping filters for both Stroker & Filler, but some work remains to be done to handle clipping in the Dasher class (preserving dash phase has some complexity). I will create another bug about clipping in Marlin's Dasher.

            Finally the JDK9 release notes should mention that this bug has this 'known' problem (side-effect) caused by BufferedImage's Graphics.getDeviceConfiguration().getBounds()
            Show
            lbourges Laurent Bourgès added a comment - I agree Sergey's comment that this API behavior change enlightened a bug in the Java2D renderer, i.e in the Marlin renderer for JDK9. However this clipping issue exists for a long time: both Ductus & Pisces suffer the same problem on JDK8. The coming Marlin 0.8.2 patch provides new clipping filters for both Stroker & Filler, but some work remains to be done to handle clipping in the Dasher class (preserving dash phase has some complexity). I will create another bug about clipping in Marlin's Dasher. Finally the JDK9 release notes should mention that this bug has this 'known' problem (side-effect) caused by BufferedImage's Graphics.getDeviceConfiguration().getBounds()
            Hide
            lbourges Laurent Bourgès added a comment -
            See side-effect in Marlin Dasher (infinite line)
            Show
            lbourges Laurent Bourgès added a comment - See side-effect in Marlin Dasher (infinite line)

              People

              • Assignee:
                psadhukhan Prasanta Sadhukhan
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                8 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: