Selenium:java.awt.image.RasterFormatException:(y +高度)在使用元素大小和位置时在Raster之外

时间:2019-07-05 18:13:09

标签: java selenium

我有一个来自this教程的代码。它进入了learning-selenium-easy.blogspot.com网站,在“阅读次数最多/受欢迎的帖子”部分中查找并拍照:

 class SshotofElement {

    public static void screenShotElement() throws InterruptedException,IOException {
        System.setProperty("webdriver.chrome.driver", "chromedriver.exe");

        DesiredCapabilities capabilities = DesiredCapabilities.chrome();
        capabilities.setCapability("marionette", true);
        WebDriver driver = new ChromeDriver(capabilities);

        driver.get("http://learn-selenium-easy.blogspot.com/");
        driver.manage().window().maximize();

        // Xpath of element to take screen shot
        WebElement element=driver.findElement(By.xpath("//*[@id='PopularPosts1']"));
        System.out.println(element.getSize());
        File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

        // Take full screen screenshot
        BufferedImage  fullImg = ImageIO.read(screenshot);
        Point point = element.getLocation();
        int elementWidth = element.getSize().getWidth();
        int elementHeight = element.getSize().getHeight();
        BufferedImage elementScreenshot= fullImg.getSubimage(point.getX(), point.getY(), elementWidth,elementHeight);  //exception here

        // crop the image to required
        ImageIO.write(elementScreenshot, "png", screenshot);
        FileUtils.copyFile(screenshot, new File("mostread_screenshot.png"));//path to save screen shot

        driver.close();
    }
}

我遇到java.awt.image.RasterFormatException: (y + height) is outside of Raster异常,但是在第BufferedImage elementScreenshot= fullImg.getSubimage(point.getX(), point.getY(), elementWidth,elementHeight);行。我不确定为什么会这样,因为图像的点和大小是从元素本身获取的。

2 个答案:

答案 0 :(得分:1)

  1. 您正在裁剪的元素图像在代码拍摄的屏幕快照中不存在。如果您放置调试并打印全屏快照路径并手动查看,则可以看到其中没有从图像中裁剪出所需的元素。

  2. 因此,首先我们需要滚动页面,将所需元素带入视图,然后截取屏幕截图。然后我们需要根据元素的位置裁剪图像。

  3. 此外,Point类也不十分可靠,无法提供元素的确切位置。

  4. 第二,如果我们看到以下值

    ImageIO.read(screenshot).getHeight() // ~ 943 => Total height
    element.getSize().getHeight() // ~ 511 => Element height 
    point.getY() // ~ 743 => start top side y coordinate of element
    
  5. 所以我相信从x,y绘制高度为743的矩形时 超出了原始屏幕截图坐标。

所以我们需要在传递坐标的同时进行一些调整。

@Test
public void subImageTest() throws InterruptedException, IOException {
    driver.get("http://learn-selenium-easy.blogspot.com/");
    ((JavascriptExecutor)driver).executeScript("window.scrollBy(0,600)");
   File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);

    WebElement element=driver.findElement(By.xpath("//*[@id='PopularPosts1']"));
    System.out.println(element.getSize());

  // Take full screen screenshot
    BufferedImage  fullImg = ImageIO.read(screenshot);
    ImageIO.read(screenshot).getHeight()
    System.out.println(fullImg.getHeight()); 
    System.out.println(fullImg.getWidth());

    Point point = element.getLocation();
    int elementWidth = element.getSize().getWidth(); 
    int elementHeight = element.getSize().getHeight();

    // Now no exception here
    BufferedImage elementScreenshot= fullImg.getSubimage(220, 170,elementWidth+150,elementHeight+100);

    // crop the image to required
    ImageIO.write(elementScreenshot, "png", screenshot);
    FileUtils.copyFile(screenshot, new File("C:\\Users\\AppData\\Local\\Temp\\mostread_screenshot.png"));//path to save screen shot

}

程序执行后元素的最终子图像 enter image description here

答案 1 :(得分:1)

RasterFormatException

如果<{3}}中的布局信息无效,则会抛出 Java文档 RasterFormatException


getLocation()

根据硒文档 Raster返回包含该元素左上角位置的点。


getSubimage()

根据 Java文档 getLocation()返回由指定矩形区域定义的子图像。返回的BufferedImage与原始图像共享相同的数据数组,并定义为:

getSubimage
public BufferedImage getSubimage(int x,
                 int y,
                 int w,
                 int h)
Returns a subimage defined by a specified rectangular region. The returned BufferedImage shares the same data array as the original image.

Parameters: 
    x - the X coordinate of the upper-left corner of the specified rectangular region 
    y - the Y coordinate of the upper-left corner of the specified rectangular region 
    w - the width of the specified rectangular region 
    h - the height of the specified rectangular region 

Returns: 
    a BufferedImage that is the subimage of this BufferedImage. 

Throws: 
    RasterFormatException - if the specified area is not contained within this BufferedImage. 

我已经编写了自己的代码,并添加了几行System.out.println()以展示到底出了什么问题。

  • 代码块:

    public class A_demo 
    {
        public static void main(String[] args) throws Exception 
        {
                System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
                ChromeOptions options = new ChromeOptions();
                options.addArguments("start-maximized");
                options.addArguments("disable-infobars");
                WebDriver driver = new ChromeDriver(options);
                driver.get("http://learn-selenium-easy.blogspot.com/");
                // Xpath of element to take screen shot
                WebElement element=driver.findElement(By.xpath("//*[@id='PopularPosts1']"));
                System.out.println("Element size is:"+element.getSize());
                File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
                FileUtils.copyFile(screenshot, new File("./Screenshots/mostread_TakesScreenshot.png")); //path to save screen shot
    
                // Take full screen screenshot
                BufferedImage  fullImg = ImageIO.read(screenshot);
                Point point = element.getLocation();
                System.out.println("Co-ordinates where on the page is the top left-hand corner of the rendered element:"+point);
                int elementWidth = element.getSize().getWidth();
                System.out.println("Element width is:"+elementWidth);
                int elementHeight = element.getSize().getHeight();
                System.out.println("Element height is:"+elementHeight);
                BufferedImage elementScreenshot= fullImg.getSubimage(point.getX(), point.getY(), elementWidth,elementHeight);  //exception here
    
                // crop the image to required
                ImageIO.write(elementScreenshot, "png", screenshot);
                FileUtils.copyFile(screenshot, new File("./Screenshots/mostread_BufferedImage.png"));//path to save screen shot
        }    
    }
    
  • 控制台输出:

    INFO: Detected dialect: W3C
    Element size is:(340, 486)
    Co-ordinates where on the page is the top left-hand corner of the rendered element:(104, 744)
    Element width is:340
    Element height is:486
    Exception in thread "main" java.awt.image.RasterFormatException: (y + height) is outside of Raster
        at sun.awt.image.ByteInterleavedRaster.createWritableChild(Unknown Source)
        at java.awt.image.BufferedImage.getSubimage(Unknown Source)
        at demo.A_demo.main(A_demo.java:78)
    

说明

如前所述,按照您的代码块fullImg.getSubimage()将尝试返回BufferedImage,即 elementScreenshot ,它将是由矩形区域指定的子图像:

  • x:指定矩形区域左上角的X坐标-point.getX()- 104
  • y:指定矩形区域左上角的Y坐标-point.getY()- 744
  • w:指定矩形区域的宽度-elementWidth- 340
  • h:指定矩形区域的高度-elementHeight- 486

因此,BufferedImage的预期高度变为744 + 486 = 1230 ,这与光栅。因此,您会看到错误。


解决方案

要使用getSubimage()截取特定元素或特定div的屏幕截图,可以使用 AShot() 方法导入 ashot- Selenium Java Client v3.14.0 ChromeDriver v2.41 Chrome v 68.0 时为1.4.4.jar 。 / p>

  

注意 ashot-1.4.4.jar 中的 AShot() 方法仅在启用的情况下有效< em> Web应用程序。

  • 代码块:

    import ru.yandex.qatools.ashot.AShot;
    import ru.yandex.qatools.ashot.Screenshot;
    
    public class A_demo 
    {
        public static void main(String[] args) throws Exception 
        {
            System.setProperty("webdriver.chrome.driver", "C:\\Utility\\BrowserDrivers\\chromedriver.exe");
            ChromeOptions options = new ChromeOptions();
            options.addArguments("start-maximized");
            options.addArguments("disable-infobars");
            WebDriver driver = new ChromeDriver(options);
            driver.get("http://learn-selenium-easy.blogspot.com/");
            WebElement myWebElement = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='PopularPosts1']")));
            ((JavascriptExecutor)driver).executeScript("arguments[0].scrollIntoView();", myWebElement);
            Screenshot myScreenshot = new AShot().takeScreenshot(driver, myWebElement);
            ImageIO.write(myScreenshot.getImage(),"PNG",new File("./Screenshots/elementAShotScreenshot.png"));
            driver.quit();
        }    
    }
    

参考

您可以在以下位置找到一些相关的讨论


Outro

您可以在Selenium: Not able to take complete page screenshot using aShot library

中找到有关所有基于 Java 的屏幕截图方法的详细讨论。