通过 TCP 发送的图像被翻转
Posted
技术标签:
【中文标题】通过 TCP 发送的图像被翻转【英文标题】:Image sent over TCP is flipped 【发布时间】:2018-01-17 12:06:08 【问题描述】:我创建了一个客户端,它通过 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
//.....
我确定消息正在正确发送和接收,因为我已经实现了用于分离数据包的协议。这不是问题。
这是接收方(服务器):
// 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);
图片颠倒了。我该如何解决?
【问题讨论】:
您在发送端使用与设备无关的位图(通过GetDIBits
),但在接收端使用与设备相关的位图(通过CreateBitmapIndirect
)。我建议您在接收端也使用 DIB,例如通过CreateDIBSection
我会测试它并回复它是否有效。谢谢
你是说 CreateDIBitmap 吧?因为我可以看到 CreateDIBSection 不会从 array 返回 HBITMAP 。我相信,基于 HDC,它会给出一个数组和一个 HBITMAP。这不是我想要的服务器。
CreateDIBSection
创建一个新的位图,并让您直接访问其数据存储。您可以将您的位复制到该存储中,它们将立即反映在位图中。但如果您愿意,我认为CreateDIBitmap
也应该可以使用。
我不知道。我猜它根据我给它的标题在内存中为位图保留空间。我需要删除[]吗?还是在调用 DeleteObject [HBITMAP] 时这样做?
【参考方案1】:
感谢@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);
【讨论】:
以上是关于通过 TCP 发送的图像被翻转的主要内容,如果未能解决你的问题,请参考以下文章