2010-10-17 23 views
4

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

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

当我尝试保存从上面的方法,我得到一个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()); 
} 

我想不出任何额外的信息,从而将有帮助。希望我的代码示例很简单,您可以清楚地看到问题。

谢谢你,史蒂夫

回答

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

我认为用块给你发出

+0

感谢您的建议,并且您保持打开的流将允许我保存是正确的。然而这在我的应用程序中不起作用,因为创建Image实例的代码和保存它的代码是无关的。我不想让FileStream保持打开状态,因为不能保证它会被关闭。我需要的是一个纯粹的内存镜像实例,没有依赖关系流或文件。 – 2010-10-17 22:54:03

+0

@ user47:然后将图像从FileStream复制到MemoryStream中。 – 2010-10-17 23:02:20

+0

@Allon:在我离开我的最后一条评论之后,我想到了同样的事情,只做了一个实验,看起来确实有效。我现在需要研究将MemoryStream打开的含义......感谢您的建议 – 2010-10-17 23:05:32

3

按照documentation

你必须保持流打开图像的寿命。

尝试调用保存在使用块内部以验证如果流仍处于打开状态,则不会引发异常。

+0

在流处理之前保存工作。感谢您的建议。 – 2010-10-17 23:07:20

0

基础上提出建议和意见,到目前为止和我自己的补充阅读,我想我有一个可行的解决方案。基本上问题是我无法关闭流。很好,但我也不能保留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()); 

非常感谢您的建议和问题。

+0

更新:我的解决方案只是一个半解决方案。它有导致图像ImageFormat设置为MemoryBmp的不幸后果。这意味着您需要在保存时明确设置ImageFormat,否则将使用PNG编码器保存。 – 2010-10-18 23:46:11

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

} 
相关问题