开发者

Image.Save() throws ExternalException on Image loaded from Stream (Image.FromStream())

I'm tracking down a pesky problem and I've narrowed down the problem down and realized it only happens when I'm dealing with an Image instance returned by Image.FromStream(). I have a utility method that returns an Image instance from a file using a Stream so I don't have the file handle left open. Here is that utility method (nothing special):

public static Image ImageFromFileReleaseHandle(string filename)
{
    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        return Image.FromStream(fs);
    }
}

When I try to save an Image loaded from the above method I'm getting an InteropServices.ExternalException "A generic error occurred in GDI+.". The following code example will demonstrate this:

private void button6_Click(object sender, EventArgs e)
{
    var filename = @"D:\My Documents\My Pictures\2010-03-27 hangover hike.jpg";

    //  Get an Image instance
    Image image;
    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        image = Image.FromStream(fs);
    }

    //  Save to a temp file - this is the code that throws the exception
    image.Save(Path.GetTempFileName());
}

If I load the image using Image.FromFile() I can save no problem:

private void button6_Click(object sender, EventArgs e)
{
    var filename = @"D:\My D开发者_运维百科ocuments\My Pictures\2010-03-27 hangover hike.jpg";

    //  Get an Image instance
    Image image = Image.FromFile(filename);

    //  Save to a temp file - this is the code that throws the exception
    image.Save(Path.GetTempFileName());
}

I can't think of any additional information that would be helpful. Hopefully my code examples are simple enough that you can clearly see the problem.

Thanks, Steve


According to the documentation:

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

Try calling Save inside the using block to verify that no exception is thrown if the stream is still open.


try this instead

//  Get an Image instance
    Image image;
    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
    {
        image = Image.FromStream(fs);
        //  Save to a temp file - this is the code that throws the exception
        image.Save(Path.GetTempFileName());
    }

I think the using block is giving you issues


Based on suggestions and comments so far and my own additional reading I think I have a working solution. Basically the problem is that I can't close the Stream. Fine, but I also can't leave a FileStream open with no guarantee it will be closed properly.

Instead I'm reading the file into a buffer then creating a MemoryStream and passing that to Image.FromStream().

var filename = @"D:\My Documents\My Pictures\2010-03-27 hangover hike.jpg";

byte[] imageData = FileUtils.ReadWholeFileBytes(filename);
Image image = Image.FromStream(new MemoryStream(imageData));

//  dump the buffer to test if this upsets the Memory Stream.  I need to read more
//  about MemoryStream and how it may keep the GC from cleaning up it's underlying data
imageData = null;        

//  Save to a temp file
image.Save(Path.GetTempFileName());

Thanks all for your suggestions and questions.


I got the same problem but instead of using a FileStream, I only have a MemoryStream, because I'm downloading the image from a database. When I save the image for the first time in the database everything is fine but when I execute an update of the image in the database throws an ExternalException. Here's my code if you want to analyze.

public class ImageConverter
{
    public static byte[] imageToByteArray(Image imageIn)
    {
        if (imageIn == null)
            return new byte[] { 45 };

        using (MemoryStream ms = new MemoryStream())
        {
            imageIn.Save(ms, imageIn.RawFormat);
            return ms.ToArray();
        }
    }

    public static Image byteArrayToImage(byte[] byteArrayIn)
    {
        if (byteArrayIn == null)
            return null;

        using (MemoryStream ms = new MemoryStream(byteArrayIn))
        {
            Image returnImage = Image.FromStream(ms);
            return returnImage;
        }
    }

} 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜