Reputation: 1004
The goal is to display bitmaps stored in memory buffers. The contents of the memory buffers are identical to disk-stored .bmp files. For performance reasons, writing these buffers to disk and then displaying them is not an option. GDI+ is also not an option. Currently, I can display 24 bit per pixel bitmaps from the memory buffers as desired. However, when I attempt to display 8 bit per pixel bitmaps, the images display with the wrong colors (i.e. figures in the image are recognizable; scaling, orientation, etc are correct, but everything is the wrong color).
Here is how I initialize the bitmap header structs:
bfh = *(tagBITMAPFILEHEADER*)buf1;
bih = *(tagBITMAPINFOHEADER*)(buf1+sizeof(tagBITMAPFILEHEADER));
rgb = *(RGBQUAD*)(buf1+sizeof(tagBITMAPFILEHEADER)+sizeof(tagBITMAPINFOHEADER));
bi.bmiColors[0] = rgb;
bi.bmiHeader = bih;
pPixels = (buf1+bfh.bfOffBits);
Then, I have tried several different ways of creating the HBITMAP, here are a few:
g_hBmp = CreateDIBitmap(dcPaint, &bih, CBM_INIT, (VOID *) pPixels, &bi, DIB_RGB_COLORS);
Or:
g_hBmp = CreateDIBSection(dcPaint, &bi, DIB_RGB_COLORS, (void**) &ppvBits, NULL, 0);
SetDIBits(dcPaint, g_hBmp, 0, bih.biHeight, pPixels, &bi, DIB_RGB_COLORS);
I have also tried different parameters:
I have dumped the contents of the memory buffers storing the .bmp file structures and verified that they are identical to disk-stored .bmp files that display correctly when loaded with LoadBitmap().
To emphasize, the above approach DOES WORK with 24bit per pixel images. But, it does NOT work with 8bit per pixel images.
Thanks in advance.
Upvotes: 2
Views: 2156
Reputation: 1004
Hans is correct to say that bi.bmiColors
was not being treated correctly. Instead of handling the bi.bmiColors
table directly, just point pBitmapInfo
to the appropriate offset in BITMAPFILEHEADER
and cast. This takes care of the color table automatically. And yes, pBitmapInfo
and pBitmapInfoHeader
do point to the same place; what they point to is casted differently in each case. Both of those pointers a required by the CreateDIBitmap()
function.
pBitmapFileHeader = (LPBITMAPFILEHEADER)buf1;
pBitmapInfoHeader = (LPBITMAPINFOHEADER)(buf1+sizeof(BITMAPFILEHEADER));
pBitmapInfo = (LPBITMAPINFO)(buf1+sizeof(BITMAPFILEHEADER));
pPixels = (buf1+pBitmapFileHeader->bfOffBits);
Then in OnPaint() do:
g_hBmp = CreateDIBitmap(dcPaint, pBitmapInfoHeader, CBM_INIT, (VOID *) pPixels, pBitmapInfo, DIB_RGB_COLORS);
Upvotes: 0
Reputation: 26279
The problem is that CreateDIBSection()
with DIB_RGB_COLORS
expects RGB values for each pixel (i.e. 24-bits) and your 8-bit bitmap contains pixels that are 8-bit indexes into an RGB palette, which is stored at bi-bmiColors
.
So, you have the option of converting your 8-bit bitmaps to 24-bit in a pre-processing step - for example by allocating memory for the RGB values and performing the look-up into the original palette to populate those values. That way you can use the same code for displaying the result. Alternatively, you can create an HBITMAP using the original data and select it into a memory DC then BitBlt()
it to the display window.
Other options, apart from GDI or GDI+ might be to consider WIC (Windows Imaging Component) and/or Direct2D.
Upvotes: 1