c# - 裁剪图像时出现 OutofMemory 错误

标签 c# image selenium bitmap out-of-memory

下面是我正在尝试的代码,但出现内存不足异常。

我正在尝试从通过 selenium 拍摄的屏幕截图中仅裁剪一个元素的图像。

            byte[] image= driver.GetScreenshot().AsByteArray;
                using (MemoryStream sourceStream = new MemoryStream(image))
                {
                    using (Bitmap source = new Bitmap(sourceStream))
                    {

                        Rectangle cropzone = new Rectangle(element.Location.X, element.Location.Y, element.Size.Width, element.Size.Height);
                        using (Bitmap croppedBitmap = source.Clone(cropzone, source.PixelFormat))
                        {
                            croppedBitmap.Save(file_name, System.Drawing.Imaging.ImageFormat.Png);
                        }
                    }
                }

最佳答案

当裁剪矩形位于屏幕截图之外时,会引发内存不足异常。如果屏幕截图包含整个页面,则需要使用相对于页面的位置来裁剪元素。如果没有,则需要将目标元素滚动到 View 中并使用相对于 View 的位置进行裁剪。

这是一个用于截取 WebElement 屏幕截图的扩展方法:

static class WebElementExt {

    public static Bitmap TakeScreenshot(this OpenQA.Selenium.IWebElement element) {
        RemoteWebDriver driver = (RemoteWebDriver)((RemoteWebElement)element).WrappedDriver;

        if (((IHasCapabilities)driver).Capabilities.HasCapability("takesElementScreenshot")) {

            byte[] bytes = ((RemoteWebElement)element).GetScreenshot().AsByteArray;
            return (Bitmap)Bitmap.FromStream(new MemoryStream(bytes, 0, bytes.Length, false, true), false, false);

        } else {
            var dict = (Dictionary<String, Object>)driver.ExecuteScript(@"
                arguments[0].scrollIntoView(true);
                var r = arguments[0].getBoundingClientRect(), scrollX = 0, scrollY = 0;
                for(var e = arguments[0]; e; e=e.parentNode) {
                  scrollX += e.scrollLeft || 0;
                  scrollY += e.scrollTop || 0;
                }
                return {left: r.left|0, top: r.top|0, width: r.width|0, height: r.height|0
                       , scrollX: scrollX, scrollY: scrollY, innerHeight: window.innerHeight}; "
                , element);

            var rect = new System.Drawing.Rectangle(
                Convert.ToInt32(dict["left"]),
                Convert.ToInt32(dict["top"]),
                Convert.ToInt32(dict["width"]),
                Convert.ToInt32(dict["height"]));

            byte[] bytes = driver.GetScreenshot().AsByteArray;
            using (Bitmap bitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(bytes, 0, bytes.Length, false, true), false, false)) {

                if (bitmap.Height > Convert.ToInt32(dict["innerHeight"]))
                    rect.Offset(Convert.ToInt32(dict["scrollX"]), Convert.ToInt32(dict["scrollY"]));

                rect.Intersect(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height));
                if (rect.Height == 0 || rect.Width == 0)
                    throw new WebDriverException("WebElement is outside of the screenshot.");

                return bitmap.Clone(rect, bitmap.PixelFormat);
            }
        }
    }
}

还有一个使用示例:

var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://stackoverflow.com");

driver.FindElementById("svnrev")
      .TakeScreenshot()
      .Save(@"screenshot-element.png", ImageFormat.Png);

driver.Quit();

关于c# - 裁剪图像时出现 OutofMemory 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36996831/

相关文章:

c# - 从不同项目的 appsettings.json 中读取多个连接字符串

将 JPEG 图像转换为黑白图像

java - ImageView 不能正确拉伸(stretch)图像

internet-explorer - Selenium RC 和 IE 脚本错误 - 远程过程调用失败

java - 如何断言包含以下内容的 if 语句

selenium - 无法进行模式匹配

c# - DateTime代表C#中的多少位

c# - 如何在基于 DDD 的应用程序中实现结账?

带有淡入/淡出的图像替换(画廊风格)

c# - 如何让 LINQ 返回具有给定属性最大值的对象?