計算機屏幕圖像的截取在屏幕的錄制、計算機遠程控制以及多媒體教學軟件中都是關鍵術,基於Windows操作系統有多種截屏方法,研究的重點集中在如何快速有效的截取DBI(Device-Independent Bitmap)格式的屏幕圖形數據。現在商業軟件流行的截屏技術主要采取的Api Hook技術,但這種技術一次截屏仍有較大的時間消耗,這樣就對運行軟件的硬件仍有較多的限制,而且是一種非標准的技術,不為微軟公司所推薦。
1截屏技術
1.1使用api hook技術
使用api hook技術截屏基於一下的原理;多數屏幕圖形的繪制都是通過調用用戶態gdi32.dll中的繪圖函數實現的,如果利用api hook技術攔截系統中所有對這些函數的調用,就可以得到屏幕圖形刷新或變化的區域坐標;然后使用api函數bitblt將刷新或者變化后的屏幕區域的ddb格式的位圖拷貝到內存中,接着使用函數getbits將ddb位圖轉換為dbi位圖,最后壓縮、存儲或者傳輸。
這種方案只有捕捉到變化,才進行截屏。這樣每次截屏都是有效的操作。每次(第一次除外)僅截取了栓新或變化部分,從根本上解決了數據量大的問題。但是這種技術仍然有一下缺點:1實際截屏采用的api函數,截取的是ddb位圖,要經過一次格式轉換,耗時較大。2如果屏幕變化區域矩形的坐標r1、r2、……rn相繼到達,為了不是屏幕變化的信息丟失,通常不是逐個截取,而是將矩形坐標合並,這樣就可以截取並未變化的區域,不經增加截屏的時間消耗,而且產生冗余數據。3該技術不支持directdraw技術,由於應用程序可能使用directdraw驅動程序進行直接操縱顯示內存、硬件位塊轉移,硬件重疊和交換表面等圖形操作,而不必進行gdi調用,所以此時api hook技術將失去效用,不能捕捉屏幕變化。4api hook技術在屏幕取詞,遠程控制和多媒體教學中都有實際的應用,但是這種技術是一種非標准的技術,微軟公司並不推薦使用。
1.2 使用圖形驅動技術
該技術的原理:應用程序調用win32 gdi 函數進行圖形輸出請求,這個請求通過核心模式gdi發送。核心模式gdi把這些請求發送到相應的圖形驅動程序。如,顯示器驅動程序,通信流如圖。現將該技術詳細解釋如下:
(1)顯示器驅動輸出一系列設備驅動程序接口DDI(Device Driver Interface)函數供GDI調用。信息通過這些入口點的輸入/輸出參數在GDI和驅動程序之間傳遞。
(2) 在顯示器驅動加載時,GDI調用顯示器驅動程序函數DrvEnableDriver,在這里我們向GDI提供顯示器驅動支持的,可供GDI調用的DDI函數入口點,其中部分時將要Hook的圖形輸出函數。
(3) 在GDI調用函數DrvEnableDriver成功返回后,GDI調用顯示器驅動的DrvEnablePDEV函數,在這里可以設置顯示器的顯示模式,然后創建一個PDEV結構,PDEV結構是物理顯示器的邏輯表示。
(4) 在成功創建PDEV結構之后,顯示驅動為視頻硬件創建一個表面,該表面可以是標准的DIB位圖管理表面,然后驅動程序使該表面與一個PDEV結構相關聯,這樣顯示驅動支持的所有繪畫操作都將在該DIB位圖表面上進行。
(5) 當應用程序調用用戶態GDI32.DLL中的繪圖函數發出圖形請求時,該請求將圖形引擎通過相應的DDI函數發送到顯示驅動,顯示驅動程序將這次圖形變化事件通知應用程序。
(6) 應用程序接受到通知后,調用函數ExtEscape發出一個請求,並通過參數傳遞一個緩沖區Buffer,圖形引擎調用DDI函數DrvEscape處理應用層的ExtEscape調用,將變化部分的圖形數據從其創建的表面拷貝Buffer,這樣數據就從核心層圖形驅動傳到應用層。
(7) 應用程序接收到的圖形數據已是DIB標准格式,所以可以直接進行壓縮傳輸或儲存。
1.3圖形驅動技術的特點
上面敘述了采用圖形驅動實現屏幕實現截屏的原理和過程,可以看出這種技術涉及核心圖形驅動的編寫,實現上較為復雜,而其具備的優點主要為:
(1) 驅動技術只截取變化的屏幕區域,這一點與API Hook技術相當;但驅動技術是一種標注技術,為微軟公司所推薦。
(2) API Hook技術在實際截屏時,采用API函數實現,截取DDB位圖,必須經過一次DDB到DIB的轉換;而驅動技術直接從其管理的DIB位圖(表面)中將截取區域的圖形數據拷貝到應用程序,顯著的降低了一次截屏的時間消耗。
(3) 如果屏幕圖形小區域范圍變化較快,屏幕變化區域矩形坐標R1、R2、R3……、Rn相繼到達,由於一次截屏時間消耗降低,區域矩形坐標疊加的概率變小,這樣屏幕變化區域及時的得到了處理,不僅增加了連續性,而且截屏時間消耗和產生的數據量一般不會出現峰值,這也是這種技術的優越之處。經過以上對比,無論是做遠程桌面還是屏幕錄制,基於MirrorDriver的屏幕截取將會是一個不錯的選擇,無論從性能占用資源的大小(主要是cpu),取得的數據量來說都要優於Hook。
最近在做遠程桌面的傳輸,所以有必要研究一下Mirror,這項技術在很多軟件中都有應用。但是開源的driver我還沒有看見過,因為沒有精力去編寫。所以才用網上的免費的driver同時也提供了api文檔。
driver內部實現的原理大致就是把顯示輸出拷貝到一個緩沖區當中,並且記錄每次屏幕更新的矩形區域。根據這些輸出,應用程序就很容易得到緩沖區中的數據了。
