Windows位图:BITMAPV5HEADER和BITMAPINFO兼容?

CreateDIBSection文档中,我发现CreateDIBSection将指针指向BITMAPINFO作为第二个参数。

但是,我遇到了各种各样的地方,表明它可能被允许传递指向其他结构(特别是BITMAPV5HEADER )的指针,包括

  • 这个答案是另一个问题
  • 铬的源代码

我有一个感觉,这是非常有意义的( BITMAPV5HEADER可以被看作是BITMAPINFO结构布局的扩展版本),但是我找不到关于这个主题的官方文档。

任何人都可以确认传递BITMAPV5HEADER*而不是BITMAPINFO实际上是有效的,并可能提供一些文档?

简短的答案是否定的BITMAPV5HEADER*不是BITMAPINFO*的替代品,无论何时只要BITMAPINFO*是预期的(因为BITMAPINFO包含调色板的颜色,而BITMAPV5HEADER只是一个标题)。


如果BITMAPV5HEADERBITMAPINFO的一部分,并且在它之后需要一些调色板颜色数据,那么传递BITMAPV5HEADER*而不是BITMAPINFO*当然是好的。 这是记录,虽然间接,通过使用指令和常识的一种:

  • BITMAPV5HEADER被记录为“ BITMAPINFOHEADER结构的扩展版本”,因此部分是清楚的。

  • BITMAPINFO被记录为结合标题和颜色数据。 头是包含值而不是由指针,所以在这一点上很明显,头可能不会只是随便大小,否则将无法访问BITMAPINFO.bmiColors和扩展版本的整个想法标题将是毫无意义的。

  • 然后在文档的另一个地方解决这个问题(“备注”部分):

    应用程序应该使用存储在biSize成员中的信息来定位BITMAPINFO结构中的颜色表,如下所示:

     pColor = ((LPSTR)pBitmapInfo + (WORD)(pBitmapInfo->bmiHeader.biSize)); 

虽然我相信这一部分并没有让你感到困惑。


现在是漫长的回答。

BITMAPV5HEADER*可以传递给BITMAPINFO*时, 似乎两种情况。 两者都没有以具体的方式记录下来,如果第一个我们可以应用上面应用的同样的常识,那么第二个似乎是文档中的一个错误:

  • BITMAPINFO.bmiColors记录为NULL 。 您可以在BITMAPINFOHEADER的文档中找到这些案例的完整列表。
  • 当标题是BITMAPV4HEADERBITMAPV5HEADER ,位图具有16位或32位颜色,压缩设置为BI_BITFIELDS 。 在这种情况下,记录在标题后面的颜色蒙版取而代之,取自标题的相应专用字段,忽略标题DWORD的三个DWORD

    这很容易通过稍微修改原始代码来证明:

     typedef struct tagV5BMPINFO { BITMAPV5HEADER bmiHeader; DWORD bmiColors[3]; } V5BMPINFO; int _tmain(int argc, _TCHAR* argv[]) { V5BMPINFO bmpinfo = { 0 }; BITMAPV5HEADER bmpheader = { 0 }; bmpheader.bV5Size = sizeof(BITMAPV5HEADER); bmpheader.bV5Width = width; bmpheader.bV5Height = height; bmpheader.bV5Planes = 1; bmpheader.bV5BitCount = 32; bmpheader.bV5Compression = BI_BITFIELDS; bmpheader.bV5SizeImage = 400*200*4; bmpheader.bV5RedMask = 0x00FF0000; bmpheader.bV5GreenMask = 0x0000FF00; bmpheader.bV5BlueMask = 0x000000FF; bmpheader.bV5AlphaMask = 0xFF000000; bmpheader.bV5CSType = 0x57696e20; // LCS_WINDOWS_COLOR_SPACE bmpheader.bV5Intent = LCS_GM_BUSINESS; bmpinfo.bmiHeader = bmpheader; // Put them in reverse order here compared to the above bmpinfo.bmiColors[0] = 0x000000FF; bmpinfo.bmiColors[1] = 0x0000FF00; bmpinfo.bmiColors[2] = 0x00FF0000; void* converted = NULL; HDC screen = GetDC(NULL); HBITMAP result = CreateDIBSection(screen, reinterpret_cast<BITMAPINFO*>(&bmpinfo), DIB_RGB_COLORS, &converted, NULL, 0); ReleaseDC(NULL, screen); DIBSECTION actual_data; GetObject(result, sizeof(actual_data), &actual_data); std::cout << std::hex; std::cout << actual_data.dsBitfields[0] << std::endl; std::cout << actual_data.dsBitfields[1] << std::endl; std::cout << actual_data.dsBitfields[2] << std::endl; std::cout << std::dec; DeleteObject(result); return 0; } 

    结果:

     FF0000
     FF00
     FF
    

    看起来文档是在BITMAPINFOHEADERBITMAPV4HEADERBITMAPV5HEADER之间BITMAPV4HEADER地复制的,应该在后两个版本中进行修改。 我能找到的最接近的解释是位图头类型至少可以识别专用掩码字段的存在,但仍然意味着必须在这些字段中提供值,并且在bmiColors的头后:

    BITMAPV4HEADER位图的红色,绿色和蓝色位域掩码紧跟BITMAPINFOHEADERBITMAPV4HEADERBITMAPV5HEADER结构之后。 BITMAPV4HEADERBITMAPV5HEADER结构包含红色,绿色和蓝色掩码的其他成员,如下所示。

    (强调我的)。

    我们只能从证据中得出结论,这是不正确的。
    它比我所希望的文档少。