C GDI单色位图在每次创建HBITMAP时翻转位
我一直在尝试从文件中加载16位A1R5G5B5 BMP,并将其alpha通道用作位掩码。除了一个在过去一周一直困扰着我的问题外,我一切都很好。这是因为,当我使用CreateDIBitmap创建带有字节缓冲区的1bit通道时,创建的位图仅在第一次绘制时使用其所有位的倒数。在下一次绘制时,位正确地翻转到提供的数据,并在绘制之后的所有绘制中保持这种方式。这种行为非常奇怪,在所有Windows版本上都会发生,我一直追踪到它与HDC的某种设置以及可能的CreateDIBitmap有关。我尝试了很多方法,包括将HDC前后的前景色和背景色设置为许多值,但我尝试的所有方法都保持了这种行为 下面是一个要尝试的POC:C GDI单色位图在每次创建HBITMAP时翻转位,c,winapi,bitmap,gdi,alpha,C,Winapi,Bitmap,Gdi,Alpha,我一直在尝试从文件中加载16位A1R5G5B5 BMP,并将其alpha通道用作位掩码。除了一个在过去一周一直困扰着我的问题外,我一切都很好。这是因为,当我使用CreateDIBitmap创建带有字节缓冲区的1bit通道时,创建的位图仅在第一次绘制时使用其所有位的倒数。在下一次绘制时,位正确地翻转到提供的数据,并在绘制之后的所有绘制中保持这种方式。这种行为非常奇怪,在所有Windows版本上都会发生,我一直追踪到它与HDC的某种设置以及可能的CreateDIBitmap有关。我尝试了很多方法,包
BITMAPINFOHEADER bmih;
BITMAPINFO bmi;
HBITMAP mask;
PBYTE data;
PBYTE alpha;
SIZE dimension;
void WhenCreated() // WM_CREATE
{
dimension.cx=3;
dimension.cy=1;
alpha=(PBYTE)malloc(1);
data=(PBYTE)malloc(1);
alpha[0]=0xA0; // 0b10100000
}
#define BIN_SCAPE(B,A) (B[0]&(1<<A))?1:0
void WhenPresenting(HDC H) // WM_PAINT
{
printf(
"ALPHA:\t%i %i %i\n",
BIN_SCAPE(alpha,7),
BIN_SCAPE(alpha,6),
BIN_SCAPE(alpha,5)
);
HDC memory;
HBITMAP matter;
memory=CreateCompatibleDC(NULL);
memset(&bmi,0x0,sizeof(BITMAPINFO));
bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth=dimension.cx;
bmi.bmiHeader.biHeight=dimension.cy;
bmi.bmiHeader.biPlanes=1;
bmi.bmiHeader.biBitCount=1;
bmi.bmiHeader.biCompression=BI_RGB;
memset(&bmih,0x0,sizeof(BITMAPINFOHEADER));
bmih.biSize=sizeof(BITMAPINFOHEADER);
bmih.biWidth=bmi.bmiHeader.biWidth;
bmih.biHeight=bmi.bmiHeader.biHeight;
mask=CreateDIBitmap(
memory,
&bmih,
CBM_INIT,
alpha,
&bmi,
DIB_RGB_COLORS
);
SelectObject(memory,mask);
GetDIBits(memory,mask,0,1,data,&bmi,DIB_RGB_COLORS);
printf(
"DATA:\t%i %i %i\n",
BIN_SCAPE(data,7),
BIN_SCAPE(data,6),
BIN_SCAPE(data,5)
);
StretchBlt(
H,
0,0,128,128,
memory,
0,0,dimension.cx,dimension.cy,
SRCCOPY
);
DeleteDC(memory);
DeleteObject(mask);
}
当程序加载显示的数据与给定的数据相反时,后续绘制会导致数据与控制台输出中显示的数据相匹配,肯定会发生位翻转。我猜第一个提供的HDC可能会使用与第一个HDC之后的所有HDC不同的调色板,这导致了这种行为?现在一切都有意义了,是调色板在改变 BIBITCUNT成员小于16,BICLRUSE成员指定图形引擎或设备驱动程序访问的实际颜色数。来自msdn 如果您在CreateDIBitmap中使用颜色HDC,您将得到一个黑色的颜色,并且该颜色在每次重新绘制时都会发生变化,这会让您开始感到害怕,直到您理解这是因为您没有将调色板设置为HBITMAP,因为当每个HDC被设置时,除非指定,否则其调色板是未定义的。您可以使用SetDIBits,但如果您想在CreateDIBitmap期间完成此操作,请尝试以下操作:
PBITMAPINFO pbmi;
RGBQUAD palette[2];
{
// this will give you white (1) and black (0)
palette[0].rgbBlue=0x00;
palette[0].rgbGreen=0x00;
palette[0].rgbRed=0x00;
palette[1].rgbBlue=0xFF;
palette[1].rgbGreen=0xFF;
palette[1].rgbRed=0xFF;
// using a PBITMAPINFO in order to allocate room for palette
pbmi=(PBITMAPINFO)LocalAlloc(LPTR,sizeof(BITMAPINFO)+sizeof(RGBQUAD)*2); // this technically allocates an extra RGBQUAD
pbmi->bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth=dimension.cx;
pbmi->bmiHeader.biHeight=dimension.cy;
pbmi->bmiHeader.biPlanes=1;
pbmi->bmiHeader.biBitCount=1;
pbmi->bmiHeader.biCompression=BI_RGB;
pbmi->bmiHeader.biClrUsed=2; // palette is two colors long
pbmi->bmiHeader.biClrImportant=2;
memcpy(pbmi->bmiColors,palette,sizeof(RGBQUAD)*2);
mask=CreateDIBitmap(
memory,
&bmih,
CBM_INIT,
alpha,
pbmi,
DIB_RGB_COLORS
);
}