Sid
Sid

Reputation: 327

Getting OutofMemory error while cropping image

Below is the code I'm trying, but getting outofmemory exception.

I'm trying to crop image of only an element from a screenshot taken through 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);
                        }
                    }
                }

Upvotes: 2

Views: 968

Answers (2)

Florent B.
Florent B.

Reputation: 42518

The Out of memory exception is raised when the cropping rectangle is outside of the screenshot. If the screenshot contains the full page, then the element needs to be cropped with a position relative to the page. If not, then the targeted element needs to be scrolled into the view and cropped with a position relative to the view.

Here is an extension method to take a screenshot of a 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);
            }
        }
    }
}

And a usage example:

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

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

driver.Quit();

Upvotes: 2

Linh Tuan
Linh Tuan

Reputation: 448

I used to work selenium this my code share for you:

public static Bitmap GetEntereScreenshot(IWebDriver driver)
        {
            Bitmap stitchedImage = null;
            try
            {
                var jse = (IJavaScriptExecutor)driver;
                jse.ExecuteScript("window.scrollTo(0, 0);");

                var jqueryLibrary = TestExtensions.GetConfigValue("jquery_library", "");
                var js = new JqueryExtension(driver, jqueryLibrary);
                var driverBrowser = ((RemoteWebDriver)driver).Capabilities.BrowserName;
                //driver_browser= 1: Internet Explorer, 2: Firefox, 3: Google Chrome
                int totalWidth;
                int totalHeight;
                if (driverBrowser.Equals("internet explorer"))
                {
                    var totalwidth1 = (Int64)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.offsetWidth;");
                    var totalHeight1 = (Int64)((IJavaScriptExecutor)driver).ExecuteScript("return document.body.parentNode.scrollHeight;");
                    totalWidth = (int)totalwidth1;
                    totalHeight = (int)totalHeight1;
                }
                else
                {
                    totalWidth = js.GetSizePage("$(document).width();");
                    totalHeight = js.GetSizePage("$(document).height();");
                }

                // Get the Size of the Viewport
                var viewportWidth1 = js.GetSizePage("$(window).width();");
                //var viewportHeight1 = driverBrowser == "2" ? totalHeight : js.GetSizePage("$(window).height();");
                int viewportHeight1;

                switch (driverBrowser)
                {
                    case "internet explorer":
                        if (((RemoteWebDriver)driver).Capabilities.Version == "8" || ((RemoteWebDriver)driver).Capabilities.Version == "9")
                        {
                            viewportHeight1 = totalHeight;
                        }
                        else
                        {
                            viewportHeight1 = js.GetSizePage("$(window).height();");
                        }
                        break;
                    case "firefox":
                        viewportHeight1 = totalHeight;
                        break;
                    default:
                        viewportHeight1 = js.GetSizePage("$(window).height();");
                        break;
                }

                var viewportWidth = viewportWidth1;
                var viewportHeight = viewportHeight1;
                // Split the Screen in multiple Rectangles
                var rectangles = new List<Rectangle>();
                // Loop until the Total Height is reached
                for (var i = 0; i < totalHeight; i += viewportHeight)
                {
                    var newHeight = viewportHeight;

                    // Fix if the Height of the Element is too big
                    if (i + viewportHeight > totalHeight)
                    {
                        newHeight = totalHeight - i;
                    }
                    // Loop until the Total Width is reached
                    for (var ii = 0; ii < totalWidth; ii += viewportWidth)
                    {
                        var newWidth = viewportWidth;
                        // Fix if the Width of the Element is too big
                        if (ii + viewportWidth > totalWidth)
                        {
                            newWidth = totalWidth - ii;
                        }

                        // Create and add the Rectangle
                        var currRect = new Rectangle(ii, i, newWidth, newHeight);
                        rectangles.Add(currRect);
                    }
                }
                // Build the Image
                stitchedImage = new Bitmap(totalWidth, totalHeight);
                // Get all Screenshots and stitch them together
                var previous = Rectangle.Empty;
                foreach (var rectangle in rectangles)
                {
                    // Calculate the Scrolling (if needed)
                    if (previous != Rectangle.Empty)
                    {
                        var xDiff = rectangle.Right - previous.Right;
                        var yDiff = previous.Height;//rectangle.Bottom - previous.Bottom;
                       ((IJavaScriptExecutor)driver).ExecuteScript(String.Format("window.scrollBy({0}, {1})", xDiff, yDiff));

                        System.Threading.Thread.Sleep(500);
                    }

                    // Take Screenshot
                    var screenshot = ((ITakesScreenshot)driver).GetScreenshot();

                    // Build an Image out of the Screenshot
                    Image screenshotImage;
                    using (var memStream = new MemoryStream(screenshot.AsByteArray))
                    {
                        screenshotImage = Image.FromStream(memStream);
                    }

                    // Calculate the Source Rectangle  
                    var sourceRectangle = new Rectangle(viewportWidth - rectangle.Width, viewportHeight - rectangle.Height, rectangle.Width, rectangle.Height);

                    // Copy the Image
                    using (var g = Graphics.FromImage(stitchedImage))
                    {
                        g.DrawImage(screenshotImage, rectangle, sourceRectangle, GraphicsUnit.Pixel);
                    }
                    // Set the Previous Rectangle
                    previous = rectangle;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            return stitchedImage;
        }

Upvotes: 0

Related Questions