.NET Image Creation Rendering a Black Box

Hello,

I've had code that creates a .JPG based off of the contents of a webpage running for 6-8 months now. All of a sudden, a black box is being rendered rather than the usual image, despite the fact that NO CODE HAS BEEN CHANGED.

This just, seemingly, randomly started happening. And it's only happening on our live server; our staging server and my local machine works just fine.

Any idea as to why this would happen?

Image is no longer rendering properly.
Here, we are getting the URL of the page we want to make an image out of. Going directly to the URL on the live server properly shows the image.
WebsiteToImage site = new WebsiteToImage(Request.Url.AbsoluteUri + "?rand=" + rInt, pathToUrl + rInt + ".jpg", divWidth + 75, divHeight + 300);
site.Generate();

Open in new window

        using System.Drawing;
        using System.Drawing.Imaging;

        public WebsiteToImage(string url, string fileName, int width, int height)
        {
            // With file 
            m_Url = url;
            m_FileName = fileName;
            m_Width = width;
            m_Height = height;
        }

        public Bitmap Generate()
        {
            // Thread 
            var m_thread = new Thread(_Generate);
            m_thread.SetApartmentState(ApartmentState.STA);
            m_thread.Start();
            m_thread.Join();
            return m_Bitmap;
        }
        private void _Generate()
        {
            var browser = new WebBrowser { ScrollBarsEnabled = false };
            browser.ScriptErrorsSuppressed = true;
            browser.Navigate(m_Url);
            browser.DocumentCompleted += WebBrowser_DocumentCompleted;

            while (browser.ReadyState != WebBrowserReadyState.Complete)
            {
                Application.DoEvents();
            }

            browser.Dispose();
        }
        private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            // Capture 
            var browser = (WebBrowser)sender;
            browser.ClientSize = new Size(m_Width, browser.Document.Body.ScrollRectangle.Height + 100);
            browser.ScrollBarsEnabled = false;
            m_Bitmap = new Bitmap(m_Width, browser.Document.Body.ScrollRectangle.Height + 100);
            browser.BringToFront();
            browser.DrawToBitmap(m_Bitmap, browser.Bounds);

            // Save as file? 
            if (m_FileName.Length > 0)
            {
                // Save 
                m_Bitmap.SaveJPG100(m_FileName);
            }

        public static void SaveJPG100(this Bitmap bmp, string filename)
        {
            var encoderParameters = new EncoderParameters(1);
            encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
            bmp.Save(filename, GetEncoder(ImageFormat.Jpeg), encoderParameters);
        }

Open in new window

infotechelgAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

infotechelgAuthor Commented:
Please let me know if you need more information.
0
infotechelgAuthor Commented:
Anyone?
0
infotechelgAuthor Commented:
So, I tried adding the following and the result is the same:

            browser.Document.BackColor = Color.Transparent;
            browser.Document.ForeColor = Color.Transparent;

Open in new window


I also added this to no avail:
            m_Bitmap.MakeTransparent();

Open in new window

0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

it_saigeDeveloperCommented:
First bitmaps do not support transparency which is why the box is rendered as black.  Second, it looks as if you are running into a timing issue (as a webpage loading can trigger the page completed event multiple times).  Give me a few and I'll throw a project together for you.

-saige-
0
it_saigeDeveloperCommented:
Using ideas from multiple sources:

http://www.codeproject.com/Articles/16422/How-To-Get-A-Website-Thumbnail-in-a-C-Application
http://www.codeproject.com/Articles/58605/HTML-to-Image-in-C?msg=4059086#xx4059086xx

Try this code -
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;

namespace EE_Q28693274
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void OnLoad(object sender, EventArgs e)
		{
			WebSiteToImage site = new WebSiteToImage(new Uri("http://www.experts-exchange.com/").AbsoluteUri, "experts-exchange.jpg");
			if (site.IsOk)
			{
				site.Generate();
				pictureBox1.Image = site.Bitmap;
			}
		}
	}

	[ComVisible(true), ComImport()]
	[GuidAttribute("0000010d-0000-0000-C000-000000000046")]
	[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
	public interface IViewObject
	{
		[return: MarshalAs(UnmanagedType.I4)]
		[PreserveSig]
		int Draw(
			[MarshalAs(UnmanagedType.U4)] UInt32 dwDrawAspect, 
			int lindex, IntPtr pvAspect, [In] IntPtr ptd, 
			IntPtr hdcTargetDev, IntPtr hdcDraw, 
			[MarshalAs(UnmanagedType.Struct)] ref Rectangle lprcBounds, 
			[MarshalAs(UnmanagedType.Struct)] ref Rectangle lprcWBounds, 
			IntPtr pfnContinue, 
			[MarshalAs(UnmanagedType.U4)] UInt32 dwContinue
			);

		[PreserveSig]
		int GetColorSet([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [In] IntPtr ptd, IntPtr hicTargetDev, [Out] IntPtr ppColorSet);

		[PreserveSig]
		int Freeze([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [Out] IntPtr pdwFreeze);

		[PreserveSig]
		int Unfreeze([In, MarshalAs(UnmanagedType.U4)] int dwFreeze);

		void SetAdvise([In, MarshalAs(UnmanagedType.U4)] int aspects, [In, MarshalAs(UnmanagedType.U4)] int advf, [In, MarshalAs(UnmanagedType.Interface)] IAdviseSink pAdvSink);

		void GetAdvise(
			[In, Out, MarshalAs(UnmanagedType.LPArray)] int[] paspects, 
			[In, Out, MarshalAs(UnmanagedType.LPArray)] int[] advf, 
			[In, Out, MarshalAs(UnmanagedType.LPArray)] IAdviseSink[] pAdvSink
			);
	}

	class WebSiteToImage
	{
		readonly WebBrowser browser;
		bool fIsGenerated = false;
		public string Url { get; private set; }
		public string FileName { get; private set; }
		public int Width { get; private set; }
		public int Height { get; private set; }
		public Bitmap Bitmap { get { return GetBitmap(); } }
		public string ErrorMessage { get; private set; }
		public bool IsOk { get; private set; }

		public WebSiteToImage(string url, string fileName, int width = -1, int height = -1)
		{
			Url = url;
			FileName = fileName;
			Width = (width != -1) ? width : 1024;
			Height = (height != -1) ? height : 768;

			try
			{
				HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Url);
				req.AllowAutoRedirect = true;
				req.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 1.1.4322)";
				req.Referer = "http://www.google.com/";
				req.ContentType = "text/html";
				req.Accept = "*/*";
				req.KeepAlive = false;

				using (HttpWebResponse response = (HttpWebResponse)req.GetResponse())
				{
					string x = response.StatusDescription;
				}
			}
			catch (Exception ex)
			{
				ErrorMessage = ex.Message;
				IsOk = false;
				return;
			}
			IsOk = true;

			browser = new WebBrowser();
			browser.DocumentCompleted += OnDocumentCompleted;
			browser.Size = new Size(Width, Height);
			browser.ScrollBarsEnabled = false;
			browser.ScriptErrorsSuppressed = true;
		}

		public bool Generate()
		{
			bool result = false;
			if (!fIsGenerated)
			{
				try
				{
					HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
					request.AllowAutoRedirect = true;
					request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 1.1.4322)";
					request.Referer = "http://www.google.com";
					request.ContentType = "text/html";
					request.AllowWriteStreamBuffering = true;
					request.AutomaticDecompression = DecompressionMethods.GZip;
					request.Method = "GET";
					request.Proxy = null;
					request.ReadWriteTimeout = 20;

					HttpStatusCode status;
					using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
						status = response.StatusCode;

					if (status == HttpStatusCode.OK || status == HttpStatusCode.Moved)
					{
						browser.Navigate(Url);
						while (browser.ReadyState != WebBrowserReadyState.Complete)
							Application.DoEvents();

						result = true;
					}
					else
						result = false;

					fIsGenerated = true;
				}
				catch (Exception ex)
				{
					ErrorMessage = ex.Message;
					result = fIsGenerated = false;
				}
				return result;
			}
			else
				return true;
		}

		private void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
		{
			if (sender is WebBrowser)
				((WebBrowser)sender).Document.Window.Error += SuppressScriptErrorsHandler;
		}

		private void SuppressScriptErrorsHandler(object sender, HtmlElementErrorEventArgs e)
		{
			e.Handled = true;
		}

		private Bitmap GetBitmap(int width = -1, int height = -1)
		{
			Bitmap result = default(Bitmap);
			if (Generate())
			{
				IViewObject ivo = browser.Document.DomDocument as IViewObject;
				Rectangle rect = new Rectangle(0, 0, Width, Height);
				Bitmap bitmap = new Bitmap(rect.Width, rect.Height);

				browser.DrawToBitmap(bitmap, rect);

				using (Graphics g = Graphics.FromImage(bitmap))
				{
					IntPtr ghdc = g.GetHdc();
					ivo.Draw(1, -1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ghdc, ref rect, ref rect, IntPtr.Zero, 0);
					g.ReleaseHdc(ghdc);
					g.Dispose();

					if (height == -1 || width == -1)
						result = bitmap;
					else if (height == Height && width == Width)
						result = bitmap;
					else
					{
						Bitmap thumbnail = new Bitmap(width, height);
						using (Graphics gfx = Graphics.FromImage(thumbnail))
						{
							// high quality image sizing
							gfx.SmoothingMode = SmoothingMode.HighQuality;
							gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
							gfx.DrawImage(bitmap, new Rectangle(0, 0, width, height), rect, GraphicsUnit.Pixel);
						}
						bitmap.Dispose();
						result = thumbnail;
					}
				}

				if (FileName.Length > 0)
					result.SaveJPG100(FileName);
			}
			return result;
		}
	}

	static class Extensions
	{
		private readonly static ImageCodecInfo[] fEncoders = ImageCodecInfo.GetImageEncoders();

		private static ImageCodecInfo GetEncoder(ImageFormat format)
		{
			return (from codec in fEncoders where codec.FormatID.Equals(format.Guid) select codec).FirstOrDefault();
		}

		public static void SaveJPG100(this Bitmap bmp, string filename)
		{
			var encoderParameters = new EncoderParameters(1);
			encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
			bmp.Save(filename, GetEncoder(ImageFormat.Jpeg), encoderParameters);
		}
	}
}

Open in new window


Which produces the following output -Capture.JPG-saige-
0
infotechelgAuthor Commented:
Saige,

Thank you for the reply!

I just added the transparent code to see if anything would happen; this was not in my original code.

Also, like I mentioned, this just randomly started happening, and I have no idea why (it was working fine for months).

Anyway, I'll take a look at your code and see what I can do. Thanks.
0
infotechelgAuthor Commented:
List of UpdatesA possible lead into the cause of the issue. I emailed our leasing company to ask if any updates were done to the Web server. And, indeed, on 6/20 (about the time this started happening), there were many .NET updates made to the server. Is it possible that one or more of these updates caused the issue?
0
it_saigeDeveloperCommented:
Anything is possible, but as I stated, it could also be a timing issue; e.g. - The page is not fully rendered when the bitmap image is created.

-saige-
0
infotechelgAuthor Commented:
Saige,

Thanks again for your assistance.

I implemented your code and received this error:

Threading Error
0
it_saigeDeveloperCommented:
Give me a few minutes.  I'll change this.

-saige-
0
infotechelgAuthor Commented:
Ok, thank you!
0
it_saigeDeveloperCommented:
Sorry about the delay.

Here is a rewrite that takes ASP.NET's processing model into account (similar to your original version):
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Windows.Forms;
using System.Threading;

namespace EE_Q28693274
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void OnLoad(object sender, EventArgs e)
		{
			WebSiteToImage site = new WebSiteToImage(new Uri("http://www.experts-exchange.com/").AbsoluteUri, "experts-exchange.jpg");
			if (site.IsOk)
			{
				site.Generate();
				pictureBox1.Image = site.Bitmap;
			}
		}
	}

	[ComVisible(true), ComImport()]
	[GuidAttribute("0000010d-0000-0000-C000-000000000046")]
	[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
	public interface IViewObject
	{
		[return: MarshalAs(UnmanagedType.I4)]
		[PreserveSig]
		int Draw(
			[MarshalAs(UnmanagedType.U4)] UInt32 dwDrawAspect, 
			int lindex, IntPtr pvAspect, [In] IntPtr ptd, 
			IntPtr hdcTargetDev, IntPtr hdcDraw, 
			[MarshalAs(UnmanagedType.Struct)] ref Rectangle lprcBounds, 
			[MarshalAs(UnmanagedType.Struct)] ref Rectangle lprcWBounds, 
			IntPtr pfnContinue, 
			[MarshalAs(UnmanagedType.U4)] UInt32 dwContinue
			);

		[PreserveSig]
		int GetColorSet([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [In] IntPtr ptd, IntPtr hicTargetDev, [Out] IntPtr ppColorSet);

		[PreserveSig]
		int Freeze([In, MarshalAs(UnmanagedType.U4)] int dwDrawAspect, int lindex, IntPtr pvAspect, [Out] IntPtr pdwFreeze);

		[PreserveSig]
		int Unfreeze([In, MarshalAs(UnmanagedType.U4)] int dwFreeze);

		void SetAdvise([In, MarshalAs(UnmanagedType.U4)] int aspects, [In, MarshalAs(UnmanagedType.U4)] int advf, [In, MarshalAs(UnmanagedType.Interface)] IAdviseSink pAdvSink);

		void GetAdvise(
			[In, Out, MarshalAs(UnmanagedType.LPArray)] int[] paspects, 
			[In, Out, MarshalAs(UnmanagedType.LPArray)] int[] advf, 
			[In, Out, MarshalAs(UnmanagedType.LPArray)] IAdviseSink[] pAdvSink
			);
	}

	class WebSiteToImage
	{
		WebBrowser browser;
		bool fIsGenerated = false;
		bool fIsGenerating = false;
		ManualResetEvent generated = new ManualResetEvent(true);
		public string Url { get; private set; }
		public string FileName { get; private set; }
		public int Width { get; private set; }
		public int Height { get; private set; }
		public Bitmap Bitmap { get; private set; }
		public string ErrorMessage { get; private set; }
		public bool IsOk { get; private set; }

		public WebSiteToImage(string url, string fileName, int width = -1, int height = -1)
		{
			Url = url;
			FileName = fileName;
			Width = width;
			Height = height;

			try
			{
				HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
				request.AllowAutoRedirect = true;
				request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 1.1.4322)";
				request.Referer = "http://www.google.com/";
				request.ContentType = "text/html";
				request.Accept = "*/*";
				request.KeepAlive = false;

				using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
				{
					string x = response.StatusDescription;
				}
			}
			catch (Exception ex)
			{
				ErrorMessage = ex.Message;
				IsOk = false;
				return;
			}
			IsOk = true;
		}

		public void Generate()
		{
			if (!fIsGenerating)
			{
				fIsGenerating = true;
				if (!fIsGenerated)
				{
					Thread t = new Thread(_Generate);
					t.SetApartmentState(ApartmentState.STA);
					t.Start();
					t.Join();
					generated.WaitOne();
				}
				fIsGenerating = false;
			}
		}

		private void _Generate()
		{
			if (!fIsGenerated)
			{
				try
				{
					HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
					request.AllowAutoRedirect = true;
					request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; .NET CLR 3.5.21022; .NET CLR 1.0.3705; .NET CLR 1.1.4322)";
					request.Referer = "http://www.google.com";
					request.ContentType = "text/html";
					request.AllowWriteStreamBuffering = true;
					request.AutomaticDecompression = DecompressionMethods.GZip;
					request.Method = "GET";
					request.Proxy = null;
					request.ReadWriteTimeout = 20;

					HttpStatusCode status;
					using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
						status = response.StatusCode;

					if (status == HttpStatusCode.OK || status == HttpStatusCode.Moved)
					{
						browser = new WebBrowser();
						browser.DocumentCompleted += OnDocumentCompleted;
						browser.Size = new Size(Width, Height);
						browser.ScrollBarsEnabled = false;
						browser.ScriptErrorsSuppressed = true;
						browser.Navigate(Url);
						while (browser.ReadyState != WebBrowserReadyState.Complete)
							Application.DoEvents();

						generated.Set();
						if (Width == -1 || Height == -1)
						{
							Width = browser.Document.Body.ScrollRectangle.Width;
							Height = browser.Document.Body.ScrollRectangle.Height;
							browser.ClientSize = new Size(Width, Height);
						}
					}
					Bitmap = GetBitmap();
					fIsGenerated = true;
				}
				catch (Exception ex)
				{
					ErrorMessage = ex.Message;
					fIsGenerated = false;
				}
			}
		}

		private void OnDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
		{
			if (sender is WebBrowser)
				((WebBrowser)sender).Document.Window.Error += SuppressScriptErrorsHandler;
		}

		private void SuppressScriptErrorsHandler(object sender, HtmlElementErrorEventArgs e)
		{
			e.Handled = true;
		}

		private Bitmap GetBitmap(int width = -1, int height = -1)
		{
			Bitmap result = default(Bitmap);
			IViewObject ivo = browser.Document.DomDocument as IViewObject;
			Rectangle rect = new Rectangle(0, 0, Width, Height);
			Bitmap bitmap = new Bitmap(rect.Width, rect.Height);

			using (Graphics g = Graphics.FromImage(bitmap))
			{
				IntPtr ghdc = g.GetHdc();
				ivo.Draw(1, -1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ghdc, ref rect, ref rect, IntPtr.Zero, 0);
				g.ReleaseHdc(ghdc);
				g.Dispose();

				if ((height == -1 || width == -1) || (height == Height && width == Width))
					result = bitmap;
				else
				{
					Bitmap thumbnail = new Bitmap(width, height);
					using (Graphics gfx = Graphics.FromImage(thumbnail))
					{
						// high quality image sizing
						gfx.SmoothingMode = SmoothingMode.HighQuality;
						gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
						gfx.DrawImage(bitmap, new Rectangle(0, 0, width, height), rect, GraphicsUnit.Pixel);
					}
					bitmap.Dispose();
					result = thumbnail;
				}
			}

			if (FileName.Length > 0)
				result.SaveJPG100(FileName);
			return result;
		}
	}

	static class Extensions
	{
		private readonly static ImageCodecInfo[] fEncoders = ImageCodecInfo.GetImageEncoders();

		private static ImageCodecInfo GetEncoder(ImageFormat format)
		{
			return (from codec in fEncoders where codec.FormatID.Equals(format.Guid) select codec).FirstOrDefault();
		}

		public static void SaveJPG100(this Bitmap bmp, string filename)
		{
			var encoderParameters = new EncoderParameters(1);
			encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
			bmp.Save(filename, GetEncoder(ImageFormat.Jpeg), encoderParameters);
		}
	}
}

Open in new window

-saige-
1

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
infotechelgAuthor Commented:
Seriously, no apologies. You're taking time out of your day to help me, and I really appreciate it.

Anywho, I implemented the updated code, and am getting an error in line 98 of your code above (83 in the attached image). It's almost like it's not finding the URL, but the URL is active and it exists. Any ideas?

GetResponse() Error.
0
it_saigeDeveloperCommented:
I've been working out of a winforms project.  Let me whip up a quick local web project.  Just checking but did you change the request.Referer from google.com?

-saige-
0
infotechelgAuthor Commented:
I did not. However, I think I may know why this is happening. Let me do a test and I'll get back to you.
0
infotechelgAuthor Commented:
Saige, so the error was happening because of custom code from the front-end that had to be modified to adjust for the new code you created. Once I fixed that, it worked locally.

Now for the real test: publish live and see if it fixes the issue.

I'll let you know the results!
0
infotechelgAuthor Commented:
YOU ARE THE BEST!!!! It totally worked. Thank you SO MUCH. You have no idea how much of a help you have been, and how much time you saved me.

Thanks again!!
0
it_saigeDeveloperCommented:
Not a problem at all.  Glad you got it sorted.

-saige-
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.