3

I have some questions regarding GetDiBits, based on my experience with this function. By mistake I have created a bitmap double the size I needed:

HBITMAP hBmpSection = CreateCompatibleBitmap(ScreenDC, 2 * radius, 2 * radius);

I did not notice because the next part of the code worked. I BitBlt a section of the screen on half of this bitmap:

bmpSmallInfo.bmiHeader.biHeight = (2*radius / 2);
bmpSmallInfo.bmiHeader.biWidth = (2*radius / 2);
BitBlt(hSectionDC, 0, 0, bmpSmallInfo.bmiHeader.biWidth, bmpSmallInfo.bmiHeader.biHeight, ScreenDC, 0, 0, SRCCOPY);

Then I get the coresponding array:

GetDIBits(hSectionDC, hBmpSection, 0, bmpSmallInfo.bmiHeader.biHeight, dataBuffer3, &bmpSmallInfo, DIB_RGB_COLORS);

When I sent all this data to another computer , the image came perfectly right(no black edges around as it would have been in the case an oversized bitmap had been sent). This means that GetDiBits ignores the right size of the bitmap and uses the one provided in the BITMAPINFOHEADER,without crashing. (I'm using Win10.)

Is this normal? As I don't want to send unwanted bytes over network , I have to ask: does GetDiBits output an array the size of the right dimensions : (4*radius^2)*3 or does it look after the values from the structure : radius^2 *3 -ignoring padding-?

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
sergiu reznicencu
  • 1,039
  • 1
  • 11
  • 31
  • 1
    I don't understand why you think it should crash or even fail. The `BITMAPINFOHEADER` describes the output buffer properties, and Windows is quite aware of the properties of the device bitmap. You don't have to, and are not, 'reminding' windows how big your DDB is so it has no problem seeing you want just the top-left corner and providing that. There is also no expectation that the source/DDB bitmap has the same pixel format (or even its per pixel) as your destination DIB formatted buffer. – Chris Becke Apr 14 '18 at 17:15
  • 1
    @ChrisBecke That's no so obvious! You should probably change the comment to an answer. – Barmak Shemirani Apr 14 '18 at 17:27
  • So...the BITMAPINFOHEADER can specify a different dimension for the bitmap when performing drawing/reading operations,right? But,obvious ,if these dimenions are higher than the size of the bitmap , the drawing will be truncated,no? – sergiu reznicencu Apr 14 '18 at 17:51

2 Answers2

1

Basically you have a code like this:

hbitmap = CreateCompatibleBitmap(hdc, max_width, max_height);
oldbmp = (HBITMAP)SelectObject(memdc, hbitmap);
BitBlt(memdc, 0, 0, width, height, hdc, x, y, SRCCOPY);
SelectObject(memdc, oldbmp);
int size = width_in_bytes_with_padding * height;
allocate size count memory ...
BITMAPINFOHEADER bi = { 40, width, height, 1, 24, BI_RGB };
GetDIBits(...);

The question you appear to be asking: Is it okay if width/height is smaller than max_width/max_height?

The answer is yes. GetDIBits expects dataBuffer3 to be large enough to receive size bytes. width/height should be less than or equal to max_width/max_height

Note that BitBlt is the slowest function in this code, that's what you need to optimize. CreateCompatibleBitmap takes a few micro seconds, you won't save much by creating a larger bitmap.

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
1

GetDIBits is a rather strange function by GDI standards. Instead of the usual pattern of taking either just an HDC or an HBITMAP it wants both, AND imposes additional restrictions on the HBITMAP parameter. iirc This pattern is used when you are asking GDI to (potentially) transform a bitmap relative to a color table - i.e. in 8bit or lower images you should have a selected HPALETTE in the HDC.

The GetDIBits function page on MSDN however is quite clear - the LPBITMAPINFO parameter is:

A pointer to a BITMAPINFO structure that specifies the desired format for the DIB data.

Subsequent comments clarify that, if lpvBits is NULL, you can use GetDIBits to retrieve bitmap properties by writing them into the BITMAPINFO structure.

To answer your specific question; GetDIBits outputs to the dataBuffer using the dimensions and format you provide in the BITMAPINFOHEADER and will clip & transform as necessary if the DDB has different dimensions or pixel format.

Chris Becke
  • 34,244
  • 12
  • 79
  • 148