Java AWT 机器人:为什么较小的屏幕捕获不等于整个屏幕捕获的子图像?

问题描述 投票:0回答:1

我在尝试

java.awt.Robot
时遇到了一些奇怪的行为。如果我用它来拍摄两张屏幕截图,一张是整个屏幕,一张是屏幕的一小部分,则屏幕的这一部分与原始屏幕截图的子图像具有不同的像素,而原始屏幕截图的子图像与该部分屏幕截图具有相同的坐标。这是我的代码:

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;
    }
}

大多数时候,它会报告

false
,这意味着从(5,5)到(55,55)的完整屏幕截图的子图像与从(5,5)到(55)的屏幕截图不同, 55)。奇怪的是,对于
x
y
w
h
的某些值,它会打印
true

下面是一对 BufferedImage 示例,代码会打印

false
。我可以看到它们略有不同,但我不明白为什么会存在这种行为。发生什么事了?

完整屏幕截图的子图:

屏幕同一部分的截图:

java awt screen-capture awtrobot
1个回答
0
投票

稍微修改了你的代码。我不喜欢(原始)代码不断创建屏幕图像的子图像以与实际的子图像进行比较。仍然没有帮助找到匹配的人。

我的下一步是从原始屏幕图像创建子图像。这是测试问题是否出在逻辑或子图像上的方法。在这种情况下,子图像匹配。

然后我回去测试两个机器人创建的图像,并注意到宽度/高度较小的子图像会匹配。

进一步测试,宽度似乎并未影响子图像的匹配。

但是,我注意到高度确实造成了问题。在我的例子中,高度需要比屏幕高度小 31 像素。巧合的是,我的 Windows 计算机上任务栏的高度为 31 像素。所以我的想法是,不知何故,当使用机器人时,第二个图像没有正确创建。不知道为什么。

无论如何,这是我用来测试的代码:

import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;

public class ScreenCapTest2 {
    public static void main(String[] args) throws AWTException {
        Robot r = new Robot();
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        BufferedImage screen = r.createScreenCapture(new Rectangle(0,0, (int)screenSize.getWidth(), (int)screenSize.getHeight()));

        int xOffset = 20;
        int yOffset = 50;
        BufferedImage subscreen = screen.getSubimage(xOffset, yOffset, (int)screenSize.getWidth()-xOffset, (int)screenSize.getHeight()-yOffset);
//        BufferedImage subscreen = r.createScreenCapture(new Rectangle(xOffset, yOffset, (int)screenSize.getWidth()-xOffset, (int)screenSize.getHeight()-yOffset));
//        BufferedImage subscreen = r.createScreenCapture( new Rectangle(xOffset, 49, 1900, 1000) );

        System.out.println( screenSize );
        System.out.println(indexOfSubImage(screen, subscreen));
    }

    public static Point indexOfSubImage(BufferedImage img, BufferedImage subimg) {
        for (int x=0; x <= img.getWidth() - subimg.getWidth(); x++) {
            for (int y=0; y <= img.getHeight() - subimg.getHeight(); y++) {
//                if (imgEqual(img.getSubimage(x, y, subimg.getWidth(), subimg.getHeight()), subimg)) {
                if (imgEqual(x, y, img, subimg)) {
                    return new Point(x,y);
                }
            }
        }
        return new Point(-1,-1);
    }

    public static boolean imgEqual(int offsetX, int offsetY, BufferedImage image1, BufferedImage image2) {

        for(int x = 0; x < image2.getWidth(); x++){
            for(int y = 0; y < image2.getHeight(); y++){
                if( image1.getRGB(x + offsetX, y + offsetY) != image2.getRGB(x, y) ){
                    return false;
                }
            }
        }

        return true;
    }
}

第一个子图像在不同的测试用例中适用于我。

第二个子图像仅在使用 (0, 0) 作为偏移量时才有效。

第三个子图像似乎适用于最大 49 的所有“y”偏移。

© www.soinside.com 2019 - 2024. All rights reserved.