sergiu reznicencu
sergiu reznicencu

Reputation: 1039

GetDiBits: different dimensions passed in BITMAPINFOHEADER

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-?

Upvotes: 3

Views: 549

Answers (2)

Chris Becke
Chris Becke

Reputation: 36141

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.

Upvotes: 1

Barmak Shemirani
Barmak Shemirani

Reputation: 31669

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.

Upvotes: 1

Related Questions