.NET中操做IPicture、IPictureDisp的小隨筆

【題外話】redis

最近在作一個調用某實驗儀器的程序,這個儀器提供了Windows上COM的接口。調用儀器的時候須要傳輸圖片,提供的接口裏使用了IPicture這個接口,因爲之前沒接觸過,因此查找了一些資料,整理了一下與.NET中System.Drawing.Image的互轉的方式。ui

 

【文章索引】spa

  1. IPicture和IPictureDisp是什麼
  2. 使用AxHost實現與System.Drawing.Image的互轉
  3. 使用VB6 compatibility library實現互轉
  4. Alpha通道的問題

 

【1、IPicture和IPictureDisp是什麼】.net

根據MSDN上對IPicture和IPictureDisp的說明來看,IPicture與IPictureDisp提供了與語言無關的接口,這個接口用來提供對位圖(Bitmap)、圖標(Icon)、圖元文件(Metafile)的抽象,其中後者還實現了IDispatch接口以實現COM的自動化接口。總之,若是經過COM接口傳輸圖像的話,可能會接觸到這兩個接口。code

 

【2、使用AxHost實現與System.Drawing.Image的互轉】orm

.NET在System.Windows.Forms下提供了一個叫AxHost的類來實現與ActiveX控件進行訪問,不過這裏用到的只是在AxHost裏的protected的靜態方法而已。因爲是protected的方法,因此沒有辦法直接調用,好在AxHost不是密封的類,因此咱們還能夠經過集成AxHost來實現調用,例如如下的代碼:blog

 1 using System.Drawing;
 2 using System.Windows.Forms;
 3 
 4 public sealed class IPictureConverter : AxHost
 5 {
 6     private IPictureConverter() : base("") { }
 7 
 8     #region IPictureDisp
 9     public static stdole.IPictureDisp ImageToIPictureDisp(Image image)
10     {
11         return (stdole.IPictureDisp)GetIPictureDispFromPicture(image);
12     }
13 
14     public static Image IPictureDispToImage(stdole.IPictureDisp pictureDisp)
15     {
16         return GetPictureFromIPictureDisp(pictureDisp);
17     }
18     #endregion
19 
20     #region IPicture
21     public static stdole.IPicture ImageToIPicture(Image image)
22     {
23         return (stdole.IPicture)GetIPictureFromPicture(image);
24     }
25 
26     public static Image IPictureToImage(stdole.IPicture picture)
27     {
28         return GetPictureFromIPicture(picture);
29     }
30     #endregion
31 }

 

【3、使用VB6 compatibility library實現互轉】索引

除了AxHost,其實微軟也提供了另一個庫提供託管的Image與IPicture等互轉,那就是Microsoft.VisualBasic.Compatibility.dll,其中有一個叫Support的類提供了不少向後兼容的方法。對於IPicture或IPictureDisp的轉換,咱們能夠寫以下代碼:接口

 1 using System.Drawing;
 2 using Microsoft.VisualBasic.Compatibility.VB6;
 3 
 4 public static class IPictureConverter
 5 {
 6     #region IPictureDisp
 7     public static stdole.IPictureDisp ImageToIPictureDisp(Image image)
 8     {
 9         return (stdole.IPictureDisp)Support.ImageToIPictureDisp(image);
10     }
11 
12     public static Image IPictureDispToImage(stdole.IPictureDisp pictureDisp)
13     {
14         return Support.IPictureDispToImage(pictureDisp);
15     }
16     #endregion
17 
18     #region IPicture
19     public static stdole.IPicture ImageToIPicture(Image image)
20     {
21         return (stdole.IPicture)Support.ImageToIPicture(image);
22     }
23 
24     public static Image IPictureToImage(stdole.IPicture picture)
25     {
26         return Support.IPictureToImage(picture);
27     }
28     #endregion
29 }

仔細看其實與上一段代碼很是相似,本着好奇的態度,咱們Relector一下這些方法實現的代碼。圖片

看起來二者幾乎是同樣的,不過有意思的是,雖然二者的不少方法如GetPICTDESCFromPicture等都不是同一個方法,甚至IPicture等接口都不是在一個庫裏定義的(AxHost是在System.Windows.Forms.UnsafeNativeMethods中定義的,而VB6 compatibility library則是在單獨的一個stdole.dll中定義的),可是其調用的方法裏執行的內容基本都相同,IPicture等接口也都是ComImport的同一個Guid,而兩個方法實現的源頭,更都是DllImport的oleaut32.dll,調用其中的「OleCreatePictureIndirect」方法,因此上述兩種方法是徹底同樣的。

不過在4.0的CLR下,提供的Microsoft.VisualBasic.Compatibility.dll的版本爲10.0.0.0,Support類以及相應的方法都被標記爲過期的(Obsolete),因此編譯的時候提示的警告也蠻讓人噁心的(2.0的CLR下提供的8.0.0.0的dll沒有這個問題),因此倒不妨採用第一種方法。

 

【4、Alpha通道的問題】

若是你的圖片包含Alpha通道的話,上述轉換可能會致使顏色有些問題,因爲IPicture沒有辦法支持Alpha通道,因此妥協的辦法只能是要麼不用Alpha通道,要麼在轉換爲IPicture前在圖片底下墊上一個純色的背景(好比對方程序中要顯示圖片的位置的背景),好比How to Convert a System.Drawing.Image to an IPictureDisp with Alpha Transparency這篇文章就是這麼作的。

 

【相關連接】

  1. IPicture interface:http://msdn.microsoft.com/en-us/library/ms680761.aspx
  2. IPictureDisp interface:http://msdn.microsoft.com/en-us/library/ms680762.aspx
  3. Converting between IPictureDisp and System.Drawing.Image:http://blogs.msdn.com/b/andreww/archive/2007/07/30/converting-between-ipicturedisp-and-system-drawing-image.aspx
相關文章
相關標籤/搜索