Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Tagged as

Creating Website Thumbnails in ASP.NET

, 19 Oct 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
Creating a small thumbnail image of a website can be a useful task. This is particularly the case with sites that are directories of websites. A thumbnail helps give the user some idea about the content of a site that they might click to visit. Although there are a couple of gotchas, doing this fro

Creating a small thumbnail image of a website can be a useful task. This is particularly the case with sites that are directories of websites. A thumbnail helps give the user some idea about the content of a site that they might click to visit.

Although there are a couple of gotchas, doing this from ASP.NET is fairly straight forward. The process involves creating a WebBrowser control to load and render the website image, and write that image to a bitmap.

The WebBrowser control is an ActiveX control. Normally, you create one of these by placing it on a Windows Form. Here, we'll just create one dynamically without any form. One problem is that this control can only be created in a single-threaded apartment. This is the tricky part of this code. We need to create a new thread, set its apartment state to single-threaded apartment, and then run it. This worker thread will create the control and generate the thumbnail. Listing 1 shows my code for the WebsiteThumbnail class.

using System.Drawing;
using System.Threading;
using System.Web;
using System.Windows.Forms;

namespace SoftCircuits
{
  public class WebsiteThumbnail
  {
    protected string _url;
    protected int _width, _height;
    protected int _thumbWidth, _thumbHeight;
    protected Bitmap _bmp;

    /// <span class="code-SummaryComment"><summary>
</span>    /// Generates a website thumbnail for the given URL
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="url">Address of website from which to generate the
</span>    /// thumbnail<span class="code-SummaryComment"></param>
</span>    /// <span class="code-SummaryComment"><param name="width">Browser width</param>
</span>    /// <span class="code-SummaryComment"><param name="height">Browser height</param>
</span>    /// <span class="code-SummaryComment"><param name="thumbWidth">Width of generated thumbnail</param>
</span>    /// <span class="code-SummaryComment"><param name="thumbHeight">Height of generated thumbnail</param>
</span>    /// <span class="code-SummaryComment"><returns></returns>
</span>    public static Bitmap GetThumbnail(string url, int width, int height,
      int thumbWidth, int thumbHeight)
    {
      WebsiteThumbnail thumbnail = new WebsiteThumbnail(url, width, height,
        thumbWidth, thumbHeight);
      return thumbnail.GetThumbnail();
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Protected constructor
    /// <span class="code-SummaryComment"></summary>
</span>    protected WebsiteThumbnail(string url, int width, int height, int thumbWidth,
      int thumbHeight)
    {
      _url = url;
      _width = width;
      _height = height;
      _thumbWidth = thumbWidth;
      _thumbHeight = thumbHeight;
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Returns a thumbnail for the current member values
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><returns>Thumbnail bitmap</returns>
</span>    protected Bitmap GetThumbnail()
    {
      // WebBrowser is an ActiveX control that must be run in a single-threaded
      // apartment so create a thread to create the control and generate the
      // thumbnail
      Thread thread = new Thread(new ThreadStart(GetThumbnailWorker));
      thread.SetApartmentState(ApartmentState.STA);
      thread.Start();
      thread.Join();
      return _bmp;
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Creates a WebBrowser control to generate the thumbnail image
    /// Must be called from a single-threaded apartment
    /// <span class="code-SummaryComment"></summary>
</span>    protected void GetThumbnailWorker()
    {
      using (WebBrowser browser = new WebBrowser())
      {
        browser.ClientSize = new Size(_width, _height);
        browser.ScrollBarsEnabled = false;
        browser.ScriptErrorsSuppressed = true;
        browser.Navigate(_url);
        // Wait for control to load page
        while (browser.ReadyState != WebBrowserReadyState.Complete)
          Application.DoEvents();
        // Render browser content to bitmap
        _bmp = new Bitmap(_thumbWidth, _thumbHeight);
        browser.DrawToBitmap(_bmp, new Rectangle(0, 0, _thumbWidth, _thumbHeight));
      }
    }
  }
}

Listing 1. WebsiteThumbnail Class

Initially, this class required you to create an instance of it and then call the GetThumbnail() method on that instance. However, I changed it to have a single static GetThumbnail() method to simplify its usage. (I've made all the other members protected.)

To generate a thumbnail image, just call WebsiteThumbnail.GetThumbnail(). The first argument is the URL of the website to generate the thumbnail from. Next are the dimensions of the browser window. This affects how large of an area will be included in the image. And, finally, the last two arguments specify the dimensions of the thumbnail. The method returns a bitmap, which you can save to a file or write to a database.

Although there are a number of services on the web for performing this task, it's nice to be able to perform it right within your application. Hopefully, this code will help you out.

NOTE: I have a shared hosting account where this code fails. I have yet to determine exactly what is happening but the entire application just seems to die at the point the worker thread is created. This code works fine on my test computer. As near as I can tell, it is related to a limitation on the shared hosting account. I will report back here if I can further isolate exactly what the issue is.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Jonathan Wood
Black Belt Coder
United States United States
Jonathan Wood has been a software developer for more years than he cares to admit. His current focus is on using C# and ASP.NET MVC to develop website applications, and C++ and MFC to develop desktop applications. His consulting company, SoftCircuits, is known for producing various commercial and shareware products.
 
Having an entrepreneurial spirit, Jonathan also has a number of other online businesses that he built from scratch such as Black Belt Coder, Trail Calendar and others. He also has expertise in designing brands (including graphics and logos) and search-engine optimization (SEO).
 
Jonathan is always willing to discuss consulting work or joint ventures with people looking to develop software or online businesses.
Follow on   Twitter

Comments and Discussions

 
GeneralMy vote of 5 Pinmembermillerbill3-Oct-12 1:30 
Generalcomment... Pinmemberemicroxxx18-May-12 22:13 
QuestionExample how to use it in asp.net webform PinmemberMohammad Owidat26-Oct-10 3:01 
SuggestionRe: Example how to use it in asp.net webform PinmemberPaulSpencerChapman30-Oct-12 10:51 
AnswerRe: Example how to use it in asp.net webform PinmemberJonathan Wood30-Oct-12 10:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 19 Oct 2010
Article Copyright 2010 by Jonathan Wood
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid