Contact   •   Products   •   Search

Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs

Common Problems with rendering Bitmaps into ASP.NET OutputStream


Raise your hand if you’ve loaded an image from a Resource (or a BLOB database field):

 

Bitmap bm2 = this.GetGlobalResourceObject("Resources", "_BitMap") as Bitmap;

Response.ContentType = "image/jpeg";

bm2.Save(Response.OutputStream, ImageFormat.Jpeg);

Response.End();

 

and finding out that you can’t save the image! You get a not so happy error:

A generic error occurred in GDI+.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+.

Source Error:

Line 41: 
Line 42:         Response.ContentType = "image/jpeg";
Line 43:         bm2.Save(Response.OutputStream, ImageFormat.Jpeg);
Line 44:         Response.End();
Line 45:


Source File: c:\projects2005\Articles\Internationalization\Test.aspx.cs    Line: 43

 

I know this isn’t the first time I’ve done this and scratched my head and go WTF. The bitmap’s there but it won’t save, not to the output stream or to disk (even with permissions for it).

 

So what gives? The documentation is not real clear on this, although MSDN has a little blurp on not saving to the same stream:

 

Remarks

You should avoid saving an image to the same stream that was used to construct it. Doing so might damage the stream.

I don’t think this applies here – the Bitmap resource comes from a database field’s raw byte stream into a memory stream from which the image is loaded in my custom Resource Provider out of a database. The original stream is long gone, but maybe that’s just the problem…

 

Whatever the problem is, the code above doesn’t work.

 

The solution is to create a second bitmap and basically copy the image into a new Bitmap object and then save  to the outputstream:

 

Bitmap bm2 = this.GetGlobalResourceObject("Resources", "_BitMap") as Bitmap;

Bitmap bm3 = new Bitmap(bm2);

 

Response.ContentType = "image/jpeg";

bm3.Save(Response.OutputStream, ImageFormat.Jpeg);

 

bm2.Dispose();

bm3.Dispose();

 

Response.End();

 

Works but it really bites that this unobvious piece of code should be necessary especially since Bitmap objects are not exactly lightweight objects to load and keep around even for a short period of time.

 

Remember PNG Images are ‘special’

In addition to the above issue remember that you can’t save PNG images directly into the output stream because of some issues with that particular format. Instead you need to write the image first into a memory stream:

 

Bitmap bm2 = this.GetGlobalResourceObject("Resources", "_BitMap") as Bitmap;

Bitmap bm3 = new Bitmap(bm2);

 

MemoryStream ms = new MemoryStream();

      

Response.ContentType = "image/png";

bm3.Save(MemStream, System.Drawing.Imaging.ImageFormat.Png);

MemStream.WriteTo(Response.OutputStream);

 

bm2.Dispose();

bm3.Dispose();

Response.End();

 

Note that you still need to do the Bitmap swapping if the image is loaded a certain way (like from the ResourceProvider) as you can’t save to a memory stream without it either.

 

Make Donation
Posted in ASP.NET  Graphics  


Feedback for this Post

 
# DotNetSlackers: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by DotNetSlackers Latest ASP.NET News October 19, 2006 @ 9:37pm
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Steve from Pleasant Hill October 20, 2006 @ 11:25am
Rick, didn't try the example on the bottom of this page, but it seems they are doing something (vaguely) similar. The example has a Response.Clear and .BufferOutput = True however...

http://msdn2.microsoft.com/en-us/library/system.web.httpresponse.outputstream.aspx
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by David Douglass October 23, 2006 @ 5:34pm
I don't know if this is related to the difficulties you're having, but use of GDI+ (and thus the System.drawing namespace) isn't supported in ASP.NET. The MSDN page for the System.Drawing namespace states:

"Classes within the System.Drawing namespace are not supported for use within a Windows or ASP.NET service. Attempting to use these classes from within one of these application types may produce unexpected problems, such as diminished service performance and run-time exceptions."
# Streaming a PNG file into Response.OutputStream? - Rick Strahl's Web Log
by Rick Strahl's Web Log October 28, 2006 @ 3:12am
Here's an odd one. I'm trying to write out a PNG bitmap into the REsponse.OutputStream but the operation fails, while writing a JPG bitmap works just fine.
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Peter Lapic November 20, 2006 @ 9:52pm
I have a similar problem. I have an ASP page which renders the PNG image from a webservice. The generic error occurs on .Save method. Any ideas?

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
Dim iImageID As Integer = Request.QueryString("id")
Dim oService As New ImageService.ImageService
Dim iResolution As Short = Request.QueryString("res")
Dim sSize As Single = Request.QueryString("size")
Dim oImageData As [Byte]() = oService.GetImage(iImageID, iResolution, sSize, True)
Dim oStream As New System.IO.MemoryStream(oImageData)
Dim obmpImage As New Bitmap(oStream)

Response.ContentType = "image/png"
obmpImage.Save(oStream, Imaging.ImageFormat.Png)
oStream.WriteTo(Response.OutputStream)
oStream.Close()

Catch ex As Exception
Throw ex
End Try
End Sub
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Rick Strahl November 21, 2006 @ 2:38am
Peter you can't save PNG objects into the output stream. You have to manually stream them.

http://www.west-wind.com/WebLog/posts/6008.aspx

Look in the comments.
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Peter Lapic November 21, 2006 @ 3:17pm
Rick the link you directed me has the following code (translated VB.Net)
Dim MemStream As New MemoryStream()
Dim bitmap As New Bitmap(image)
' set the content type
Response.ContentType = "image/png"
'send the image to the memory stream then output
bitmap.Save(MemStream, System.Drawing.Imaging.ImageFormat.Png)
MemStream.WriteTo(Response.OutputStream)

This is the same method that I am using. The only difference is that I include a buffer object, which contains the image from the web service, in the memory stream. Then the bitmap object is created based on this memory stream.

The code I have works 99% of the time. We stream images in 2 colour (Magenta/Black) that works perfectly. Occassionally when the images are in 4 colour (CMYK) that's when the error can occur and that is what I am trying to resolve.

Any ideas?
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by ar December 04, 2006 @ 10:02am
hi
i use this way, and until now i face no problem:


 Response.ContentType = "image/Png";
         Response.Buffer = false;
         Response.Clear();

        MemoryStream stream1 = new MemoryStream();
//DrawPie method return an Image
                this.DrawPie(table1).Save(stream1, ImageFormat.Png);

             Response.BinaryWrite(stream1.ToArray());
        
         base.OnPreInit(e);
.
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Nostra April 17, 2007 @ 12:19am
Hello.

Thaks for the solution, I had problems with loading Png pictures in an ASP.Net website and a Winform app : there was always like a shadow on the picture.

I googled a lot of time and tryed a lot of tricks but nothing worked... Except the second solution, with the Bitmap copy.

I'm happy, it works! xD
But I'd like to understand why... Any idea?
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by kalyan November 06, 2007 @ 3:16am

Hello,

I want to save that optputstream image to a file. Please can anyone suggest me...

Thanks in Advance....
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by caloggins May 31, 2008 @ 3:06pm
Thank you! I've been beating my head against this problem for two days.
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Alasdair CS June 25, 2008 @ 6:51am
Congratulations once again, Sir! This irritated me (and still does), but at least it works now.

Thank you.

Alasdair CS
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Marco Kummer June 27, 2008 @ 6:32am
Thank you so much for this helpful hint! I kept getting this strange exception when trying to save a bitmap to a MemoryStream. In my opinion this is definitely a bug in the framework.
# Common Problems with rendering Bitmaps into ASP.NET OutputStream
by DotNetKicks.com October 30, 2008 @ 7:09pm
You've been kicked (a good thing) - Trackback from DotNetKicks.com
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Jed Silvestre March 14, 2009 @ 8:15pm
Rick, google's been my common reference regarding my coding, and most of the time, i stumble on your blogs, it always hits my problem head-on and solves it!
keep it up, you help a lot of programmers!
Thank you, sir!
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by TheYetiMan April 27, 2009 @ 6:40am
Oh man.. you're totally my hero - I've been racking my brain all day about writing a PNG directly to response.outputstream and this is the only place on the Interwebs that actually mentions how to get around it - MARVELLOUS!

Thanks again!
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Daniel July 16, 2009 @ 11:39pm
Rick, when i click a button and download a file from server, then the browser popups a 'Open/sava/cancel' message box waiting users to choose, when i clicked 'save' then 'Save as' message box popup let me choose saving path and rename the file . How can i do on server side code to skip the first message box, directly popup the "Save as" message box?
Please give me some help!
Thanks in advance.
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Rick Strahl July 17, 2009 @ 10:55am
@Daniel - you can't control this behavior is controlled by the browser and I believe what you're seeing will behave differently on different browsers.
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Daniel July 20, 2009 @ 5:53pm
Rick, Thanks for your timely reply. It's true that it will behave differently on different browsers, luckly my

client just requests that it is normal on IE6 or IE7. One of their engineers shared me some C# code and told me that

it can resolve my problem, but i don't use C# in my project, so i want to know whether the code works normally on

IIS, if it works, I think there will be a way to resolve my problem by other program languages.

The code(two methods):

Directly export to excel when there is a result set

      Event driven, such as click a button
//********Direct Method*********//

   string attachment = "attachment; filename=OverheadReport.xls";
            Response.ClearContent();
            Response.AddHeader("content-disposition", attachment);
            Response.ContentType = "application/vnd.ms-excel";
            string tab = "";
            foreach (DataColumn dc in result.Columns)
            {
                Response.Write(tab + dc.ColumnName);
                tab = "\t";
            }
            Response.Write("\n");

            int i;
            foreach (DataRow dr in result.Rows)
            {
                tab = "";
                for (i = 0; i < result.Columns.Count; i++)
                {
                    Response.Write(tab + dr[i].ToString());
                    tab = "\t";
                }
                Response.Write("\n");
            }
            Response.End();


//**********Event driven********//

   protected void ExportToExcelButton_Click(object sender, EventArgs e)

    {
        Response.Clear();
        Response.AddHeader("content-disposition", "attachment;filename=Company50UploadError.xls");
        Response.Charset = "";
        // If you want the option to open the Excel file without saving then

        // comment out the line below
        //Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.ContentType = "application/vnd.xls";
        System.IO.StringWriter stringWrite = new System.IO.StringWriter();
        System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
        ErrorGridView.AllowPaging = false;
        ErrorGridView.DataSource = (Company50Report.ErrorLogDataTable)Session["currentTable"];
        ErrorGridView.DataBind();
        ErrorGridView.RenderControl(htmlWrite);
        Response.Write(stringWrite.ToString());
        Response.End();
    }

    public override void VerifyRenderingInServerForm(Control control)
    {
        /* Confirms that an HtmlForm control is rendered for the specified ASP.NET
           server control at run time. */
    }

    public override bool EnableEventValidation
    {
        get
        {
            return false;
        }
        set
        {
            // DO NOTHING
        }
}
//*******End**********//
     

Looking forward to your reply.

Daniel
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Pkeno January 22, 2010 @ 6:20am
Thank you. This article was very helpful
# GDI Fehler "A generic error occurred in GDI " beim Erzeugen von PNG
by The IT Blog March 23, 2010 @ 2:24am
GDI Fehler "A generic error occurred in GDI " beim Erzeugen von PNG
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Sushil Kumar April 26, 2010 @ 5:09am
Stream _stream = new FileStream(path, System.IO.FileMode.Open);
MemoryStream storeStream = new MemoryStream();
storeStream.SetLength(_stream.Length);
_stream.Read(storeStream.GetBuffer(), 0, (int)_stream.Length);
storeStream.Flush();
_stream.Close();
Response.ContentType = "image/jpeg";
storeStream.WriteTo(Response.OutputStream);
SaveMemoryStream(storeStream, "C:\\text1" + ".jpeg");
storeStream.Close();
Response.End();
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Dave July 09, 2010 @ 10:47am
I'm always happy when your blog pops up when I'm looking into a problem. Thanks for the consistently good solutions.
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Frasse February 02, 2011 @ 5:09am
Great stuff! Tanks alot Rick!
Your solution worked for me. My problem was that the GDI+ error did not happen on my development machine at all, while on the production server it happend every time. I still have two issues: The solution breaks animated gifs, that is they don't display as animated gifs. Secondly, I would really like to know what the actual problem is in the first place. Anyone?
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Hashname March 08, 2011 @ 11:05pm
Unfortunately none of this worked for me.
So I simply choose to write the Byte Stream directly to output(without first converting it to BitMap) using Response.BinaryWrite and voila it worked :)

Thanks anyways Rick
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by madper April 02, 2011 @ 12:33am
Thanks man, this solution was save me from this headache!!
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Doogal April 20, 2011 @ 8:54am
Once again you've saved me, cheers! I wish somebody would sort out GDI+, just saying you can't use it in ASP.NET doesn't really cut it when it seems to be the only option. At the very least they should fix the awful error messages!
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Allie June 21, 2011 @ 5:30am
Tried the suggested solution and it seemed to work but unfortunately when loading a page with many PNG images, an error ocurred saying "out of memory", right on the place where the second Bitmap was created.
I then tried the following and it works :
context.Response.BinaryWrite(System.IO.File.ReadAllBytes(context.Server.MapPath(context.Request.Path)));
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Rick Strahl June 21, 2011 @ 10:01am
@Allie - If you have really large images and you're running in a low memory environment you may have problems with this because the images are loaded into memory. You might try explicitly calling ms.Dispose() to release the MemoryStream as well (should be automatic when it goes out of scope, but might save a few extra cycles of memory usage).
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Coder December 13, 2011 @ 3:35pm
System.Drawing namespace isnt supported in ASP.NET at all:

http://msdn.microsoft.com/en-us/library/system.drawing.aspx
# re: Common Problems with rendering Bitmaps into ASP.NET OutputStream
by Rick Strahl December 13, 2011 @ 7:04pm
@Coder - that's what it says because not all of GDI+ is threadsafe. In reality though if you use image processing in low volume situations (ie. convert an uploaded image or something along those lines) I've never ever run into a problem with this. Not saying it can't happen but think that it's overrated.

WPF actually includes threadsafe drawing classes. Bertrand had a post on comparing drawing modes etc. a while back that might be helpful if you're worried about threadsafe operation:

http://weblogs.asp.net/bleroy/archive/2009/12/10/resizing-images-from-the-server-using-wpf-wic-instead-of-gdi.aspx
 


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2014