我在程序中实现抓屏,根据 Various methods for capturing the screen 文章中的两种方式(以下时间的计算都为release版)。发现使用GDI方式抓一次屏的时间大概20毫秒左右,但是使用DirectX9抓一次屏的时间竟然是400毫秒左右。各位看看问题出现在哪里?DirectX不会就是这样的速度吧?
DirectX code: InitD3D(m_hWnd);
DWORD u32Time = ::GetTickCount();
g_pd3dDevice->CreateOffscreenPlainSurface(ScreenWidth, ScreenHeight,
D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
g_pd3dDevice->GetFrontBufferData(0, pSurface);
D3DXSaveSurfaceToFile("Desktop.bmp",D3DXIFF_BMP,pSurface,NULL,NULL);//save the bmp
pSurface->Release();
u32Time = ::GetTickCount() - u32Time;
我是想找个更快的抓屏方法,16ms都感觉有点慢,因为我的电脑配置比较好。可是换成DirectX竟然400毫秒。
各位要是有更好更快的抓屏方法请贡献一个,不胜感觉。Thanks in advance!
DirectX code: InitD3D(m_hWnd);
DWORD u32Time = ::GetTickCount();
g_pd3dDevice->CreateOffscreenPlainSurface(ScreenWidth, ScreenHeight,
D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
g_pd3dDevice->GetFrontBufferData(0, pSurface);
D3DXSaveSurfaceToFile("Desktop.bmp",D3DXIFF_BMP,pSurface,NULL,NULL);//save the bmp
pSurface->Release();
u32Time = ::GetTickCount() - u32Time;
我是想找个更快的抓屏方法,16ms都感觉有点慢,因为我的电脑配置比较好。可是换成DirectX竟然400毫秒。
各位要是有更好更快的抓屏方法请贡献一个,不胜感觉。Thanks in advance!
解决方案 »
- 如何判断一个float函数的当前值和过100ms的值。
- 为什么下载不到VC.net2002
- VC串口程序占用CPU很高
- 真是见鬼,有个图片,UrlDownloadToFile不能下,用迅雷却可以下
- ftp断点续传的疑问哦...
- 如何填充一个任意多边形啊?急!!!!!!!!!!!!
- 请教为什么要用long?
- 在那里可以找到这些指针(IHTMLDocument2,IHTMLElement等等)的相关资料?
- 关于CRichEditView的问题,急!
- 小弟看VC技术内幕已经看了有一个月了,可是什么也没看懂,请指教。
- VC最新动向? 现在VS.net 2008出来了。VC方面有什么变化吗?
- 如何改变对话框背景?
to:zhoujianhei g_pd3dDevice-> GetFrontBufferData(0, pSurface); 这个函数执行最长 300多ms
D3DXSaveSurfaceToFile("Desktop.bmp",D3DXIFF_BMP,pSurface,NULL,NULL); 次之 几十ms.
我希望是抓屏后保存在内存,然后执行压缩之类的再送出。
各位继续!!!HRESULT InitD3D(HWND hWnd)
{
D3DDISPLAYMODE ddm;
D3DPRESENT_PARAMETERS d3dpp; if((g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))==NULL)
{
AfxMessageBox("Unable to Create Direct3D ");
return E_FAIL;
} if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&ddm)))
{
AfxMessageBox("Unable to Get Adapter Display Mode");
return E_FAIL;
} ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS)); d3dpp.Windowed=WINDOW_MODE;
d3dpp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
d3dpp.BackBufferFormat=ddm.Format;
d3dpp.BackBufferHeight=nDisplayHeight=gScreenRect.bottom =ddm.Height;
d3dpp.BackBufferWidth=nDisplayWidth=gScreenRect.right =ddm.Width;
d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow=hWnd;
d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_DEFAULT;
d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT; if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dpp,&g_pd3dDevice)))
{
AfxMessageBox("Unable to Create Device");
return E_FAIL;
} if(FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(ddm.Width, ddm.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL)))
{
AfxMessageBox("Unable to Create Surface");
return E_FAIL;
} return 0;
},第一次使用DirectX.
Init code:
HRESULT InitD3D(HWND hWnd)
{
D3DDISPLAYMODE ddm;
D3DPRESENT_PARAMETERS d3dpp;
if((g_pD3D=Direct3DCreate9(D3D_SDK_VERSION))==NULL)
{
return E_FAIL;
}
if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&ddm)))
{
return E_FAIL;
}
ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
d3dpp.Windowed=WINDOW_MODE;
d3dpp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
d3dpp.BackBufferFormat=ddm.Format;
d3dpp.BackBufferHeight=nDisplayHeight=gScreenRect.bottom =ddm.Height;
d3dpp.BackBufferWidth=nDisplayWidth=gScreenRect.right =ddm.Width;
d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE;
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow=hWnd;
d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_DEFAULT;
d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;
if(FAILED(g_pD3D->CreateDevic(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dpp,&g_pd3dDevice)))
{
return E_FAIL;
} if(FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(ddm.Width, ddm.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL)))
{
return E_FAIL;
} return 0;
}
期待高手出来解惑..............................
个人愚见,有不对的还请大牛指正
”就不用API,自己来实现它 “ 对于这个不用api自己来实现,由于能力不够,是否可以给个自己实现的思路?只要思路就可以了,我会去实现。Thanksto all:有好建议的请提出来,热烈欢迎! 能详细的就给详细点,不然就给个思路。
Thanks in advance!!!
内存压缩再SEND,当然然取的并不一定是全屏,是有时机与有效区域,你看下mircosoft的远程桌面刷新方式就知道了,
尽量减少I/O操作
保存文件只是为了查看一下抓的屏对不对,其实真的要实现的时候是只要buffer就可以了的。
“mircosoft的远程桌面刷新方式”从哪里可以看到mircosoft的远程桌面刷新方式?? 请再说明一下,谢谢!
---------------
主表面的buffer数据在内部是加了锁保护的,读取时要等到解锁才能返回。与刷新率相关。
但是如同前面说的,抓取别的程序生成的窗口的数据并不占据优势; 至于慢的原因抓取的速度20ms应该是够快的了,人眼可以识别的25帧, 平均40ms就够了另外, 你用的时间技术器不适合做这个判断, 它太粗了, 要找更高精度的计数器来计算
再说你把保存磁盘文件的时间也计算进去了,磁盘io的速度是很慢的。
to:shrnruo 是否我在GetFrontBufferData 之前进行刷新屏幕的话程序执行会更快一点。感谢大家关注,请继续!!!
后来才发现在debug状态的时候,根本发挥不出硬件指令的优势,在release下面快了n倍,
楼主可以试试用release版对比