Recently I was working in a project wherein we needed to generate PDFs from Html pages. While in the process of investigating various methods to achieve the same. One idea struck into my mind was to get the snapshot of the webpage programmatically and insert that into the pdf. However this solution was not used in the project I was working on but the idea of getting the snapshot of the webpage stuck into my mind.
Hence I decided to try that how can we programmatically get the snapshot of any url provided and save it in any image format. This is what I am going to share in this post.
In order to get the snapshot of a webpage, we need to instantiate an object of WebBrowser class and pass the url to its navigate method. The webbrowser class is available in System.Windows.Forms namespace.
Note: If you are working in a web application you need to add the reference of System.Windows.Forms in your solution.
Further we need to set the width and height of the WebBrowser object. The width and height specifies the width and height of the snapshot to be generated of the webpage whose URL has been provided.
Then we need to call the DrawToBitmap method of the webBrowser object to load the snapshot into a bitmap object.
Further, You can use graphics object to manipulate the image and save it in any format.
In the code snippet below GenerateScreenShot method does the task for us. However, this WebBrowser object cannot be used in a Multithreaded Apartment state, hence In the page_load method, I had defined a new thread and set its Apartment State as SingleThreaded.
using System.Text;
using System.Web.UI;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Collections;
using System;
protected void Page_Load(object sender, EventArgs e)
{
Thread webBrowseThread = new Thread(new ThreadStart(GenerateScreenshot));
webBrowseThread.SetApartmentState(ApartmentState.STA);
webBrowseThread.Start();
}
//this method on providing the url of the webpage copies the image of that webpage.
public void GenerateScreenshot()
{
string url = "http://www.go4coding.com/post/2011/05/30/Getting-Screenshot-of-a-web-page-in-aspnet.aspx";
int width = 1024;
try
{
DateTime timeStamp = DateTime.Now;
// Load the webpage into a WebBrowser control
WebBrowser wb = new WebBrowser();
wb.ScrollBarsEnabled = false;
wb.ScriptErrorsSuppressed = true;
wb.Navigate(url);
WebBrowserReadyState flag = wb.ReadyState;
while (flag != WebBrowserReadyState.Complete && DateTime.Now < timeStamp.AddSeconds(10))
{
System.Windows.Forms.Application.DoEvents();
flag = wb.ReadyState;
TimeSpan elapsed = DateTime.Now.Subtract(timeStamp);
}
wb.Width = wb.Document.Body.ScrollRectangle.Width;
wb.Height = wb.Document.Body.ScrollRectangle.Height;
if (wb.Width < width)
{
// Take Screenshot of the web pages full width
wb.Width = width;
}
// Get a Bitmap representation of the webpage as it's rendered in the WebBrowser control
Bitmap bitmap = new Bitmap(wb.Width, wb.Height);
wb.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, wb.Width, wb.Height));
Graphics Grfx = Graphics.FromImage(bitmap);
Grfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
Grfx.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
Grfx.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
Grfx.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
Grfx.DrawImage(bitmap, 0, 0, wb.Width, wb.Height);
wb.Dispose();
SplitAndSaveImages(bitmap);
}
catch (Exception ex)
{
}
}
Here, Since My code generates a single bitmap for the complete webpage and the webpage may be very long. So, I defined and called a method SplitAndSaveImages(Bitmap bitmap).
This Method splits the image into multiple images of size equivalent to the visible screen area and saves them to a folder specified.
protected void SplitAndSaveImages(Bitmap input)
{
try
{
int height = input.Height;
int width = input.Width;
if (input.Height > 768)
{
int y = 0;
while (y < height)
{
using (Bitmap img = input.Clone() as Bitmap)
{
Bitmap newimage = img.Clone(new System.Drawing.Rectangle(0, y, width, height - y > 768 ? 768 : height - y), img.PixelFormat);
newimage.Save(@"D:\BitmapSplit\Output\" + "output" + y.ToString() + ".bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
y += 768;
}
}
else
{
using (Bitmap img = input.Clone() as Bitmap)
{
Bitmap newimage = img.Clone(new System.Drawing.Rectangle(0, 0, width, height), img.PixelFormat);
newimage.Save(@"D:\BitmapSplit\Output\" + "output.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
}
}
catch (Exception ex)
{
}
}
Hope, You all find it useful..
Cheers!!