2D繪圖引擎比較

 

           這個問題很廣泛。最近在研究這個問題,在網上搜了一些資料,再結合本身的經驗,談談本身的一些想法。html

 

                                                                一.雙緩存能提升繪圖效率嗎?程序員

 

網上有篇文章:繪圖效率完整解決方案——三種手段提升GDI/GDI+繪圖效率,其中提到一種方法是:1. 緩存——Bitmap或者DoubleBuffer。緩存就是先把繪製的圖形繪製到一張內存位圖上,而後在一次性的貼位圖,他能夠提升繪圖速度,也能避免閃爍。DoubleBuffer=true是C#窗體的屬性,設置了此屬性估計系統自己會起用無效區的內存位圖緩存,而不須要程序員Bitmap處理。數組

 

這裏對雙緩存的一般作法不做介紹,網上的相關資料不少。說實話,我對使用雙緩存能提高繪圖效率表示懷疑,理由很簡單,同是DC,同是繪製1000條線段,有什麼理由內存DC就比窗口DC快(固然這個我沒有做具體的測試,這個有空能夠測試下)。我還稍微懷疑使用雙緩存繪圖比直接使用窗口DC繪圖還慢一些,理由有二:一是使用雙緩存須要增長建立內存DC和內存位圖的操做;二是使用雙緩存還須要增長一個把內存DC拷貝到窗口DC的操做。那麼雙緩存的主要做用是什麼?其實就是解決繪圖過程的閃爍問題,改善繪圖效果。緩存

 

                                                        二.Windows環境下二維繪圖引擎的選取數據結構

 

和繪圖效率的一個重要相關因素是繪圖引擎。Windows環境下二維繪圖引擎有多種選擇:GDI、GDI+、DirectDraw、QT、Agg、Cairo、skia、Direct2D、Direct3D、OpenGL等。下面我逐一做一個簡單的分析:架構

 

GDI:微軟原生的二維繪圖引擎。框架

優勢:微軟的全力支持,做爲操做系統核心層效率方面不用擔憂,支持多種開發框架(含語言):Win SDK、MFC、Delphi等。函數

缺點:基於過程,缺少面向對象,使用起來不太方便,不支持反鋸齒,不支持複雜的繪圖效果(這個相對於GDI+而言)。性能

 

GDI+:微軟後來推出的二維繪圖引擎。測試

優勢:微軟的全力支持,支持多種開發框架(含語言):Win SDK、MFC、Delphi等,能夠實現複雜的繪圖效果,如反鋸齒、路徑畫刷等;面向對象的架構,使用起來比較方便。

缺點:繪圖效率較GDI稍低,繪圖交互性不如GDI(缺乏GDI的支持位運算的繪圖模式),開啓反鋸齒後效率不如QT。

 

有關GDI和GDI+的詳細比較,請看我之前寫的一篇文章:GDI和GDI+的應用場合思考

 

DirectDraw:從GDI、GDI+到Direct 2D的一個過渡產品,微軟已明確表示不推薦使用,在MicrosoftDirectX SDK (June 2010)已看不到它的身影,在此不做介紹。

 

QT:開源跨平臺(基於LGPL協議),面向對象的方式組織,使用起來較爲方便。

 

Agg:C++編寫的開源繪圖引擎(基於GPL協議)

 

Cairo:C編寫的開源繪圖引擎(基於LGPL協議),大名鼎鼎的FireFox就是用這個繪圖引擎的。

 

   有關Agg和Cairo請參考這篇文章:Agg vs. Cairo 二維繪圖引擎之比較和選擇。該文做者比較推崇Cairo,但據我公司的一個同事介紹:Cairo的繪圖效率很慢。具體我沒有作過測試。

 

Skia:Google的Android的繪圖引擎。  

 

Direct2D:微軟在WindowsVista及以後的Windows版本推出的意在取代GDI、GDI+的二維繪圖引擎,支持硬件加速。

 

Direct3D:微軟開發的3D繪圖引擎。

 

OpenGL:SGI開發的3D繪圖引擎。

 

上面簡單對Windows下的二維繪圖引擎做了一個簡單介紹。個人推薦是:開發商業產品通常狀況下在Windows XP及如下Windows版本使用GDI和GDI+,在Windows Vista及其以後的Windows版本(如Win 7)使用Direct2D。理由是:跨平臺的繪圖引擎如Agg、Cairo之類的,出於跨平臺封裝的須要,必然會犧牲一部分性能,就是說它原本就是封裝GDI的,怎麼可能超出GDI的繪圖效率呢?還有就是諸如Agg還有開源協議的限制,這樣就排除了開源二維繪圖引擎。我也不推薦使用Direct3D、OpenGL等三維繪圖引擎進行二維繪圖,理由是三維繪圖能夠利用硬件加速,繪圖速度應該比GDI、GDI+快,但三維繪圖引擎通常是基於三維的數據結構進行組織的,對二維繪圖並不合適,好比之前咱們曾利用OpenGL進行二維繪圖,發現OpenGL在二維一些操做並不合適,如二維中的點、線捕捉、自定義圖例的添加、打印的支持等等。因此我傾向於使用GDI、GDI+。GDI的一大缺點是因爲不是面向對象組織的,使用起來較爲繁瑣。這個我以爲能夠參考GDI+的面向對象封裝的方式對GDI進行封裝。Direct 2D是微軟在後XP時代開發的開發二維繪圖引擎。微軟出於兼容性的考慮還會繼續對GDI、GDI+進行支持,但毫無疑問微軟的策略是要Direct 2D取代GDI和GDI+的,所以在WindowsVista及其以後的Windows上進行二維繪圖開發我建議是直接使用Direct2D。Direct 2D支持硬件加速,在繪圖效率應有必定程度的提高。

 

                                                                         三.提升GDI繪圖效率的經常使用作法

    

提升GDI繪圖效率的通常原則能夠簡單歸納爲:儘可能減小無效繪圖區域,儘可能減小沒必要要的繪圖操做。

 

儘可能減小繪圖區域的一般作法是:

  1. 設置裁剪區。裁剪區的做用就是:只有在這個區內的繪圖過程纔會真正有效,在區外的是無效的,即便在區外執行了繪圖函數也是不會顯示的。由於多數狀況下窗口重繪的產生大可能是由於窗口部分被遮擋或者窗口有滾動發生,改變的區域並非整個圖形而只有一小部分,這一部分須要改變的就是pDC中的裁剪區了。由於顯示(往內存或者顯存都叫顯示)比繪圖過程的計算要費時得多,有了裁剪區後顯示的就只是應該顯示的部分,大大提升了顯示效率。可是這個裁剪區是MFC設置的,它已經爲咱們提升了顯示效率,在進行復雜圖形的繪製時如何進一步提升效率呢?那就只有去掉在裁剪區外的繪圖過程了。能夠先用pDC->GetClipBox()獲得裁剪區,而後在繪圖時判斷你的圖形是否在這個區內,若是在就畫,不在就不畫。

 

  1. 減小無效區域。在GDI繪圖中,被標記爲無效矩形的區域直到WM_PAINT消息被處理完以後纔會消失。所以在繪圖中應儘可能避免使用Invalidate函數(該函數使整個客戶區設置爲無效區域),而應在多使用InvalidateRect函數具體好比你想改變某條線的線型,應首先精確計算改線的屏幕範圍,而後改變其線型後調用InvalidateRect函數進行局部更新。

 

  1. 儘可能減小沒必要要的繪圖操做。好比二維矢量繪圖中通常有一個滑動鼠標滾輪進行全圖縮放的操做。其實在縮放過程當中,每一次WM_MOUSEWHEEL消息的處理都必須是先把全部的繪圖對象重繪一次。這個其實並無必要。一個優化方案是經過設置一個標記,在繪圖循環中(通常在複雜繪圖中都把繪圖對象保存在一個數組或鏈表中),當這個標記爲TRUE時,就中止繪圖,當這個標記爲FALSE則不影響繪圖。在處理WM_MOUSEWHEEL消息是,先設置這個標記爲TRUE,而後發送一個重繪消息,設置標記爲FALSE進行重繪。而後在繪圖循環時先判斷這個標記是否TRUE,爲TRUE則退出繪圖,而後截取鼠標消息,優先WM_MOUSEWHEEL消息,大體代碼以下:

jpg改rar

相關文章
相關標籤/搜索