Selenium Screenshot • November 2019

How to get an image of an element into memory for analysis.

I needed to grab an image of an element into memory so I could peek at the pixels to see how the data matched the graph. It was really more complicated than that as I did not have access to the data but needed to check some calculations based on the data.

Using my semi-adequate google-fu, I found how to save part of the screen to a file. All I had to do was skip the file part and have it in a bitmap so I could peek at the pixels.

Grab image of a control
										
public static Bitmap SnapScreenShot(By locator)
{
  Screenshot ss = ((ITakesScreenshot)Driver).GetScreenshot();
  Byte[] bytes = ss.AsByteArray;
  MemoryStream ms = new MemoryStream(bytes);
  Image img = Image.FromStream(ms);
  IWebElement element = Driver.FindElement(locator);
  Rectangle rect = new Rectangle(element.Location, element.Size);
  Rectangle dest = new Rectangle(Point.Empty, rect.Size);
  Bitmap cimg = new Bitmap(rect.Width, rect.Height);
  using (var graphics = Graphics.FromImage(cimg))
  {
    graphics.DrawImage(img, dest, rect, GraphicsUnit.Pixel);
  }
  return cimg;
}
										
									

Let's try to understand this mess.

									
Screenshot ss = ((ITakesScreenshot)Driver).GetScreenshot();
									
								

The driver is your selenium driver. This gets an image of the whole screen into some object called a Screenshot that I know nothing about. Next, use the member "AsByteArray" to get this data into an array of bytes.

Next I made this byte array into a "memory stream." Finally, we can load this memory stream into an image. Now, I have an image of the whole page, which might be pretty useful.


Byte[] bytes = ss.AsByteArray;
MemoryStream ms = new MemoryStream(bytes);
								

I was interested in just a part of this image, so I used Selenium to find the screen location given the "By." (I don't know if this is proper Seleniumese.)


IWebElement element = Driver.FindElement(locator);
Rectangle rect = new Rectangle(element.Location, element.Size);
Rectangle dest = new Rectangle(Point.Empty, rect.Size);
Bitmap cimg = new Bitmap(rect.Width, rect.Height);
using (var graphics = Graphics.FromImage(cimg))
{
  graphics.DrawImage(img, dest, rect, GraphicsUnit.Pixel);
}
return cimg;
								

After all this goofing around, I could examine the pixels of the image using .net graphics. I scanned each column of pixels looking for the curve. Then I did a little arithmetic, mulitplying the y position of the pixel by the "full scale" of the graph and dividing by the height of the image. Doing the same with the x position and width, I got the curve's position in the units of the graph and could compare this to the data to see if the graph as drawn was reasonably close to the input data.