草庐IT

Windows 位图 : BITMAPV5HEADER and BITMAPINFO compatible?

coder 2024-06-09 原文

来自 the documentation on CreateDIBSection我观察到 CreateDIBSection 将指向 BITMAPINFO 的指针作为第二个参数。

但是,我遇到了很多地方表明可能允许将指针传递给其他结构(特别是 BITMAPV5HEADER),包括

我觉得这很有道理(BITMAPV5HEADER 可以看作是 BITMAPINFO 结构布局的“扩展版本”),但我找不到一个关于此主题的单个官方文档。

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

最佳答案

简短的回答必须是BITMAPV5HEADER*不能替代 BITMAPINFO*并且可能不会在任何时候通过 BITMAPINFO*是预期的(仅仅是因为 BITMAPINFO 包含标题后的调色板颜色,而 BITMAPV5HEADER 只是一个标题)。


通过BITMAPV5HEADER*肯定没问题而不是 BITMAPINFO*只要BITMAPV5HEADERBITMAPINFO 的一部分并且在它之后需要一种调色板颜色数据。这是通过使用说明和常识记录的,虽然有点间接:

  • BITMAPV5HEADERdocumented成为“BITMAPINFOHEADER 结构的扩展版本”,所以这部分很清楚。

  • BITMAPINFOdocumented合并标题和颜色数据。 header 是按值包含的,而不是按指针包含的,因此很明显 header 的大小可能不会随心所欲地增长,否则将无法访问 BITMAPINFO.bmiColors。拥有扩展版本的 header 的整个想法将毫无意义。

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

    An application should use the information stored in the biSize member to locate the color table in a BITMAPINFO structure, as follows:

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

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


现在是长答案。

BITMAPV5HEADER* 时,似乎 两种 情况可以通过 BITMAPINFO* .两者都没有以具体的方式记录,如果对于第一个我们可以应用我们上面应用的相同常识,那么第二个似乎是文档中的错误:

  • 何时BITMAPINFO.bmiColors记录为 NULL .您可以在 documentation for BITMAPINFOHEADER 中找到此类案例的完整列表。 .
  • 当标题为BITMAPV4HEADER时或 BITMAPV5HEADER ,位图有 16 或 32 位颜色,压缩设置为 BI_BITFIELDS .在那种情况下,记录在标题后面的颜色掩码取而代之的是从标题的各个专用字段中获取,并且三个 DWORD标题后面的 s 将被忽略。

    这很容易通过稍微修改 original code 来证明。 :

    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
    

    看起来文档是在 BITMAPINFOHEADER 之间被漫不经心地复制的, BITMAPV4HEADERBITMAPV5HEADER当它应该被修改为最后两个。我能找到的最接近的解释是 Bitmap Header Types这至少承认专用掩码字段的存在,但仍然意味着必须在这些字段中和 bmiColors 中的 header 之后提供值:

    The red, green, and blue bitfield masks for BI_BITFIELD bitmaps immediately follow the BITMAPINFOHEADER, BITMAPV4HEADER, and BITMAPV5HEADER structures. The BITMAPV4HEADER and BITMAPV5HEADER structures contain additional members for red, green, and blue masks as follows.

    (强调我的)。

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

关于Windows 位图 : BITMAPV5HEADER and BITMAPINFO compatible?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46338924/

有关Windows 位图 : BITMAPV5HEADER and BITMAPINFO compatible?的更多相关文章

随机推荐