我之前也曾經在處理圖片相關工作時遇過 "在 GDI+ 中發生泛型錯誤" 的錯誤,最近我們又再次遇到了,雖然這類問題多試幾次就很快能解決,但因為同樣的問題出現好幾次了,卻不太知有哪些出現的時機,因此做了一些研究,以便於下次更快速的判斷解決之道。
我先把中、英文錯誤訊息列出來:
- System.Runtime.InteropServices.ExternalException: 在 GDI+ 中發生泛型錯誤。
- System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI+
GDI 的全名是 Graphics Device Interface 的縮寫,是在 Windows 平台內十分重要的核心元件,負責處理許多跟影像物件有關的工作,包括繪製直線、曲線、字型、材質、處理縮圖、裁切圖片、...等。而 GDI+ 則是以 C++ 語言所開發的 GDI 介面,可直接利用系統硬體(顯示卡)資源對圖片相關操作進行加速處理,詳細的技術細節可參考 Graphics Device Interface - Wikipedia, the free encyclopedia 的說明。
在 .NET Framework BCL 中所有與繪圖有關的類別 (System.Drawing 命名空間) 也都幾乎不是 Managed 組件,幾乎都是透過 Unmanaged GDI+ 元件進行圖形操作,所以只要發生 GDI+ 的錯誤就一定不是 .NET 程式語法的錯誤,而且錯誤訊息是直接從 GDI+ 傳來的,繁體的作業系統就會回應中文訊息、英文的作業系統就會回應英文訊息,透過 Thread.CurrentThread.CurrentCulture 是沒辦法指定錯誤訊息的。
由於「在 GDI+ 中發生泛型錯誤」實在不容易除錯,尤其是 .NET 初學者更難以判斷問題發生的原因,往往是瞎子摸象、到處亂查、到處亂試。
首先,我們已經知道錯誤發生的地方一定不是 .NET 程式語法的問題,所我們就要找出其他可能發生的原因,我整理一些我曾經發生過的問題,以及有可能發生問題的地方供各位參考:
- 與『檔案系統』有關的問題
- 目錄權限不足,無法寫入或無法讀取 ( 包括把檔案寫入 UNC 路徑 )
解決之道: 設定正確可讀取或寫入的權限 - 檔案權限不足,無法寫入或無法讀取 ( 包括把檔案寫入 UNC 路徑 )
解決之道: 設定正確可讀取或寫入的權限 - 目錄不存在,所以根本無法寫入檔案
解決之道: 先建立目錄,然後再進行寫入 ( Image.Save , Bitmap.Save )
- 與『圖檔格式』有關的問題
- 透過 Image.FromStream 載入圖片時,其 Stream 無法使用 Seek 方法
解決之道: 將無法 Seek 的 Stream 先寫入 MemoryStream 再進行載入即可。在 MSDN 上 Image.FromStream 的備註有寫:「在 Image 的存留期內,資料流都必須保持開啟。」 - 遇到了無法轉換的圖檔類型
解決之道: 一般來說,GIF, JPEG, PNG 應該都沒問題,但還是有些圖檔格式無法透過 GDI+ 進行轉換,這時也會發生錯誤。遇到這個問題必須透過 UI 告訴使用者避開一些無法轉換的圖檔類型。我之前會遇到這個問題是因為在測試時亂選圖,剛好選到一張不能轉換成功的圖 ( 註: 該圖檔好像是顏色數非常少的 GIF 檔,年代有點久遠我記不太清楚了 )
我能想到的只有這些,總之跟 .NET 沒關係就是了,如果下次再遇到類似的問題,以上幾種狀況還找不到解法的話,請多多查詢 MSDN 並多看一下「備註」的部分,或參考以下相關連結。
相關連結