<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Dejan on Technology &#187; Drawing</title>
	<atom:link href="http://www.vesic.org/english/blog/category/drawing/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.vesic.org/english/blog</link>
	<description>dotNet, ASP.Net, Programming, Software ...</description>
	<lastBuildDate>Mon, 01 Mar 2010 09:07:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>How to render Html content into JPG/JPEG image in best quality (WinForms)</title>
		<link>http://www.vesic.org/english/blog/winforms/render-html-to-quality-jpeg/</link>
		<comments>http://www.vesic.org/english/blog/winforms/render-html-to-quality-jpeg/#comments</comments>
		<pubDate>Wed, 28 Feb 2007 15:34:44 +0000</pubDate>
		<dc:creator>Dejan Vesić</dc:creator>
				<category><![CDATA[.Net]]></category>
		<category><![CDATA[Drawing]]></category>
		<category><![CDATA[WinForms]]></category>

		<guid isPermaLink="false">http://www.vesic.org/english/blog/winforms/render-html-to-quality-jpeg/</guid>
		<description><![CDATA[On recent project, I had a tasks to:
<ol>
	<li>Save result of Html page to JPG image</li>
	<li>To do that in best possible quality</li>
</ol>
	
Both tasks sounds trivial, but I did not find quite satisfying solutions, so, I came up with one bellow...]]></description>
			<content:encoded><![CDATA[<h2>How to save Html to JPG/JPEG Image and how to save it in best quality?</h2>
<p>On recent project, I had a tasks to:</p>
<ol>
<li>Save result of Html page to JPG image</li>
<li>To do that in best possible quality</li>
</ol>
<p>Both tasks sounds trivial, but I did not find quite satisfying solutions, so, I came up with one bellow.</p>
<p>First, you need <a href="http://msdn2.microsoft.com/en-us/library/system.windows.forms.webbrowser.aspx">WebBrowser</a> control &#8211; it is basicaly wrapper around ActiveX Internet Explorer interface.</p>
<p>Once when Html content is ready (local or remote), ask control to call your procedure upon completion:</p>
<p><code>webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);</code></p>
<p>and start render your content:</p>
<p><code>webBrowser1.Navigate(  UriToRender )</code></p>
<p>In DocumentCompletedEventHandler, call your routine for rendering content to image:</p>
<pre>
void webBrowser1_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
  if( GetImageFromHtml(currentFile, webBrowser1) )
  {
     toolStripStatusLabel1.Text = "Image saved.";
  }
  else
  {
     toolStripStatusLabel1.Text = "Sorry, there was problem with saving.";
  }
}</pre>
<p>And here is code for rendering Html to image:</p>
<pre>
/// &lt;summary&gt;
/// Method for saving Html content into image
/// &lt;/summary&gt;
/// &lt;param name="imageName"&gt;File name of image&lt;/param&gt;
/// &lt;param name="webBrowser"&gt;Target WebBrowser control to query for content&lt;/param&gt;
/// &lt;returns&gt;True if save was succesfull&lt;/returns&gt;
/// &lt;seealso cref="System.Windows.Forms.WebBrowser" /&gt;

public bool GetImageFromHtml(string imageName, WebBrowser webBrowser)
{
  if (webBrowser.Document == null)
  {
     return false;
  }

  Cursor current = Cursor;
  Cursor = Cursors.WaitCursor;

  // Give time to WebBrowser control to finish rendering of document
  Thread.Sleep(200);

  try
  {

     // save old width / height
     Size originalSize = new Size(webBrowser1.Width, webBrowser1.Height);

     // Change to full scroll size
     int scrollHeight = webBrowser.Document.Body.ScrollRectangle.Height;
     int scrollWidth = webBrowser.Document.Body.ScrollRectangle.Width;

     Bitmap image = new Bitmap(scrollWidth, scrollHeight);
     webBrowser.Size = new Size(scrollWidth, scrollHeight);

     // Draw to image
     webBrowser.DrawToBitmap(image, webBrowser.ClientRectangle);
     webBrowser.Size = originalSize;

     // Old one with bad quality:
     // image.Save(imageName, ImageFormat.Jpeg);

     // Save in full quality
     SaveJPG(image, imageName, 100);

     return true;
  }

  catch { return false; }

  finally {  Cursor = current; }
}
</pre>
<p>Usual <a href="http://msdn2.microsoft.com/en-us/library/9t4syfhh.aspx">Image.Save</a> method saves image in number of formats; however, quality is some default (bad) quality; and I needed more control over it. So, here are methods which allow that kind of control:</p>
<pre>
/// &lt;summary&gt;
/// Gets codec info by given mimeType
/// &lt;/summary&gt;
/// &lt;param name="mimeType"&gt;mimeType to lookup for&lt;/param&gt;
/// &lt;returns&gt;ImageCodecInfo if all ok or null&lt;/returns&gt;

public static ImageCodecInfo GetCodecInfo(String mimeType)
{
  ImageCodecInfo[] encoders;
  encoders = ImageCodecInfo.GetImageEncoders();
  for (int iterator = 0; iterator &lt; encoders.Length; ++iterator)
  {
     if (encoders[iterator].MimeType == mimeType)
        return encoders[iterator];
  }
  return null;
}

/// &lt;summary&gt;
/// Save an Image to JPEG with given compression quality
/// &lt;/summary&gt;
/// &lt;param name="image"&gt;Image to save&lt;/param&gt;
/// &lt;param name="imageName"&gt;File name to store image&lt;/param&gt;
/// &lt;param name="quality"&gt;Quality parameter: 0 - lowest quality, smallest size,
/// 100 - max quality and size&lt;/param&gt;
/// &lt;returns&gt;True if save was succesfull&lt;/returns&gt;

public static bool SaveJPG(Image image, string imageName, long qual)
{
  EncoderParameters eps = new EncoderParameters(1);
  eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qual);
  ImageCodecInfo ici = GetCodecInfo("image/jpeg");

  if(ici == null) { return false; }

  image.Save(imageName, ici, eps);
  return true;
}
</pre>
<p>Now you can select jpeg image quality and render html the way you like.</p>
<p><a href="http://digg.com/programming/How_to_render_Html_content_into_JPG_JPEG_image_in_best_quality_WinForms"><img src="http://digg.com/img/badges/91x17-digg-button.png" width="91" height="17" alt="Digg!" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.vesic.org/english/blog/winforms/render-html-to-quality-jpeg/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

