Я экспериментировал с способами захвата экрана на окнах и, следовательно, самым быстрым способом сделать это. Наиболее распространенным является, очевидно, путь GDI. И это достойно и в производительности. В зависимости от загрузки системы и статического/нестатического содержимого экрана скорость захвата экрана варьировалась от 27-47 кадров в секунду (Windows 7, Intel i5 @ 2,6 ГГц, 8 ГБ оперативной памяти).Использование DirectX для захвата экрана в Windows
Теперь, используя подход Front Front front buffer (используя API GetFrontBufferData()), производительность была сопоставимой, но немного более медленной (я не мог достигать 48 кадров в секунду).
Я прошел через это сообщение: 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);
Пожалуйста, укажите на ошибку в коде выше. Любые предложения приветствуются. Я также попробовал API GetBackBuffer(), но я не смог получить данные изображения.
EDIT:
Мой случай использования был захват рабочего стола экран, который, кажется, сделано только с помощью GetFrontBufferData() с помощью DirectX. GetBackBuffer()/GetRenderTargetData() не является правильным API для вызова этого случая. Ссылка: The desktop capture with DirectX does not work и How to get the screenshot of the desktop from back buffer with DirectX.
Однако любые предложения по ускоренному методу захвата экрана рабочего стола или оптимизации способа GDI приветствуются.
Я чувствую, что 'GetRenderTarget' вернет задний буфер для устройства. Вы можете посмотреть функцию 'GetFrontBufferData'. –
Я использовал GetFrontBufferData(), как упоминалось в вопросе, он отлично работает. Но нет никакой выгоды в производительности по сравнению с GDI. Я искал более быстрый подход, если он есть. –
Я также пишу приложение screencapture. [Здесь] (http://stackoverflow.com/q/31286503/4794952) является ссылкой на мою проблему. Я получаю черный экран, когда я захватываю любую игру, тогда как для любого другого приложения он возвращает правый захваченный экран. Есть ли способ заставить его работать с полноэкранными играми? – newbie2015