我一直在尝试从文件加载16位(A1R5G5B5)BMP并使用其alpha通道作为位掩码。除了过去一周困扰我的一个问题之外,我已经把一切都搞好了。当我使用CreateDIBitmap制作带有字节缓冲区的1bit通道时,创建的Bitmap仅在第一次绘制时使用其所有位的反转。在下一个画面上,这些位正确地翻转到所提供的数据,然后保持这种方式。这种行为非常奇怪,并且发生在所有Windows版本上,我已将其跟踪到与某些HDC设置和可能的CreateDIBitmap有关。我尝试了很多东西,包括将HDC前后的前景和背景颜色设置为很多值,但是我尝试的所有内容仍然保持这种行为。
这是一个尝试的POC:
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可能会使用不同的调色板而不是第一个导致此行为的调色板?
答案 0 :(得分:0)
现在一切都有意义,它正在改变。
“biBitCount成员小于16,biClrUsed成员指定图形引擎或设备驱动程序访问的实际颜色数。” (来自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
);
}