颜色显示不正确
Colors are not being correctly displayed
只是为了学习Windows API,我正在尝试使用我购买的廉价指纹设备。
它附带的库将指纹捕获为 256x280 像素的 8 位位图,并将原始像素存储在缓冲区中。
我正在尝试将此原始像素流复制到设备独立位图 (DIB) 中,然后尝试使用此 DIB 绘制到 window。
我设法显示了图像,但颜色都不对。这是处理绘画的一段代码。
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 次。
我卡住了!提前致谢。
简而言之,您有一个索引位图(每个像素不是 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;
}
只是为了学习Windows API,我正在尝试使用我购买的廉价指纹设备。 它附带的库将指纹捕获为 256x280 像素的 8 位位图,并将原始像素存储在缓冲区中。
我正在尝试将此原始像素流复制到设备独立位图 (DIB) 中,然后尝试使用此 DIB 绘制到 window。
我设法显示了图像,但颜色都不对。这是处理绘画的一段代码。
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 次。
我卡住了!提前致谢。
简而言之,您有一个索引位图(每个像素不是 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;
}