颜色未正确显示

时间:2015-08-28 20:59:12

标签: winapi gdi

为了学习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次。

我陷入了困境!提前谢谢。

1 个答案:

答案 0 :(得分:4)

简而言之,你有一个索引位图(每个像素不是一个RGB值,而是一个定义的颜色调色板的索引),你还没有提供一个调色板供它使用。

BITMAPINFO是一个可变大小的结构 - BITMAPINFOHEADER,后跟至少一个但可能更多RGBQUAD个结构。对于索引位图深度(8 bpp及以下),需要在内存中的BITMAPINFOHEADER之后提供调色板。

所需的调色板条目数由biBitCountbiClrUsed字段决定。如果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;
}