HBitmap字节数组到php

时间:2013-11-19 13:53:07

标签: php c++ winapi base64

我正试图以这种方式在我的控制台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中捕获:

$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;
   ...
}

并发送到socket:

int length;
char *buff = getScreenshot(&length);
send(hClientSocket, buff, length, 0);

但它继续避免显示......

2 个答案:

答案 0 :(得分:2)

BMP图像不仅仅是图像中的“位”(这是buffer中的内容)。 BMP图像的标题包含宽度,高度,每像素位数和其他一些此类项目。

最简单的方法是将HBITMAP保存为图像文件,然后在套接字代码中加载filedata。如果您不想将其另存为文件,则必须构建兼容的标头并在实际图像数据之前发送。

至少要确认您的原则,请在编制代码之前尝试“保存位图到文件”的方法。

答案 1 :(得分:1)

这肯定会引起问题:

char *buff = getScreenshot();
string a(buff);

您正在获取一组任意二进制数据,并尝试将其转换为string对象。 char *构造函数将期望以null结尾的字符串。这意味着它将在第一次图像中的一个像素在任何RGB分量中的值为0时停止。

要传输原始像素数据,最好避免完全转换为string对象。只需将char *指针直接传递给send()函数即可。您显然需要告诉它正确的大小(类似strlen()之类的问题与string构造函数有相同的问题)。您可以通过参考参数从getScreenshot()函数中传出大小信息。

我怀疑当您以HTML格式输出图像时,您也会遇到丢失标题信息的问题。客户端浏览器目前无法分辨图像的尺寸(即宽度/高度的像素数),或者数据格式是什么。