2014-02-28 66 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參數。