1

I created an client which sends a screenshot over TCP to an server.The image is sent successfully. However at receival the image is upside down(I know this is set by the negative height in one of the structure's properties). I've searched over the internet on the means of doing it, but I couldn't find a proper way to achieve this.So if there's a better way of doing it , please do correct me.

This is how I send the screenshot (client) :

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
//.....

I am sure the message is being sent and received properly as I have implemented a protocol for separating the packets.This is not the problem .

This is the receiver (server) :

// 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);

The image is upside down .How can I fix it ?

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
Reznicencu Bogdan
  • 902
  • 2
  • 11
  • 28
  • 1
    You use a device-independent bitmap on the sending side (by way of `GetDIBits`) but a device-dependent one on the receiving side (by way of `CreateBitmapIndirect`). I suggest you use a DIB on the receiving side as well, e.g. via `CreateDIBSection` – Igor Tandetnik Aug 09 '17 at 14:28
  • I''l test it and reply if it works or not.Thanks – Reznicencu Bogdan Aug 09 '17 at 14:31
  • You mean CreateDIBitmap maybe ? because CreateDIBSection as I can see doesn't return an HBITMAP from an array . I believe, based on the HDC it gives out an array and a HBITMAP. That's not what i want on the server. – Reznicencu Bogdan Aug 09 '17 at 14:47
  • `CreateDIBSection` creates a new bitmap, and gives you direct access to its data storage. You can copy your bits into that storage, and they will be immediately reflected in the bitmap. But if you prefer, `CreateDIBitmap` should also work, I think. – Igor Tandetnik Aug 09 '17 at 14:50
  • I had no idea.I guess it reserves the space for the bitmap in memory based on the header i give to it.Do i need to delete[] it ? Or it does so when calling DeleteObject [HBITMAP]? – Reznicencu Bogdan Aug 09 '17 at 14:54
  • The memory is associated with the handle, and is freed when you delete the bitmap via `DeleteObject`. – Igor Tandetnik Aug 09 '17 at 15:01
  • `bmHeight` needs to be negative for a top-down bitmap, and you have made it positive. Presumably that's all it is. – Jonathan Potter Aug 09 '17 at 15:06
  • I did with CreateDIBSection .It works , yet i removed abs() and still shows the right way (with or without it's the same thing...).I checked the height in the client and server and it is always positive.When i set it negative in the server it didn't show anything.Is this negative thing real ? – Reznicencu Bogdan Aug 09 '17 at 15:13
  • why the downvote ? – Reznicencu Bogdan Aug 09 '17 at 18:07

1 Answers1

3

Thanks to @Igor Tandetnik I solved this problem .This is the final code:

On the client i send BITMAPINFO instead of BITMAPINFOHEADER:

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

Server side(I used CreateDIBSection instead of 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);
Reznicencu Bogdan
  • 902
  • 2
  • 11
  • 28