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

Smaller screen capture not equal to a subimage of a capture of the entire screen

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      Tested on several computers and operating systems

      A DESCRIPTION OF THE PROBLEM :
      I encountered some weird behavior while experimenting with `java.awt.Robot`. If I use it to take two screenshots, one of the entire screen and one of just a subsection of the screen, the subsection of the screen has different pixels than a subimage of the original screenshot with the same coordinates as the subsection screenshot. Here is my code:

      ```
      import java.awt.AWTException;
      import java.awt.Dimension;
      import java.awt.Rectangle;
      import java.awt.Robot;
      import java.awt.Toolkit;
      import java.awt.image.BufferedImage;
      import java.io.File;
      import java.io.IOException;
      import javax.imageio.ImageIO;

      public class ScreenCapTest {
          public static void main(String[] args) throws AWTException, IOException {
              // Construct Robot
              Robot r = new Robot();
              
              // Get dimensions of screen
              Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
              
              // Take screenshot
              BufferedImage screen = r.createScreenCapture(new Rectangle(0,0, (int)screenSize.getWidth(), (int)screenSize.getHeight()));
              
              // Take screenshot of small section of screen
              int x = 5;
              int y = 5;
              int w = 50;
              int h = 50;
              BufferedImage subscreen = r.createScreenCapture(new Rectangle(x,y,w,h));
              
              // Create a subimage of the same section of the screen from the original screenshot
              BufferedImage subimageOfScreen = screen.getSubimage(x,y,w,h);
              
              // Are they equal?
              System.out.println(imgEqual(subimageOfScreen, subscreen));
              
              // Output images for comparison
              ImageIO.write(subimageOfScreen, "png", new File("subimage.png"));
              ImageIO.write(subscreen, "png", new File("subscreen.png"));
          }
          
          public static boolean imgEqual(BufferedImage image1, BufferedImage image2) {
              int width;
              int height;
              boolean imagesEqual = true;

              if( image1.getWidth() == ( width = image2.getWidth() ) &&
                  image1.getHeight() == ( height = image2.getHeight() ) ){

                  for(int x = 0;imagesEqual == true && x < width; x++){
                      for(int y = 0;imagesEqual == true && y < height; y++){
                          if( image1.getRGB(x, y) != image2.getRGB(x, y) ){
                              imagesEqual = false;
                          }
                      }
                  }
              } else {
                  imagesEqual = false;
              }
              return imagesEqual;
          }
      }
      ```

      Most of the time, it reports false, meaning that the subimage of a full screenshot from (5,5) to (55,55) is different from the screenshot of the screen from (5,5) to (55,55). Weirdly, for some values of x, y, w, and h, it prints true.

      I can see that the saved images are slightly different, but I don't understand why this behavior exists. What's going on?

      This question is currently being discussed on StackOverflow at https://stackoverflow.com/questions/77727691/java-awt-robot-why-doesnt-a-smaller-screen-capture-equal-a-subimage-of-a-captu

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Compile and run the code in the description with a static window

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Console reads "true"
      ACTUAL -
      Console reads "false"

      ---------- BEGIN SOURCE ----------
      import java.awt.AWTException;
      import java.awt.Dimension;
      import java.awt.Rectangle;
      import java.awt.Robot;
      import java.awt.Toolkit;
      import java.awt.image.BufferedImage;
      import java.io.File;
      import java.io.IOException;
      import javax.imageio.ImageIO;

      public class ScreenCapTest {
          public static void main(String[] args) throws AWTException, IOException {
              // Construct Robot
              Robot r = new Robot();
              
              // Get dimensions of screen
              Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
              
              // Take screenshot
              BufferedImage screen = r.createScreenCapture(new Rectangle(0,0, (int)screenSize.getWidth(), (int)screenSize.getHeight()));
              
              // Take screenshot of small section of screen
              int x = 5;
              int y = 5;
              int w = 50;
              int h = 50;
              BufferedImage subscreen = r.createScreenCapture(new Rectangle(x,y,w,h));
              
              // Create a subimage of the same section of the screen from the original screenshot
              BufferedImage subimageOfScreen = screen.getSubimage(x,y,w,h);
              
              // Are they equal?
              System.out.println(imgEqual(subimageOfScreen, subscreen));
              
              // Output images for comparison
              ImageIO.write(subimageOfScreen, "png", new File("subimage.png"));
              ImageIO.write(subscreen, "png", new File("subscreen.png"));
          }
          
          public static boolean imgEqual(BufferedImage image1, BufferedImage image2) {
              int width;
              int height;
              boolean imagesEqual = true;

              if( image1.getWidth() == ( width = image2.getWidth() ) &&
                  image1.getHeight() == ( height = image2.getHeight() ) ){

                  for(int x = 0;imagesEqual == true && x < width; x++){
                      for(int y = 0;imagesEqual == true && y < height; y++){
                          if( image1.getRGB(x, y) != image2.getRGB(x, y) ){
                              imagesEqual = false;
                          }
                      }
                  }
              } else {
                  imagesEqual = false;
              }
              return imagesEqual;
          }
      }
      ---------- END SOURCE ----------

      FREQUENCY : always


        1. ScreenCapTest.java
          2 kB
          Praveen Narayanaswamy

            azvegint Alexander Zvegintsev
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: