C# - Outputting Image to Response Output Stream Giving Gdi+ Error

C# - Outputting image to response output stream giving GDI+ error

PNGs (and other formats) need to be saved to a seekable stream. Using an intermediate MemoryStream will do the trick:

using (Bitmap image = new Bitmap(context.Server.MapPath("images/stars_5.png")))
{
using(MemoryStream ms = new MemoryStream())
{
image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
ms.WriteTo(context.Response.OutputStream);
}
}

A generic error occurred in GDI+, JPEG Image to MemoryStream

OK I seem to have found the cause just by sheer luck and its nothing wrong with that particular method, it's further back up the call stack.

Earlier I resize the image and as part of that method I return the resized object as follows. I have inserted two calls to the above method and a direct save to a file.

// At this point the new bitmap has no MimeType
// Need to output to memory stream
using (var m = new MemoryStream())
{
dst.Save(m, format);

var img = Image.FromStream(m);

//TEST
img.Save("C:\\test.jpg");
var bytes = PhotoEditor.ConvertImageToByteArray(img);

return img;
}

It appears that the memory stream that the object was created on has to be open at the time the object is saved. I am not sure why this is. Is anyone able to enlighten me and how I can get around this.

I only return from a stream because after using the resize code similar to this the destination file has an unknown mime type (img.RawFormat.Guid) and Id like the Mime type to be correct on all image objects as it makes it hard write generic handling code otherwise.

EDIT

This didn't come up in my initial search but here's the answer from Jon Skeet

Why does Image.FromFile keep a file handle open sometimes?

I went through the same journey as a few other posters on this thread. Things I noted:

  1. Using Image.FromFile does seem unpredictable on when it releases the file handle. Calling the Image.Dispose() did not release the file handle in all cases.

  2. Using a FileStream and the Image.FromStream method works, and releases the handle on the file if you call Dispose() on the FileStream or wrap the whole thing in a Using {} statement as recommended by Kris. However if you then attempt to save the Image object to a stream, the Image.Save method throws an exception "A generic error occured in GDI+". Presumably something in the Save method wants to know about the originating file.

  3. Steven's approach worked for me. I was able to delete the originating file with the Image object in memory. I was also able to save the Image to both a stream and a file (I needed to do both of these things). I was also able to save to a file with the same name as the originating file, something that is documented as not possible if you use the Image.FromFile method (I find this weird since surely this is the most likely use case, but hey.)

So to summarise, open your Image like this:

Image img = Image.FromStream(new MemoryStream(File.ReadAllBytes(path)));

You are then free to manipulate it (and the originating file) as you see fit.

output image using web api HttpResponseMessage

The the following:

  1. Ensure path is correct (duh)

  2. Ensure your routing is correct. Either your Controller is ImageController or you have defined a custom route to support "GetImage" on some other controller.
    (You should get a 404 response for this.)

  3. Ensure you open the stream:

    var stream = new FileStream(path, FileMode.Open);

I tried something similar and it works for me.

System.Drawing.Image.FromFile does not close the file stream

Do not use this method. Use FromStream instead and do this:

    Using FileStream = New IO.FileStream("D:\Test.jpg", IO.FileMode.Open)
Dim x = System.Drawing.Image.FromStream(FileStream)

'Do your image manipulation...'
End Using

IO.File.Delete("D:\Test.jpg")


Related Topics



Leave a reply



Submit