【问题标题】:GDI Monochrome Bitmap flips bits on each creation of HBITMAPGDI 单色位图在每次创建 HBITMAP 时翻转位
【发布时间】:2015-06-07 07:38:51
【问题描述】:

我一直在尝试从文件加载 16 位 (A1R5G5B5) BMP 并将其 alpha 通道用作位掩码。除了过去一周一直困扰我的一个问题外,我一切都正常工作。就是当我使用 CreateDIBitmap 来制作带有字节缓冲区的 1 位通道时,所创建的位图仅在第一次绘制时才使用其所有位的倒数。在下一次绘画中,位正确地翻转到提供的数据,并在之后的所有绘图中保持这种状态。这种行为非常奇怪,并且发生在所有 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 可能使用与第一个之后的所有调色板不同的调色板,这会导致这种行为?

【问题讨论】:

    标签: c winapi bitmap gdi alpha


    【解决方案1】:

    现在这一切都说得通了,只是调色板正在发生变化。

    “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
    );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-03
      • 2016-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-11
      • 2020-04-12
      相关资源
      最近更新 更多