Windows で画面をキャプチャする方法を試していたので、最速の方法を決定しました。最も一般的なのは明らかに GDI の方法です。それでいて性能も申し分ありません。システム負荷と静的/非静的画面コンテンツに応じて、画面キャプチャ レートは 27 ~ 47 fps の範囲でした (Windows 7、Intel i5@2.6 GHz、8 GB RAM)。
現在、DirectX フロント バッファー アプローチ (GetFrontBufferData() API を使用) を使用すると、パフォーマンスは同等でしたが、わずかに遅くなります (48 fps には達しませんでした)。
私はこの投稿を見ました:スクリーンキャプチャの最速の方法と、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 ではありません。参考:DirectXでデスクトップキャプチャーがうまくいかない、 DirectXでバックバッファーからデスクトップのスクリーンショットを取得する方法
ただし、デスクトップ画面をキャプチャしたり、GDI の方法を最適化するためのより高速な方法についての提案は大歓迎です。