我在尝试
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
。我可以看到它们略有不同,但我不明白为什么会存在这种行为。发生什么事了?
稍微修改了你的代码。我不喜欢(原始)代码不断创建屏幕图像的子图像以与实际的子图像进行比较。仍然没有帮助找到匹配的人。
我的下一步是从原始屏幕图像创建子图像。这是测试问题是否出在逻辑或子图像上的方法。在这种情况下,子图像匹配。
然后我回去测试两个机器人创建的图像,并注意到宽度/高度较小的子图像会匹配。
进一步测试,宽度似乎并未影响子图像的匹配。
但是,我注意到高度确实造成了问题。在我的例子中,高度需要比屏幕高度小 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”偏移。