为了学习Windows API,我正在尝试使用我买的便宜的指纹设备。 随附的库将指纹捕获为256x280像素的8位位图,并将原始像素存储在缓冲区中。
我正在尝试将此原始像素流复制到设备无关位图(DIB)中,然后尝试使用此DIB绘制到窗口上。
我设法显示图像,但颜色都错了。下面是处理这幅画的代码。
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);
奇怪的是,当我将di_bmp_info.bmiHeader.biBitCount
更改为32时,颜色显示完美,但图像尺寸变小,水平重复约5或6次。
答案 0 :(得分:4)
简而言之,你有一个索引位图(每个像素不是一个RGB值,而是一个定义的颜色调色板的索引),你还没有提供一个调色板供它使用。
BITMAPINFO
是一个可变大小的结构 - BITMAPINFOHEADER
,后跟至少一个但可能更多RGBQUAD
个结构。对于索引位图深度(8 bpp及以下),需要在内存中的BITMAPINFOHEADER
之后提供调色板。
所需的调色板条目数由biBitCount
和biClrUsed
字段决定。如果biClrUsed
为0,则调色板条目的数量必须为1 << biBitCount
,或者在8bpp的情况下为256。将biClrUsed
设置为0以外的值可以让您在位图不需要时提供更少的调色板条目。
因为你还没有设置biClrUsed
,所以假设一个完整的256色调色板跟在内存中的BITMAPINFOHEADER
,并且使用了基本上随机的内存。
BITMAPINFO
本身只提供一个RGBQUAD
,因此您需要扩展结构以提供其余内容,例如:
struct MyBitmapInfo
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD palette[256];
};
您实际获取调色板的位置取决于您,但您可以使用这样的灰度调色板:
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;
}