CreateDIBSection function
The CreateDIBSection function creates a DIB that applications can write to directly. The function gives you a pointer to the location of the bitmap bit values. You can supply a handle to a file-mapping object that the function will use to create the bitmap, or you can let the system allocate the memory for the bitmap.
Syntax
HBITMAP CreateDIBSection( __in HDC hdc, __in const BITMAPINFO *pbmi, __in UINT iUsage, __out VOID **ppvBits, __in HANDLE hSection, __in DWORD dwOffset );
Parameters
- hdc [in]
-
A handle to a device context. If the value of iUsage is DIB_PAL_COLORS, the function uses this device context's logical palette to initialize the DIB colors.
- pbmi [in]
-
A pointer to a BITMAPINFO structure that specifies various attributes of the DIB, including the bitmap dimensions and colors.
- iUsage [in]
-
The type of data contained in the bmiColors array member of the BITMAPINFO structure pointed to by pbmi (either logical palette indexes or literal RGB values). The following values are defined.
Value Meaning - DIB_PAL_COLORS
The bmiColors member is an array of 16-bit indexes into the logical palette of the device context specified by hdc.
- DIB_RGB_COLORS
The BITMAPINFO structure contains an array of literal RGB values.
- ppvBits [out]
-
A pointer to a variable that receives a pointer to the location of the DIB bit values.
- hSection [in]
-
A handle to a file-mapping object that the function will use to create the DIB. This parameter can be NULL.
If hSection is not NULL, it must be a handle to a file-mapping object created by calling the CreateFileMapping function with the PAGE_READWRITE or PAGE_WRITECOPY flag. Read-only DIB sections are not supported. Handles created by other means will cause CreateDIBSection to fail.
If hSection is not NULL, the CreateDIBSection function locates the bitmap bit values at offset dwOffset in the file-mapping object referred to by hSection. An application can later retrieve the hSection handle by calling the GetObject function with the HBITMAP returned by CreateDIBSection.
If hSection is NULL, the system allocates memory for the DIB. In this case, the CreateDIBSection function ignores the dwOffset parameter. An application cannot later obtain a handle to this memory. The dshSection member of the DIBSECTION structure filled in by calling the GetObject function will be NULL.
- dwOffset [in]
-
The offset from the beginning of the file-mapping object referenced by hSection where storage for the bitmap bit values is to begin. This value is ignored if hSection is NULL. The bitmap bit values are aligned on doubleword boundaries, so dwOffset must be a multiple of the size of a DWORD.
Return value
If the function succeeds, the return value is a handle to the newly created DIB, and *ppvBits points to the bitmap bit values.
If the function fails, the return value is NULL, and *ppvBits is NULL.
This function can return the following value.
| Return code | Description |
|---|---|
|
One or more of the input parameters is invalid. |
Remarks
As noted above, if hSection is NULL, the system allocates memory for the DIB. The system closes the handle to that memory when you later delete the DIB by calling the DeleteObject function. If hSection is not NULL, you must close the hSection memory handle yourself after calling DeleteObject to delete the bitmap.
You cannot paste a DIB section from one application into another application.
CreateDIBSection does not use the BITMAPINFOHEADER parameters biXPelsPerMeter or biYPelsPerMeter and will not provide resolution information in the BITMAPINFO structure.
You need to guarantee that the GDI subsystem has completed any drawing to a bitmap created by CreateDIBSection before you draw to the bitmap yourself. Access to the bitmap must be synchronized. Do this by calling the GdiFlush function. This applies to any use of the pointer to the bitmap bit values, including passing the pointer in calls to functions such as SetDIBits.
ICM: No color management is done.
Requirements
|
Minimum supported client | Windows 2000 Professional |
|---|---|
|
Minimum supported server | Windows 2000 Server |
|
Header |
|
|
Library |
|
|
DLL |
|
See also
- Bitmaps Overview
- Bitmap Functions
- BITMAPINFO
- CreateFileMapping
- DeleteObject
- DIBSECTION
- GetDIBColorTable
- GetObject
- GdiFlush
- SetDIBits
- SetDIBColorTable
Send comments about this topic to Microsoft
Build date: 9/7/2011
Why would you use DIB sections? Because DIB section modification is freaking fast compared to a lot of different methods, especially SetPixel.
This will gear more towards 24-bpp (24-bit color) DIB sections and higher, since most people that start on DIB sections want this.
ppvBits contains the raw data to your image. It's up to you how to change that information.
See BITMAPINFOHEADER for more information about the formats
For 24-bit BI_RGB images, the array contains the information in the following format: Blue Green Red. So, a line will literally be BGRBGRBGRBGR. Each color pixel is 8 bits in 24-bit and 32-bit.
For 32-bit BI_RGB, I think it's ABGR. This is easy enough to test. The alpha channel isn't supported by a lot of applications, so you may get side-effects when trying to view your test data. In my case, the program tinted the entire image blue in GDI applications. Officially, the highest byte of the 32-bit data is ignored. Some people use the opportunity to store temporary data or the alpha channel.
There's also BI_BITFIELDS for 32-bit imagery. Basically you need to use a mask to extract the values. I haven't had the chance to play with this yet.
So why are the pixels backwards? It deals with the little-endian architecture that PCs tend to use. Look up little-endian if you want to learn more.
16-bit pixels are packed. There are two methods of using 16-bit pixels. BI_RGB uses a 5,5,5 encoding (5 bits red, 5 bits green, and 5 bits blue). In order to use 5,6,5 encoding (6 bits given to green), you have to use BI_BITFIELDS. The BI_BITFIELDS comes with three 32-bit masks,
0x0000F800
0x000007E0
0x0000001F
which adds to 16 bits. The 5-6-5 encoding is popular with video cards. You can use these to extract red, green, and blue. If you have a copy of the *Petzold book, see page 737 for more details. In fact, the parts I'm writing on 1-bit through 16-bit are using information taken from that book. Also, do others a favor by marking and checking both the bpp infomration and BI_BITFIELDS if you are doing 5-6-5.
8-bit: each 8-bit piece of data represents a palette entry
4-bit: divided into two 4-bit pieces of data. Each representing a pixel: aaaabbbb. Also uses a palette
1-bit: 8-bit piece of data divided 8 times. abcdefg, each letter representing a pixel. 0 is black, 1 is white
DIB sections are a product of OS/2. If the specified DIB section height is positive, the 0,0 coordinate is the bottom-left pixel, which is how it is in OS/2. If the DIB section is negative, the 0,0 coordinate is the top-left pixel, which is how it is in Windows. Most implementations follow the OS/2 implementation.
So, your image will be upside-down a lot of the times. Also, another quirk is that the row data of DIB sections. You basically have
Pixel-Pixel-Pixel-Pixel-Pixel-Pixel-pad
Pixel-Pixel-Pixel-Pixel-Pixel-Pixel-pad
Pixel-Pixel-Pixel-Pixel-Pixel-Pixel-pad
Every row is 4-byte aligned, and that padding is the trickiest part of DIB sections. This means that when you allocate a DIB section, it allocates the RAM for the rows based on 4-byte chunks. This is why a lot of people starting out using DIB sections will get rows that have the first few pixels cut off. Some people take the easy way out and just use 32-bit DIB sections (4 bytes anyways).
It's tricky, but it's not impossible to calculate the 4-byte alignment. You basically take the width of the image, multiply it by the amount of bits per pixel, and divide by 8. You then go to the next highest multiple of 4. Here's my implementation, which may not work below 8-bpp DIB sections:
// This part figures out how many bytes are left after the last pixel of the row's byte
RowMult = 4 - (((bitmapInfo.bmiHeader.biBitCount * bitmapInfo.bmiHeader.biWidth) / 8) % 4);
if ( RowMult == 4 )
RowMult = 0;
// now add the rest of the equation: how many bytes are there to a line
RowMult += (bitmapInfo.bmiHeader.biBitCount * bitmapInfo.bmiHeader.biWidth / 8);
License: The information here is put together from other sources, plus my messing around, so I'm giving it a public domain license. I got my info from sources like a lot of forums, the MSDN, and books like the *Petzold. You are free to use any of this information code however you want, whether it be a free product, commercial product, or in a book.
* When I say the Petzold, I mean Programming Windows, 5th Edition. If you are doing any Win32 C/C++ coding, that book is just awesome.
