我打算创建一些"远程桌面"通过套接字将屏幕内容流式传输到连接的客户端的应用程序。
为了拍摄截图,我已经提出了以下代码,这是我在这里和那里看到的示例的修改版本。
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
int _tmain( int argc, _TCHAR * argv[] )
{
int ScreenX = 0;
int ScreenY = 0;
BYTE* ScreenData = 0;
HDC hScreen = GetDC(GetDesktopWindow());
ScreenX = GetDeviceCaps(hScreen, HORZRES);
ScreenY = GetDeviceCaps(hScreen, VERTRES);
ScreenData = (BYTE*)calloc(4 * ScreenX * ScreenY, sizeof(BYTE) );
BITMAPINFOHEADER bmi = {0};
bmi.biSize = sizeof(BITMAPINFOHEADER);
bmi.biPlanes = 1;
bmi.biBitCount = 32;
bmi.biWidth = ScreenX;
bmi.biHeight = -ScreenY;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = 0; // 3 * ScreenX * ScreenY;
int iBegTc = ::GetTickCount();
// Take 100 screen captures for a more accurante measurement of the duration.
for( int i = 0; i < 100; ++i )
{
HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, ScreenX, ScreenY);
HDC hdcMem = CreateCompatibleDC (hScreen);
HGDIOBJ hOld = SelectObject(hdcMem, hBitmap);
BitBlt(hdcMem, 0, 0, ScreenX, ScreenY, hScreen, 0, 0, SRCCOPY);
SelectObject(hdcMem, hOld);
GetDIBits(hdcMem, hBitmap, 0, ScreenY, ScreenData, (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
DeleteDC(hdcMem);
DeleteObject(hBitmap);
}
int iEndTc = ::GetTickCount();
printf( "%d ms", (iEndTc - iBegTc) / 100 );
system("PAUSE");
ReleaseDC(GetDesktopWindow(),hScreen);
return 0;
}
我的问题是循环中的代码执行时间太长。就我而言,每次迭代大约36毫秒。
我想知道是否有一些语句可以只执行一次,因此放在循环之外,对于字节缓冲区,我做了。我不知道哪些是我必须为每个新图像做的,哪些是我只能做一次的。
答案 0 :(得分:0)
将BitBlt
和GetDIBits
保留在循环中,将其余内容移动到循环外部,如下所示:
HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, ScreenX, ScreenY);
HDC hdcMem = CreateCompatibleDC (hScreen);
HGDIOBJ hOld = SelectObject(hdcMem, hBitmap);
for( int i = 0; i < 100; ++i )
{
BitBlt(hdcMem, 0, 0, ScreenX, ScreenY, hScreen, 0, 0, SRCCOPY);
//hBitmap is updated now
GetDIBits(hdcMem, hBitmap, 0, ScreenY, ScreenData, (BITMAPINFO*)&bmi, DIB_RGB_COLORS);
//wait...
}
SelectObject(hdcMem, hOld);
DeleteDC(hdcMem);
DeleteObject(hBitmap);
此外,bmi.biSizeImage
应设置为数据大小,在本例中为4 * ScreenX * ScreenY
这不会使代码明显加快。瓶颈位于BitBlt
。它仍然是大约30帧/秒,除非屏幕上有游戏或电影,否则这应该没问题。
您也可以尝试保存为24位位图。它不会对此代码产生任何影响,但数据大小会更小((width * bitcount + 31) / 32) * 4 * height)
答案 1 :(得分:0)
Windows的Aero功能似乎会影响BitBlt的速度。
如果从显示器上迭代一个BitBlt甚至一个像素,它将以每秒30帧的速度运行,并且CPU使用率将接近空闲状态。但是,如果关闭Windows的Aero功能,则会获得显着更快的BitBlt速度。