我正试图以这种方式在控制台win32应用程序中进行屏幕截图:
char* getScreenshot(){
HDC hScreenDC = CreateDC("DISPLAY", NULL, NULL, NULL);
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
int x = GetDeviceCaps(hScreenDC, HORZRES);
int y = GetDeviceCaps(hScreenDC, VERTRES);
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, x, y);
size_t width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
size_t height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
BitBlt(hMemoryDC, 0, 0, width, height, hScreenDC, 0, 0, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemoryDC, hOldBitmap);
char* buffer = new char[x*y]();
GetBitmapBits(hBitmap,x*y,buffer);
DeleteDC(hMemoryDC);
DeleteDC(hScreenDC);
return buffer;
}
缓冲区应该是包含hbitmap屏幕截图的字节数组。
然后我用这种方式通过一个套接字发送:
char *buff = getScreenshot();
string a(buff);
send(hClientSocket, buff, a.length(), 0);
if (hClientSocket!=INVALID_SOCKET)
closesocket(hClientSocket);
我用这种方式从php获取if:
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
set_time_limit(15);
$succ = socket_connect($sock, $ip, $port) or die("timeout");
$output = "";
while($resp = socket_read($sock, 1000)) {
$output .= $resp;
}
socket_close($sock);
$base64 = base64_encode($output);
echo "<img src='data:image/bmp;base64,$base64' />";
我的问题是我不能用上面写的方法来显示图像。
可能是什么问题?我哪里错了?
谢谢!
编辑
根据@Peter R.Bloomfield的说法,我将我的功能更改为:
char* getScreenshot(int* length){
...
*length = x*y;
...
}
并发送到套接字:
int length;
char *buff = getScreenshot(&length);
send(hClientSocket, buff, length, 0);
但它继续避免显示。。。
BMP图像不仅仅是图像中的"位"(即buffer
中的位)。BMP图像有一个包含宽度、高度、每像素位数和其他一些项目的标题。
最简单的方法是将HBITMAP保存为图像文件,然后在套接字代码中加载文件数据。如果你不想把它保存为文件,那么你必须构造一个兼容的头,并在实际的图像数据之前发送它。
至少为了确认你的原则,在编写代码制作标题之前,可以尝试"将位图保存到文件"的方法。
这必然会导致问题:
char *buff = getScreenshot();
string a(buff);
您正在获取一个任意二进制数据的数组,并试图将其转换为string
对象。char *
构造函数将需要一个以null结尾的字符串。这意味着当图像中的某个像素在任何RGB分量中的值为0时,它将停止。
对于传输原始像素数据,最好完全避免转换为string
对象。只需将char *
指针直接传递给send()
函数。不过,您显然需要告诉它正确的大小(任何类似strlen()
的东西都会遇到与string
构造函数相同的问题)。您可以通过引用参数从getScreenshot()
函数中传递大小信息。
我怀疑,当您以HTML格式输出图像时,您也会遇到缺少标头信息的问题。客户端浏览器目前无法判断图像的尺寸(即宽/高像素数)或数据格式。