2013-07-23 119 views
5

我正在試驗如何捕獲窗口上的屏幕,並因此決定最快的方式。最常見的顯然是GDI方式。在性能方面也不錯。根據系統負載和靜態/非靜態屏幕內容,屏幕捕捉速率範圍爲27-47 fps(Windows 7,Intel [email protected] GHz,8 GB RAM)。使用DirectX捕獲Windows上的屏幕

現在,使用DirectX前端緩衝區方法(使用GetFrontBufferData()API),性能相當,但稍慢一些(我無法達到48 fps)。

我通過這篇文章去:Fastest method of screen capturing和嘗試了使用getRenderTarget()和getRenderTargetData()在接受的答案建議的方式,但在意見提出,我得到的是一個黑色的圖像。這裏是我完整的代碼,包括對設備的初始配置:

IDirect3DSurface9* pRenderTarget=NULL; 
    IDirect3DSurface9* pDestTarget=NULL; 
    // sanity checks. 
    if (g_pd3dDevice == NULL){ 
     return; 
    } 
    HRESULT hr; 
    // get the render target surface. 
    hr = g_pd3dDevice->GetRenderTarget(0, &pRenderTarget); 
    // get the current adapter display mode. 
    //hr = pDirect3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&d3ddisplaymode); 

    // create a destination surface. 
    hr = g_pd3dDevice->CreateOffscreenPlainSurface(1600, 900, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pDestTarget, NULL); 
    //copy the render target to the destination surface. 
    hr = g_pd3dDevice->GetRenderTargetData(pRenderTarget, pDestTarget); 

    D3DLOCKED_RECT lockedRect; 
    hr =pDestTarget->LockRect(&lockedRect,NULL, D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY); 

    for(int i=0 ; i < 900 ; i++) 
    { 
     for(int j=0; j < 1600; j++){ 
      memcpy((BYTE*) data + i * 1600 * 3 + j * 3, (BYTE*) lockedRect.pBits + i* lockedRect.Pitch + j * 4, 3); 
     } 
    } 
    pDestTarget->UnlockRect(); 
    // clean up. 
    pRenderTarget->Release(); 
    pDestTarget->Release(); 

而對於設備初始化部分:

g_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION); 
D3DPRESENT_PARAMETERS PresentParams; 
memset(&PresentParams, 0, sizeof(D3DPRESENT_PARAMETERS)); 
PresentParams.Windowed = TRUE; 
PresentParams.SwapEffect =D3DSWAPEFFECT_DISCARD; 
g_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL ,GetDesktopWindow(),D3DCREATE_SOFTWARE_VERTEXPROCESSING, &PresentParams,&g_pd3dDevice); 

請指出在上面的代碼中的錯誤。歡迎任何建議。我也嘗試過GetBackBuffer()API,但我無法掌握圖像數據。

編輯:

我的使用情況下是捕獲桌面屏幕,這似乎只能通過使用DirectX的GetFrontBufferData()來完成。 GetBackBuffer()/ GetRenderTargetData()不是調用這種情況的正確API。參考:The desktop capture with DirectX does not workHow to get the screenshot of the desktop from back buffer with DirectX

然而,歡迎任何關於捕獲桌面屏幕或優化GDI方式的更快速方法的建議。

+1

我覺得'GetRenderTarget'會返回設備的後臺緩衝區。你可能想看看'GetFrontBufferData'函數。 –

+0

我已經使用GetFrontBufferData()在問題中提到,它工作正常。但是,GDI方式的表現沒有任何好處。如果有的話,我正在尋找更快的方法。 –

+0

我還在編寫一個screencapture應用程序。 [Here](http://stackoverflow.com/q/31286503/4794952)是我的問題的鏈接。當我捕捉任何遊戲時,我會看到一個黑屏,而對於任何其他應用程序,它會返回正確的捕捉屏幕。有什麼辦法可以讓它在全屏遊戲中運行嗎? – newbie2015

回答

2

在拍攝截圖之前您是否渲染過任何東西?

  • GetFrontBufferData - 此功能讓屏幕
  • GetRenderTargetData的數據 - 該功能得到數據渲染目標

所以,如果你沒有任何渲染,你一定會得到一個空白圖片。

+0

我可能在這裏沒有語境。我的用例是獲取桌面屏幕的數據。那麼,你是否建議GetRenderTargetData()不是要調用的正確API。你能否詳細說明渲染部分? –

+0

檢查你的答案在這裏http://stackoverflow.com/questions/12859894/the-desktop-capture-with-directx-does-not-work/12863143#12863143 ..所以,GetFrontBufferData()是唯一的API用於通過DirectX捕獲桌面屏幕。 –

+1

是的,GetRenderTargetData()用於從應用程序的渲染目標獲取數據,而不是桌面。 – zdd