-1

I am trying to compare two images by checking for matching pixels in Java. This is normally no problem on my main desktop however when I port my code over to my laptop it does not work at all. My laptop is using a resolution of 2736 x 1824 however I think that is scaled up since when I take a screen shot the resulting image always has a size of 1368 x 912. Anyways I need a way to take screen shots of my desktop and compare it to a another smaller desktop image (I take them with the snipping tool). I also noticed that the bit depth of both images are different however they are also different on my desktop so I ruled that out.

Anyways as a little recap I assume snipping tool is taking the picture at 2736 x 1824 (just a section of the screen though) while robot.createScreenCapture is taking the screen shot at 1368 x 912. Is there a way I can take a screen shot at 2736 x 1824 in java so I can correctly get the pixel's RGB values?

private int xCenterPixel;
private int yCenterPixel;
private BufferedImage image;
private Robot robot;

public boolean checkImage(String path) {
    try {
        robot = new Robot();
    } catch (AWTException awtException) {
        awtException.printStackTrace();
        System.exit(-1);
    }

    File smallImage = new File(path);
    BufferedImage large = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));

    final BufferedImage small = getInitialImage(smallImage);

    final boolean containsImage = containsImage(large, small);
    System.out.println("Does contain: " + containsImage);
    return containsImage;
}

private BufferedImage getInitialImage(File file) {
    try {
        image = ImageIO.read(file);
        image = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
        image = ImageIO.read(file);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return image;
}

private boolean containsImage(BufferedImage large, BufferedImage small) {
    final int smallColor = small.getRGB(0, 0);

    for(int xLarge = 0; xLarge < large.getWidth(); xLarge++) {
        for(int yLarge = 0; yLarge < large.getHeight(); yLarge++) {
            final int largeColor = large.getRGB(xLarge, yLarge);

            if(largeColor == smallColor) {
                if(checkPixels(large, small, xLarge, yLarge)) {
                    xCenterPixel = xLarge + (small.getWidth() / 2);
                    yCenterPixel = yLarge + (small.getHeight() / 2);
                    return true;
                }
            }
        }
    }
    return false;
}

Also if I can figure out how to take a picture in 2736 x 1824 I can just divide my resulting centerX and centerY by 2 to convert to 1368 x 912 which is what the rest of my program uses. Also this is not all of my code this is just the parts leading up the issue specifically the (largeColor == smallColor) part. if anyone has any suggestions please let me know!

UnSure
  • 9
  • 5
  • The obvious solutions that come to my mind would be: either you scale the smaller image up or you scale the larger image down. As you want to compare the both, it only would make sense to scale the larger image down, but you have to take care how you calculate the mean value of the 4x4 pixels - this should be done in a manner that the pixel values stay comparable, or you build in some tolerance for the comparison. – cyberbrain Apr 10 '22 at 18:06
  • But of course the better solution would be that both tools do screenshots without or with the same scaling. Try to find out, what your real screen resolution is (e.g. with the Windows Tool "System Information" in the Components/Display section). – cyberbrain Apr 10 '22 at 18:08
  • It says my resolution is 2736 x 1824 but for some reason using Java's screen capture tool only gives me an image of 1368 x 912. Also after testing I can confirm that the snipping tool uses the native resolution so when I take a small screen shot the pixel density will be different. Is there a way I can easily scale one of these values, an api maybe? Or is there a way to take a screen shot in Java with your native resolution (I have no idea why robot.screenCapture gives me an image of 1368 x 912). – UnSure Apr 10 '22 at 18:33

1 Answers1

0

You can either look at this question, that shows a handful of answers how to scale an image in Java: How to scale a BufferedImage

Or you try to use Robot.createMultiResolutionScreenCapture​ - be sure to check its JavaDoc, it contains a nice example how to fetch the native resolution. I just put the link to Java 11 there, but it should be available since Java 9.

cyberbrain
  • 1,338
  • 7
  • 16
  • How can I turn MultiResolutionImage into a BufferedImage? – UnSure Apr 10 '22 at 19:06
  • For comparison of the two images, you could use a `java.awt.PixelGrabber` to extract the data into an `int[]`. You also could check if the resulting `Image` is actually an instance of `BufferedImage` as `Image` is just an abstract class. Or you create your own implementation of `ImageConsumer`, add it to the `ImageProducer` from `getSource` and each call of one of the methods compares to the other `BufferedImage` until you receive the `imageComplete` call. – cyberbrain Apr 10 '22 at 19:22