在前文 SharpDX之Direct2D教程II——加載位圖文件和保存位圖文件 中,發現在VB2010中不能很好的運用SharpDx中的WIC組件進行圖片的編碼工作。可能是我的設置問題,也可能是SharpDx對VB2010支持的不夠好(用C#就沒有問題) ,有網友將代碼貼到VB2012中,也發現可以運行的很好。由於手頭上沒有VS2012,故這個功能的實驗放置一段時間
不過,回過頭想一想。我們需要WIC的圖片編碼功能么?
Direct2D(SharpDx等)的顯示繪制優勢
和GDI、GDI+相比,Direct2D(SharpDx等)的優勢在於利用硬件(GPU)繪制,節省時間,節省CPU的占用率,提高繪制效率。
GDI、GDI+等的繪制流程如下:
1、GDI、GDI+將繪制命令傳到CPU
2、CPU開始在內存中繪制圖形
3、CPU將繪制完的圖形傳到GPU
4、GPU將圖形傳到顯示設備(顯示器等)
Direct2D(SharpDx等)的繪制模式有Hardware(基於硬件)、Software(基於軟件)、Default(默認)
其中Software模式和GDI、GDI+繪制流程一樣。Default模式在初始化的時候會進行硬件檢測,如果硬件支持,則采用Hardware模式,如果硬件不支持,則采用Software模式
Direct2D(SharpDx等)在模式選擇為Hardware時的繪制流程如下:
1、Direct2D(SharpDx等)將繪制命令傳到CPU
2、CPU將繪制命令傳到GPU
3、GPU在顯存中繪制圖形
4、GPU將繪制好的圖形傳到顯示設備(顯示器等)
上述兩個流程的區別在於:
GDI、GDI+等是利用CPU繪制圖形,繪制圖形在內存中有備份。
Direct2D(SharpDx等)的Hardware模式是利用GPU繪制圖形,內存中並沒有備份。和GDI、GDI+等相比優勢在於快,節省CPU占用(GPU的繪制效率遠高於CPU)。但也有一些問題,就是CPU將繪制命令傳到GPU后,就不管了,至於GPU繪制成什么樣子,那就是GPU的事了。這也可以解釋為何早期的顯卡,有時會出現渲染的錯誤。
WIC如何將繪制的圖形編碼到圖形文件
在Direct2D的說明幫助里提到,如果需要利用WIC將RenderTarget上的內容編碼到圖形文件中的話,則得把RenderTarget的模式設置為Software(不能是Hardware,以目前的電腦配置Default基本上等同於Hardware)
WIC將RenderTarget上的內容編碼到圖形文件的流程如下:
1、創建WicBitmap對象,再之上創建WicRenderTarget對象
2、創建D2DBitmap對象,再利用CopyFromRenderTarget方法把RenderTarget上的內容復制到D2DBitmap對象
3、利用WicRenderTarget對象的DrawBitmap方法把D2DBitmap對象繪制到WicBitmap對象上
4、創建BitmapEncoder對象,在之上創建BitmapFrameEncoder對象,並創建和BitmapEncoder相關的Stream對象
5、將WicBitmap對象寫入到BitmapFrameEncoder對象
6,調用BitmapFrameEncoder對象和BitmapEncoder對象的Commit方法,將內容編碼到Stream對象,可以保存到文件
在Software模式下,是利用CPU繪制圖形,結果在內存中有緩存。WIC的WicRenderTarget對象的DrawBitmap方法能把緩存中的內容繪制到WicBitmap上。
而在Hardware模式下,利用的是GPU繪制圖形,在內存中沒有緩存。WIC的WicRenderTarget對象的DrawBitmap方法沒法把內容繪制到WicBitmap上(因為緩存中沒有),強行調用的話,會報錯的。
我們需要WIC的圖片編碼功能么?
用Direct2D(SharpDx等)就是看重其硬件加速的能力,但也籍此不能使用WIC保存繪制的內容;如果要使用WIC保存繪制的內容,則Direct2D(SharpDx等)的繪制模式設置為Software,但又犧牲了硬件加速能力,其效率和GDI、GDI+等相差無幾。
再加上WIC實際上是調用系統默認的編碼器對圖形進行編碼,但同時幾乎不提供的可調參數的功能。例如:我們知道在保存JPG的時候,可以設置精度(因為JPG是有損壓縮,根據精度的不同,保存的文件大小也不相同),但是用WIC保存為JPG的時候,卻沒有參數可以設置精度(或者是我沒找到);保存為GIF時,可以設置每幀之間的間隔時間,但在WIC中也沒有相應的屬性可以提供(也許可以通過添加MetaData的方式設置該屬性)。
換個角度考慮,圖形的編碼遠比解碼復雜的多。解碼圖形,只要依據已經存在的數據按照一定的規則解碼就行了,即使是用不同的解碼器解碼出來的圖形應該是毫無二致。但是,編碼就不同了,同樣的格式、同樣的參數,不同的編碼器出來的文件可能就不一樣了(我們用PS和Fireworks編碼出來的GIF文件大小就不一樣)。
因此,如果是采用默認編碼器對圖形編碼的話,真不一定需要WIC(WIC僅僅是提供了一個調用的途徑),在GDI+中完全可以利用Bitmap對象的Save方法做到。如果需要對編碼進行參數設置的話,以獲得不同的文件的話,這個似乎WIC又做不到。
因此,看來我們並不需要WIC的圖片編碼功能。再說,我們使用Direct2D(SharpDx等)是依靠其硬件加速的能力,加強圖形渲染功能。
現在在研究GIF的編碼,發現 Robin 寫的系列文章不錯。待研究后再書新文
