使用DirectX在Windows上捕获屏幕
Using DirectX to capture screen on Windows
我一直在尝试在窗口上捕获屏幕的方法,因此决定了最快的方法。最常见的显然是GDI方法。它的表现也不错。根据系统负载和静态/非静态屏幕内容,屏幕捕获速率在27-47 fps之间(Windows 7,Inteli5@2.6GHz、8GB RAM)。
现在,使用DirectX前缓冲区方法(使用GetFrontBufferData()API),性能相当,但速度稍慢(我无法达到48fps)。
我浏览了这篇文章:最快的屏幕捕捉方法,以及使用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方式的更快方法的建议都是受欢迎的。
在截屏之前你渲染过什么吗?
- GetFrontBufferData-此函数用于获取屏幕的数据
- GetRenderTargetData-此函数从渲染目标获取数据
所以,如果你不渲染任何东西,你肯定会得到一个空白的图像。
相关文章:
- 在 Windows 8/10 技术中完全实时的屏幕捕获,没有延迟
- C++ Windows 凭据提供程序错误屏幕
- 显示和隐藏Windows 10屏幕键盘(osk.exe)时遇到问题
- 用SFML在屏幕顶部(Windows)绘制
- 如何在 Windows 10 上检测辅助监视器的本机屏幕分辨率或缩放因子
- 我可以讓 MoveWindow 在 Windows 10 中使用屏幕協調嗎?C++
- MFC和Windows API之间的区别在获取屏幕分辨率方面
- 如何检测Windows开始菜单/开始屏幕何时打开
- 使用C++在Windows 8中不固定到"开始屏幕"的应用程序快捷方式
- 更改Windows 8启动屏幕颜色
- 如何使用mouseevent在windows登录屏幕中移动鼠标光标
- 要在Windows上读取/设置用户屏幕保护程序,是否需要使用系统注册表或SystemParametersInfo API
- 在 WIndows 8.1 中捕获 PC 的整个屏幕截图
- 关机时如何在Windows XP中强制"it's now safe to turn off your computer"屏幕?
- 在Windows桌面共享API上,UAC提示变为黑色暂停屏幕
- 是否可以在本机 Windows 8.1 桌面应用程序中确定屏幕方向
- 在没有 DirectX 的 Windows 上获得精确的屏幕刷新率
- 在 C++/Qt/Windows 中控制 Windows 屏幕方向
- Windows 桌面屏幕标记
- 在Windows中的屏幕上渲染缓冲区