c++ - 通过 TCP 发送的图像被翻转

标签 c++ sockets winapi gdi bitblt

我创建了一个客户端,它通过 TCP 将屏幕截图发送到服务器。图像已成功发送。但是在接收时图像是颠倒的(我知道这是由结构属性之一的负高度设置的)。 我已经在互联网上搜索了这样做的方法,但我找不到合适的方法来实现这一点。所以如果有更好的方法,请纠正我。

这就是我发送屏幕截图(客户端)的方式:

HDC ScreenDC = GetDC(0);
HDC hMemory = CreateCompatibleDC(ScreenDC);
POINT ScreenSize = { GetDeviceCaps(ScreenDC, HORZRES),GetDeviceCaps(ScreenDC, VERTRES)};

// fill the hbitmap wtih the screenshot
HBITMAP hBitmap = CreateCompatibleBitmap(ScreenDC, ScreenSize.x, ScreenSize.y);
HGDIOBJ hOldBitmap = SelectObject(hMemory, hBitmap);
BITMAPINFO bmpInfo = { 0 };

bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);
GetDIBits(ScreenDC , hBitmap, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS); // fill bmpInfo with info about the hBitmap
char * dataBuffer = new char[bmpInfo.bmiHeader.biSizeImage];

// adjust the header for our needs
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;  // no compression -> easier to use
bmpInfo.bmiHeader.biHeight = abs(bmpInfo.bmiHeader.biHeight);
BitBlt(hMemory, 0, 0, ScreenSize.x, ScreenSize.y, ScreenDC, 0, 0, SRCCOPY); // take a screenshot
GetDIBits(ScreenDC, hBitmap, 0, bmpInfo.bmiHeader.biHeight, dataBuffer, &bmpInfo, DIB_RGB_COLORS);  // fill dataBuffer with raw image data

// send first the bmpInfo.bmiHeader struct
// send raw data : dataBuffer
//.....

我确信消息被正确发送和接收,因为我已经实现了一个用于分离数据包的协议(protocol)。这不是问题。

这是接收者(服务器):

// data is the entire sent : structure + dataBuffer

HDC hDc = GetDC(windowHwnd);
HDC tCpyHdc = CreateCompatibleDC(hDc);

BITMAPINFOHEADER bmpHeader = *(BITMAPINFOHEADER*)data;
BITMAP bmp;
bmp.bmType = 0;
bmp.bmWidth = bmpHeader.biWidth;
bmp.bmHeight = abs(bmpHeader.biHeight);
bmp.bmPlanes = bmpHeader.biPlanes;
bmp.bmWidthBytes = bmpHeader.biWidth * 4;
bmp.bmBitsPixel = bmpHeader.biBitCount;
bmp.bmBits = (char*)(data + sizeof(BITMAPINFOHEADER));

HBITMAP hB = CreateBitmapIndirect(&bmp);

HBITMAP oldBmp = (HBITMAP)SelectObject(tCpyHdc, hB);
StretchBlt(hDc, 0, 0, width - 20, height - 40, tCpyHdc, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);

图像颠倒了。我该如何解决?

最佳答案

感谢@Igor Tandetnik 我解决了这个问题。这是最终代码:

在客户端我发送 BITMAPINFO 而不是 BITMAPINFOHEADER:

//...
// send first the bmpInfo struct
// send raw data : dataBuffer
//.....

服务器端(我使用 CreateDIBSection 而不是 CreateBitmapIndirect):

// data is the entire sent : structure + dataBuffer

HDC hDc = GetDC(windowHwnd);
HDC tCpyHdc = CreateCompatibleDC(hDc);

BITMAPINFO bmpInfo = *(BITMAPINFO*)data;
BITMAP bmp;
bmp.bmType = 0;
bmp.bmWidth = bmpInfo.bmiHeader.biWidth;
bmp.bmHeight = -abs(bmpInfo.bmiHeader.biHeight);
bmp.bmPlanes = bmpInfo.bmiHeader.biPlanes;
bmp.bmWidthBytes = bmpInfo.bmiHeader.biWidth * 4;
bmp.bmBitsPixel = bmpInfo.bmiHeader.biBitCount;
bmp.bmBits = (char*)(data + sizeof(BITMAPINFO));

char* dibarr = NULL;
HBITMAP hB = CreateDIBSection(windowData.tCpyHdc, &bmpInfo, DIB_RGB_COLORS, (void**)&dibarr, 0, 0);
memcpy((void*)dibarr, (void*)bmp.bmBits, inf.packetsz - sizeof(BITMAPINFO));

HBITMAP oldBmp = (HBITMAP)SelectObject(tCpyHdc, hB);
StretchBlt(hDc, 0, 0, width - 20, height - 40, tCpyHdc, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);

关于c++ - 通过 TCP 发送的图像被翻转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45593404/

相关文章:

c++ - 将 void* (char* without\0) 转换为 std::string

Java面向事件的Socket库

java - 在标准 OutputStream 上并发写入

c++ - 失去弹跳球的位置

java - 使用 Java 中的 Windows API 调用使用 "native"

c++ - 在 win32 中创建自定义消息类型?

c++ - 在 C++ 中缓存昂贵的数据——函数范围的静态变量与可变成员变量

c++ - 为什么 "<<"运算符可以被继承而 ">>"运算符不能?

c++ - 运算符按位左移

linux - 套接字将端口绑定(bind)到我的本地主机和盒子IP中的相同端口