UPDATE: It seems this is a bug in Java: https://bugs.java.com/bugdatabase/view_bug?bug_id=JDK-8322845
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.
Below is an example pair of BufferedImages for which the code prints false. I can see that they are slightly different, but I don't understand why this behavior exists. What's going on?


Modified your code a bit. I didn't like that the (original) code continually created a sub image of your screen image to compare to the actual subImage. Still didn't help finding a match.
My next step was to create the sub image from the original screen image. This is a way to test if the issue is with the logic or the sub image. In this case the sub image matched.
I then went back to testing the two Robot created images and noticed that sub images with smaller width/height would match.
Further testing and the width did not appear to impact the matching of the sub image.
However, I noticed that the height did cause a problem. In my case the height needed to be 31 pixels smaller than the height of the screen. By coincidence 31 pixels is the height of the taskbar on my Windows machine. So my thought is that somehow when using the Robot the second image is not created correctly. Have no idea why.
In any case here is the code I used to test:
The first subImage works for me in different test cases.
The second subImage only works when using (0, 0) as the offsets.
The third subImage seems to work on all "y" offsets up to 49.
Edit:
Using your new code I attempted to automate the testing:
I ran the code from the command prompt using:
java ScreenCapTest3.javaand got a mixture of true/false.I then ran the code using:
java ScreenCapTest.java > out.txtWhen I look at out.txt everything is true.
So it appears to me that there is a subtle change in the sub image because the System.out.println(...) is displayed on the screen BEFORE the second image is captured?
Created a simple frame to cover the desktop. I used the buttons on the left and a large image in the center to break up the white space of an empty frame.
When you click the button I used a Timer to delay the screen capture process to allow the button to be painted back in its original state.