Programmatically get a screenshot of the page

I am writing a specialized finder and parser for internal use, and I need the ability to take a screenshot of a web page to check what colors are used everywhere. The program will take about ten web addresses and save them as a bitmap.

From there, I plan to use LockBits to create a list of the five most used colors in the image. As far as I know, this is the easiest way to get the colors used on the web page, but if there is an easier way to do this, please call back with your suggestions.

Anyway, I was going to use ACA WebThumb ActiveX Control until I saw the price. I am also pretty new to C #, but only used it for a few months. Is there a solution to my problem to take a screenshot of a webpage to extract the color scheme?

+43
c # screenshot cutycapt iecapt
Dec 30 '09 at 18:25
source share
7 answers

https://www.url2png.com/docs is good. They have a free level.

You will need to use HttpWebRequest to load the binary image file. Here is an example:

HttpWebRequest request = HttpWebRequest.Create("https://api.url2png.com/v6/[API_KEY]/[API_TOKEN]/png/?url=[URL]") as HttpWebRequest; Bitmap bitmap; using (Stream stream = request.GetResponse().GetResponseStream()) { bitmap = new Bitmap(stream); } // now that you have a bitmap, you can do what you need to do... 

To create a url ...

 public static string url2png(string UrlToSite) { string url2pngAPIKey = "PXXX"; string url2pngPrivateKey = "SXXX"; string url = HttpUtility.UrlEncode(UrlToSite); string getstring = "fullpage=true&url=" + url; string SecurityHash_url2png = Md5HashPHPCompliant(url2pngPrivateKey + "+" + getstring).ToLower(); var url2pngLink = "http://api.url2png.com/v6/" + url2pngAPIKey + "/" + SecurityHash_url2png + "/" + "png/?" + getstring; return url2pngLink; } public static string Md5HashPHPCompliant(string pass) { System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] dataMd5 = md5.ComputeHash(Encoding.UTF8.GetBytes(pass)); StringBuilder sb = new StringBuilder(); for (int i = 0; i <= dataMd5.Length - 1; i++) { sb.AppendFormat("{0:x2}", dataMd5[i]); } return sb.ToString(); } 
+18
Mar 22
source share

A quick and dirty way is to use WinForms WebBrowser and draw it in a bitmap. Doing this in a stand-alone console application is somewhat difficult because you need to be aware of the consequences of hosting STAThread when using a fundamentally asynchronous programming pattern. But here is a working proof of the concept that captures a web page in a 800x600 BMP file:

 namespace WebBrowserScreenshotSample { using System; using System.Drawing; using System.Drawing.Imaging; using System.Threading; using System.Windows.Forms; class Program { [STAThread] static void Main() { int width = 800; int height = 600; using (WebBrowser browser = new WebBrowser()) { browser.Width = width; browser.Height = height; browser.ScrollBarsEnabled = true; // This will be called when the page finishes loading browser.DocumentCompleted += Program.OnDocumentCompleted; browser.Navigate("https://stackoverflow.com/"); // This prevents the application from exiting until // Application.Exit is called Application.Run(); } } static void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { // Now that the page is loaded, save it to a bitmap WebBrowser browser = (WebBrowser)sender; using (Graphics graphics = browser.CreateGraphics()) using (Bitmap bitmap = new Bitmap(browser.Width, browser.Height, graphics)) { Rectangle bounds = new Rectangle(0, 0, bitmap.Width, bitmap.Height); browser.DrawToBitmap(bitmap, bounds); bitmap.Save("screenshot.bmp", ImageFormat.Bmp); } // Instruct the application to exit Application.Exit(); } } } 

To compile this, create a new console application and be sure to add assembly links for System.Drawing and System.Windows.Forms .

UPDATE: I rewrote the code to avoid using the WaitOne / DoEvents pattern for hacker polling. This code should be closer to the following guidelines.

UPDATE 2:. You indicate that you want to use this in a Windows Forms application. In this case, forget about dynamically creating the WebBrowser . You want to create a hidden (Visible = false) instance of WebBrowser in your form and use it in the same way as shown above. Here is another example that shows part of the form’s user code with a text box ( webAddressTextBox ), a button ( generateScreenshotButton ) and a hidden browser ( WebBrowser ). Although I worked on this, I found a feature that I could not handle before - the DocumentCompleted event can be raised several times depending on the nature of the page. This sample should work as a whole, and you can expand it to do whatever you want:

 namespace WebBrowserScreenshotFormsSample { using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Windows.Forms; public partial class MainForm : Form { public MainForm() { this.InitializeComponent(); // Register for this event; we'll save the screenshot when it fires this.webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(this.OnDocumentCompleted); } private void OnClickGenerateScreenshot(object sender, EventArgs e) { // Disable button to prevent multiple concurrent operations this.generateScreenshotButton.Enabled = false; string webAddressString = this.webAddressTextBox.Text; Uri webAddress; if (Uri.TryCreate(webAddressString, UriKind.Absolute, out webAddress)) { this.webBrowser.Navigate(webAddress); } else { MessageBox.Show( "Please enter a valid URI.", "WebBrowser Screenshot Forms Sample", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); // Re-enable button on error before returning this.generateScreenshotButton.Enabled = true; } } private void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { // This event can be raised multiple times depending on how much of the // document has loaded, if there are multiple frames, etc. // We only want the final page result, so we do the following check: if (this.webBrowser.ReadyState == WebBrowserReadyState.Complete && e.Url == this.webBrowser.Url) { // Generate the file name here string screenshotFileName = Path.GetFullPath( "screenshot_" + DateTime.Now.Ticks + ".png"); this.SaveScreenshot(screenshotFileName); MessageBox.Show( "Screenshot saved to '" + screenshotFileName + "'.", "WebBrowser Screenshot Forms Sample", MessageBoxButtons.OK, MessageBoxIcon.Information); // Re-enable button before returning this.generateScreenshotButton.Enabled = true; } } private void SaveScreenshot(string fileName) { int width = this.webBrowser.Width; int height = this.webBrowser.Height; using (Graphics graphics = this.webBrowser.CreateGraphics()) using (Bitmap bitmap = new Bitmap(width, height, graphics)) { Rectangle bounds = new Rectangle(0, 0, width, height); this.webBrowser.DrawToBitmap(bitmap, bounds); bitmap.Save(fileName, ImageFormat.Png); } } } } 
+25
Dec 30 '09 at 19:26
source share

There is an excellent browser based on Webkit PhantomJS that allows you to execute any JavaScript from the command line.

Install it from http://phantomjs.org/download.html and run the following sample script from the command line:

 ./phantomjs ../examples/rasterize.js http://www.panoramio.com/photo/76188108 test.jpg 

It will create a screenshot of this page in a JPEG file. The potential of this approach is that you do not rely on any external provider and can easily automate the capture of images in large quantities.

+13
Jul 31 '12 at 8:38
source share

This question is old, but alternatively you can use the nuget Freezer package. It is free, uses the recent Gecko web browser (supports HTML5 and CSS3) and costs only one DLL.

 var screenshotJob = ScreenshotJobBuilder.Create("https://google.com") .SetBrowserSize(1366, 768) .SetCaptureZone(CaptureZone.FullPage) .SetTrigger(new WindowLoadTrigger()); System.Drawing.Image screenshot = screenshotJob.Freeze(); 
+11
Apr 21 '16 at 16:25
source share

Check this one . This seems to do what you wanted, and technically it approaches the problem in a similar way through web browser management. It seems that it served a number of parameters that should be passed, as well as good error handling built into it. The only drawback is that you create an external process (exe) and create a physical file that you will read later. From your description, you are even considering web services, so I don't think this is a problem.

When deciding your last comment on how to handle multiple of them at the same time, this will be ideal. You can run a parallel of 3, 4, 5 or more processes at any given time or analyze a color bit executed as a stream while another capture process is taking place.

For image processing, I recently met Emgu , havent used it myself, but it seems fascinating. He claims to be fast and has great support for graphical analysis, including pixel color readout. If I now have a graphics processing project, I will try.

+1
Mar 24 '10 at 20:57
source share

you can also take a look at QT jambi http://qt.nokia.com/doc/qtjambi-4.4/html/com/trolltech/qt/qtjambi-index.html

they have a good webkit-based java implementation for the browser, where you can take a screenshot just by doing sth like:

  QPixmap pixmap; pixmap = QPixmap.grabWidget(browser); pixmap.save(writeTo, "png"); 

Look at the samples - they have a good demonstration of the web browser.

+1
Apr 13 '10 at 16:00
source share

I used WebBrowser and it does not work perfectly for me, especially when I need to wait for JavaScript to complete. I tried several Api (s) and found Selenium , the most important thing in Selenium, it does not require STAThread and can run a simple console application, as well as services.

try:

 class Program { static void Main() { var driver = new FirefoxDriver(); driver.Navigate() .GoToUrl("http://stackoverflow.com/"); driver.GetScreenshot() .SaveAsFile("stackoverflow.jpg", ImageFormat.Jpeg); driver.Quit(); } } 
+1
Jun 15 '15 at 8:56
source share



All Articles