2014-02-28 68 views
1

我有2个样本代码,我尝试做同样的事情,将属性项更新回图像并将其保存在不同的文件下。从流打开的图像不同于从文件打开的图像

代码1

 Image image; 
     using (FileStream stream = new FileStream(this.fileName, FileMode.Open)) { 
      image = Image.FromStream(stream); 
      foreach (var property in this.propItems) { 
       image.SetPropertyItem(property); 
      } 
     } 

     image.Save(@"D:\Temp\1.jpg"); 
     image.Dispose(); 

代码2

 using (Image image = new Bitmap(this.fileName)) { 
      foreach (var property in this.propItems) { 
       image.SetPropertyItem(property); 
      } 

      image.Save(@"D:\Temp\1.jpg"); 
     } 

唯一的区别是,我怎么打开的文件。如果我运行的第一块代码我得到异常消息

System.Runtime.InteropServices.ExternalException了未处理
的HResult = -2147467259消息=在GDI +发生一般性错误。
源= System.Drawing中错误码= -2147467259

我的第二张的代码只是运行正常,我可以得到正确的输出。这里有什么不同?

+2

在您已经离开使用范围的第一个示例中,流已关闭。 – jac

回答

2

这是由设计,Image.FromStream()的MSDN文章严厉警告这一点。关闭流后,图像不再可用。试图像你一样保存它很有可能,但不能保证,当它试图从封闭流中检索像素数据时抛出异常。

Image类的一个关键属性是它是lazy,与许多.NET类不同,它不会访问流数据,直到需要时为止。直到像素数据被实际使用,这是不必要的,这发生在你的片段的Save()调用中。 Kaboom当它不能再读取它时。

您可以通过移动储存解决您的第一个片段()的使用声明中称:

using (var stream = new FileStream(this.fileName, FileMode.Open)) 
    using (var image = Image.FromStream(stream) { 
     foreach (var property in this.propItems) { 
      image.SetPropertyItem(property); 
     } 
     image.Save(@"D:\Temp\1.jpg"); 
    } 

没有点在使用一个FileStream了。请注意,您保存图像的文件不能与您从中读取图像的文件相同。有人暗示你试图解决这个问题。使用MemoryStream是避免锁定文件的常用技术。

还请注意代码中的另一个错误,即使用.jpg扩展名保存文件,但它实际上是一个PNG文件。如果您需要JPEG,则不能省略ImageFormat参数。