Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image.Save(..) throws a GDI+ exception because the memory stream is closed

As it's a MemoryStream, you really don't need to close the stream - nothing bad will happen if you don't, although obviously it's good practice to dispose anything that's disposable anyway. (See this question for more on this.)

However, you should be disposing the Bitmap - and that will close the stream for you. Basically once you give the Bitmap constructor a stream, it "owns" the stream and you shouldn't close it. As the docs for that constructor say:

You must keep the stream open for the lifetime of the Bitmap.

I can't find any docs promising to close the stream when you dispose the bitmap, but you should be able to verify that fairly easily.


A generic error occurred in GDI+. May also result from incorrect save path! Took me half a day to notice that. So make sure that you have double checked the path to save the image as well.


Perhaps it is worth mentioning that if the C:\Temp directory does not exist, it will also throw this exception even if your stream is still existent.


Copy the Bitmap. You have to keep the stream open for the lifetime of the bitmap.

When drawing an image: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI

    public static Image ToImage(this byte[] bytes)
    {
        using (var stream = new MemoryStream(bytes))
        using (var image = Image.FromStream(stream, false, true))
        {
            return new Bitmap(image);
        }
    }

    [Test]
    public void ShouldCreateImageThatCanBeSavedWithoutOpenStream()
    {
        var imageBytes = File.ReadAllBytes("bitmap.bmp");

        var image = imageBytes.ToImage();

        image.Save("output.bmp");
    }

I had the same problem but actually the cause was that the application didn't have permission to save files on C. When I changed to "D:\.." the picture has been saved.


You can try to create another copy of bitmap:

using (var memoryStream = new MemoryStream())
{
    // write to memory stream here

    memoryStream.Position = 0;
    using (var bitmap = new Bitmap(memoryStream))
    {
        var bitmap2 = new Bitmap(bitmap);
        return bitmap2;
    }
}