Reputation: 87
Just to learn Windows API, I'm trying to use a cheap fingerprint device I bought. The library that came with it captures the fingerprint as an 8bit bitmap of 256x280 pixels and stores the raw pixels in a buffer.
I'm trying to copy this raw pixel stream into a Device Independent Bitmap (DIB) and then trying to use this DIB to draw onto a window.
I managed to display the image but the colors are all wrong. Heres the piece of code that handles the painting.
PAINTSTRUCT ps;
HDC hdc,memDC;
HBITMAP cp_bmp;
HBITMAP di_bmp;
BITMAPINFO di_bmp_info;
void *di_bmp_data;
int ptr;
int x,y;
int aux;
ZeroMemory(&di_bmp_info,sizeof(BITMAPINFO));
di_bmp_info.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
di_bmp_info.bmiHeader.biWidth=256;
di_bmp_info.bmiHeader.biHeight=280;
di_bmp_info.bmiHeader.biPlanes=1;
di_bmp_info.bmiHeader.biBitCount=8;
di_bmp_info.bmiHeader.biCompression=BI_RGB;
hdc=BeginPaint(hwnd,&ps);
// create the DIB
di_bmp=CreateDIBSection(hdc,&di_bmp_info,DIB_RGB_COLORS,&di_bmp_data,NULL,0);
// Copy the original bitstream onto the DIB
CopyMemory(di_bmp_data,fingerprint,256*280);
// create the mem dc
memDC=CreateCompatibleDC(hdc);
// create the DDB
cp_bmp=CreateCompatibleBitmap(hdc,256,280);
SelectObject(memDC,cp_bmp);
SetDIBits(memDC,cp_bmp,0,280,di_bmp_data,&di_bmp_info,DIB_RGB_COLORS);
BitBlt(hdc,10,10,256,280,memDC,0,0,SRCCOPY);
DeleteObject(cp_bmp);
EndPaint(hwnd,&ps);
Curious fact is that when I change the di_bmp_info.bmiHeader.biBitCount
to 32, the colors display perfectly but the image gets smaller in size and gets repeated around 5 or six times horizontally.
Im stuck!. Thanks in advance.
Upvotes: 0
Views: 262
Reputation: 37132
In short, you have an indexed bitmap (each pixel is not an RGB value but instead an index into a defined palette of colors) and you haven't provided a palette for it to use.
BITMAPINFO
is a variable sized structure - a BITMAPINFOHEADER
, followed by at least one but potentially more RGBQUAD
structures. For indexed bitmap depths (8 bpp and below), a palette needs to be provided following the BITMAPINFOHEADER
in memory.
The number of palette entries required is determined by the biBitCount
and biClrUsed
fields. If biClrUsed
is 0 the number of palette entries must be 1 << biBitCount
, or 256 in the case of 8bpp. Setting biClrUsed
to something other than 0 lets you provide fewer palette entries if the bitmap doesn't need them.
Because you haven't set biClrUsed
a full 256 color palette is assumed to follow the BITMAPINFOHEADER
in memory and essentially random memory is being used.
BITMAPINFO
provides only a single RGBQUAD
itself so you need to extend the structure to provide the rest, for example:
struct MyBitmapInfo
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD palette[256];
};
Where you actually get the palette from is up to you, but you could e.g. use a grayscale palette like this:
struct MyBitmapInfo di_bmp_info;
ZeroMemory(&di_bmp_info,sizeof(struct MyBitmapInfo));
di_bmp_info.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
di_bmp_info.bmiHeader.biWidth=256;
di_bmp_info.bmiHeader.biHeight=280;
di_bmp_info.bmiHeader.biPlanes=1;
di_bmp_info.bmiHeader.biBitCount=8;
di_bmp_info.bmiHeader.biCompression=BI_RGB;
// initialise greyscale palette
for (int i = 0; i < 256; i++)
{
di_bmp_info.palette[i].rgbRed =
di_bmp_info.palette[i].rgbGreen =
di_bmp_info.palette[i].rgnBlue = i;
}
Upvotes: 4