2013-03-22 50 views
14

有了這樣的加載和存儲圖像時的年齡工作的代碼,我發現我有一個打破這個代碼的單個圖像如何在保存圖像時找到Generic GDI +錯誤的原因?

const string i1Path = @"c:\my\i1.jpg"; 
const string i2Path = @"c:\my\i2.jpg"; 

var i = Image.FromFile(i1Path); 
i.Save(i2Path, ImageFormat.Jpeg); 

唯一的例外是:

System.Runtime .InteropServices.External發生的異常

GDI +中發生了一般性錯誤。

在System.Drawing.Image.Save(字符串文件名,ImageCodecInfo編碼器,EncoderParameters encoderParams)
在System.Drawing.Image.Save(字符串文件名,格式的imageformat)
在...

就我所見,圖像沒有特別之處。它大小約爲250像素,可以在例如Windows圖像查看器或Paint.NET:

enter image description here

(由於上面的圖片,上傳到堆棧溢出不會產生錯誤了之後,我已經把the original image here

我發現是在調用Save method時,目標圖像文件正在創建零字節。

我對導致錯誤的原因確實無能爲力。

我的問題:

  • 你能想到的會從保存圖像阻礙.NET任何特別的東西?
  • 有沒有什麼辦法(除了恐慌)來縮小這類錯誤?
+1

MSDN說從流加載的位圖需要流保持存在,只要位圖存在。 – 2015-11-11 00:14:00

+1

未解決您的問題:但是,如果路徑不存在,則會發生同樣的異常(我花了一段時間才弄清楚我有一個錯字)。可能幫助別人。 – 2017-05-18 08:27:25

回答

27

雖然我還是沒弄明白保存圖像時,究竟是什麼導致錯誤的原因,我發現了一個變通方法適用於:

const string i1Path = @"c:\my\i1.jpg"; 
const string i2Path = @"c:\my\i2.jpg"; 

var i = Image.FromFile(i1Path); 

var i2 = new Bitmap(i); 
i2.Save(i2Path, ImageFormat.Jpeg); 

即通過將圖像內部複製到Bitmap實例並保存該圖像而不是原始圖像,該錯誤消失。

我假設通過複製它,導致原來的Save調用失敗的錯誤部分被移除和/或規範化,從而使保存操作成功。

saved image i2.jpg

有趣的是,如此存儲的圖像具有在磁盤(16 KB)比其原始的源(26 KB)更小的文件。

+4

構建一個新的位圖(oldImage)也解決了我的問題... – esbenr 2013-12-20 08:51:57

+1

這也適用於我。之後,我不得不強制垃圾收集,原因是「內存異常」。 – user426364 2014-06-09 13:04:26

+1

爲我工作 - 不知道爲什麼。只有與JPG圖像(PNG等問題)的問題 – Darren 2015-04-09 19:56:13

3

原因可能是圖像被加載懶惰,並且加載過程在您嘗試保存時尚未完成。

以下說的this blog post(假設你是德國人,你在圖片中鏈接了你的問題)提供了一個可能的解決方案。另外this SO question's接受的答案表明這是由於您試圖保存的圖像文件被鎖定。

編輯
尤里西斯阿爾維斯,從鏈接的博客條目:如果您加載使用Image.FromFile(),直到它被置於它保持鎖定的圖像。這可以防止致電Save()

pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg"); 
pictureBox1.Image.Save("C:\\test\\test2.jpg"); 

上述代碼會引發錯誤。

要使其工作,您需要複製圖像。下面的代碼工作:

pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg"); 
Image copy = pictureBox1.Image; 
copy.Save("C:\\test\\test2.jpg") 
+1

我真的不明白爲什麼這個答案是downvoted ...也許有人可以解釋? – 2013-03-22 13:41:01

+1

由於下來的選民沒有留下評論,我們可能永遠不會知道。 :) – 2015-11-11 00:10:47

+0

我找不到任何與此主題相關的鏈接帖子。您能否在您的答案中提供一個代碼示例? – 2017-10-23 16:47:11

8

首先確保所需的文件夾具有讀/寫權限。更改權限爲我解決了這個問題。

+1

謝謝。這個對我有用。 – 2014-05-29 00:15:44

+0

這就像90%的情況:-) – 2017-02-23 16:18:36

5

解決方案就在這裏,您必須處理映像對象以釋放服務器上的內存。 嘗試使用using聲明。確保服務器上的目標目錄也存在。

+1

這聽起來像是一個糟糕的答案。 – 2014-04-28 13:35:21

+2

「確保服務器上的目標目錄存在」是我的問題 – 2015-09-18 15:23:50

+2

@UweKeim - 在臨時IDisposable對象上使用''只是確保在安全的情況下儘快調用GC。 – 2015-11-11 00:03:43

3

我的解決方案只是將文件保存

這裏之前做,寫臨時含量(File.WriteAllText)是代碼:

var i = Image.FromFile(i1Path); 
File.WriteAllText(i2Path, "empty"); // <---- magic goes here 
i.Save(i2Path, ImageFormat.Jpeg); 

請嘗試,讓我知道

+1

如果您沒有創建該文件的權限,我可以看到在哪裏/哪裏出現異常,哪裏會發生變化。 :) :)但它會很奇怪,如果這解決了OP中的其他問題。 'bitmap.Freeze(); bitmap.Save(...);'或'var other = new Bitmap(bitmap); other.Save(...);'這兩個函數確保在調用Save之前,保存的位圖不會綁定到流。 – 2015-11-11 00:08:40

-1

在程序中打開

const string i1Path = @"c:\my\i1.jpg"; 

const string i2Path = @"c:\my\i2.jpg"; 

var i = Image.FromFile(i1Path); 

i.Save(i2Path, ImageFormat.Jpeg); 

i.Dispose(); 
-3

問題是,您無法保存在C:驅動器的根分區上。保存在其他地方,你不會有問題。

+0

在我看來,這是一個非常糟糕的答案。您是否閱讀了我的整個問題? – 2017-10-07 12:26:40

相關問題