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:
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.
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.
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:
Ensure path is correct (duh)
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.)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
How to Force Bundlecollection to Flush Cached Script Bundles in MVC4
Unique Ways to Use the Null Coalescing Operator
How to Deploy a .Net Application That Uses Odac Without Installing the Whole Component to the User
Database.Begintransaction VS Transactions.Transactionscope
How to Get the Position of Textbox That Has Been Pressed
Total Number of Items Defined in an Enum
How to Open a Web Page from My Application
Factory Pattern in C#: How to Ensure an Object Instance Can Only Be Created by a Factory Class
Find Image Format Using Bitmap Object in C#
Creating Threads - Task.Factory.Startnew VS New Thread()
Why Is There a Difference in Checking Null Against a Value in Vb.Net and C#
Difference Between Destructor, Dispose and Finalize Method
Why Would One Ever Use the "In" Parameter Modifier in C#
Can Unity Be Made to Not Throw Synchronizationlockexception All the Time
Rotate a Graphics Bitmap at Its Center
How to Install a C# Compiler Without Visual Studio