2

How much memory should be allocated for the DIB data received from HBITMAP using GetDIBits function?

The GetDIBits function is described in MSDN as follow:

int GetDIBits(
  __in     HDC hdc,
  __in     HBITMAP hbmp,
  __in     UINT uStartScan,
  __in     UINT cScanLines,
  __out    LPVOID lpvBits,
  __inout  LPBITMAPINFO lpbi,
  __in     UINT uUsage
);

However, the buffer to receive data lpvBits must be allocated before calling GetDIBits, because GetDIBits doesn't allocate this automatically.

The question is how much memory should be allocated to receive the DIB data? Supposed that the HBITMAP has width&height as Bmp_Width&Bmp_Height; and the bitmap is 32-bit (RGBA).

jondinham
  • 8,271
  • 17
  • 80
  • 137
  • there's a function called CreateDIBitmap but just can't figure out whether this function can be used to solve this question – jondinham Sep 05 '11 at 07:12

3 Answers3

1

I think the simplest way is calling GetObject() function (And BTW to get the image bits):

BITMAP bmpObject;
GetObject(hBitmap, sizeof(BITMAP), &bmpObject);

Then you simply use the Bitmap Fields:

LONG size = bmpObject.bmWidthBytes * bmpObject.bmHeight;

Be aware of alignment whem processing image bytes!

Hope this will be helpful!

beren
  • 166
  • 1
  • 8
  • you mean sizeof(BITMAP) surely? – David Heffernan Sep 05 '11 at 07:28
  • @beren: does the DIB data contain BMP header? if so, bmpObject.bmWidthBytes*bmpObject.bmHeight is still the correct size for DIB data? coz as i know this DIB data is actually the image of .bmp file in memory. – jondinham Sep 05 '11 at 07:49
  • the header and the bits are separate – David Heffernan Sep 05 '11 at 07:58
  • @Paul: If you mean the field bmBits of the BITMAP structure, then NO, the data does not contain the header. Also, you must note that the height might be a negative number (meaning a Bottom-up bitmap). Finally, the bitmap data format might not be one that you are expecting. You must check the field bmBitsPixel. – beren Sep 05 '11 at 08:00
  • @beren: tks for the notice about negative height value – jondinham Sep 05 '11 at 09:45
1

The memory pointed to by lpvBits must be the size of one scan line times the height. Each scan line must be aligned on a DWORD boundary.

Since you are using 32 bit colour then each scanline will naturally satisy that requirement, so long as you ensure that the first scanline, i.e. the start of the memory block, is 4 byte aligned.

So the answer, measured in bytes, is 4*width*height, aligned to start on a 4 byte boundary.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

biSizeImage Contains the size of the bitmap proper in bytes or the value 0. A value of 0 indicates that the DIB is of default size. Calculating the size of a bitmap is not difficult:

biSizeImage = ((((biWidth * biBitCount) + 31) & ~31) >> 3) * biHeight:

The crazy roundoffs and shifts account for the bitmap being DWORD-aligned at the end of every scanline. When nonzero, this field tells an application how much storage space the DIB's bits need. The biSizeImage field really becomes useful when dealing with an RLE bitmap, the size of which depends on how well the bitmap was encoded. If an RLE bitmap is to be passed around, the biSizeImage field is mandatory.

Every scanline is DWORD-aligned. The scanline is buffered to alignment; the buffering is not necessarily 0.

Gery, Ron. “DIBs and Their Use.” MSDN Technology Group, 20 Mar. 1992, https://learn.microsoft.com/previous-versions/ms969901(v=msdn.10).

DJm00n
  • 1,083
  • 5
  • 18