Image.Save()在从Stream(Image.FromStream())加载的Image上抛出ExternalException

时间:2010-10-17 22:25:05

标签: c# gdi+

我正在追踪一个讨厌的问题,我已经缩小了问题并且意识到它只发生在我处理Image.FromStream()返回的Image实例时。我有一个实用程序方法,使用Stream从文件返回一个Image实例,所以我没有打开文件句柄。这是实用方法(没什么特别的):

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

当我尝试保存从上面的方法加载的Image时,我得到一个InteropServices.ExternalException“GDI +中发生了一般错误。”。以下代码示例将演示此:

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());
}

如果我使用Image.FromFile()加载图像,我可以保存没问题:

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 = Image.FromFile(filename);

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

我想不出任何有用的补充信息。希望我的代码示例足够简单,您可以清楚地看到问题。

谢谢, 史蒂夫

4 个答案:

答案 0 :(得分:3)

根据documentation

  

您必须在图像的生命周期内保持流打开。

尝试在using块内调用Save,以验证如果流仍处于打开状态,则不会抛出任何异常。

答案 1 :(得分:1)

试试这个

//  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());
    }

我认为使用块会给你带来问题

答案 2 :(得分:0)

根据目前的建议和评论以及我自己的额外阅读,我认为我有一个有效的解决方案。基本上问题是我无法关闭Stream。很好,但我也不能保持FileStream打开,但不保证它会被正确关闭。

相反,我正在将文件读入缓冲区,然后创建一个MemoryStream并将其传递给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());

感谢大家的建议和问题。

答案 3 :(得分:0)

我遇到了同样的问题,但我没有使用FileStream,而只使用MemoryStream,因为我正在从数据库下载图像。当我第一次在数据库中保存图像时,一切都很好但是当我在数据库中执行图像更新时会抛出ExternalException。如果你想分析,这是我的代码。

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;
        }
    }

}