Windows位图:BITMAPV5HEADER和BITMAPINFO兼容吗?

时间:2017-09-21 08:24:56

标签: windows winapi bitmap gdi createdibsection

the documentation on CreateDIBSection我发现CreateDIBSection将指向BITMAPINFO的指针作为第二个参数。

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

我觉得这很有道理(BITMAPV5HEADER可以被视为BITMAPINFO wrt结构布局的扩展版本"但我找不到一个关于这个主题的官方文件。

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

1 个答案:

答案 0 :(得分:3)

简短的回答必须是BITMAPV5HEADER*不能替代BITMAPINFO*,并且可能无法在BITMAPINFO*出现时传递(仅仅因为BITMAPINFO在标题后面包含调色板颜色,而BITMAPV5HEADER是只是标题)。

如果BITMAPV5HEADER*BITMAPINFO*的一部分,并且在其后需要各种调色板颜色数据,那么传递BITMAPV5HEADER而不是BITMAPINFO肯定会很好。这是通过使用说明和常识间接记录的,但有点间接记录:

  • BITMAPV5HEADER documented是“BITMAPINFOHEADER结构的扩展版本”,因此该部分很明确。

  • BITMAPINFOdocumented,用于组合标题和颜色数据。标题是由值而不是指针包含的,所以此时很明显标题可能不会随着它的大小增加,否则将无法访问BITMAPINFO.bmiColors以及扩展的整个想法标题版本没有意义。

  • 然后在another place in the documentation(“备注”部分)中解决了该问题:

      

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

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

虽然我相信这部分并不会让你开始感到困惑。

现在回答很久。

当<{1}}可以传递BITMAPV5HEADER*时,出现 两个个案。两者都没有以具体方式记录,如果第一个我们可以应用我们上面应用的相同常识,第二个似乎是文档中的错误:

  • BITMAPINFO*被记录为BITMAPINFO.bmiColors时。您可以在documentation for BITMAPINFOHEADER
  • 中找到此类案例的完整列表
  • 当标头为NULLBITMAPV4HEADER时,位图具有16或32位颜色,压缩设置为BITMAPV5HEADER。在这种情况下,记录在标题后面的颜色掩码将取自标题的相应专用字段,并忽略标题后面的三个BI_BITFIELDS

    通过稍微修改original code

    ,可以很容易地证明这一点
    DWORD

    结果:

    ff0000
    ff00
    ff
    

    看来文档在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; } BITMAPINFOHEADERBITMAPV4HEADER之间被忽略后复制,应该在最后两个版本中进行修改。我能够找到的最接近的解释是Bitmap Header Types,它至少可以识别专用掩码字段的存在,但仍然暗示必须在这些字段中以及BITMAPV5HEADER中的标题之后提供值:< / p>

      

    bmiColors位图的红色,绿色和蓝色位域掩码会立即跟随 BI_BITFIELD BITMAPINFOHEADERBITMAPV4HEADER 结构。 BITMAPV5HEADERBITMAPV4HEADER结构包含红色,绿色和蓝色蒙版的其他成员,如下所示。

    (强调我的)。

    我们只能从证据中得出结论,认为事实并非如此 它比我希望的文档少。