2

从我观察到的文档中CreateDIBSectionCreateDIBSection,将指向 a 的指针BITMAPINFO作为第二个参数。

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

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

任何人都可以确认传递 aBITMAPV5HEADER*而不是 aBITMAPINFO实际上是有效的并且可能提供一些文件吗?

4

1 回答 1

3

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


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

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

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

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

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

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

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


现在是长答案。

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

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

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

    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
    

    看起来文档是在 之间不经意间复制的BITMAPINFOHEADERBITMAPV4HEADER并且BITMAPV5HEADER应该对最后两个进行修改。我能找到的最接近的解释是位图标题类型,它至少可以识别专用掩码字段的存在,但仍然暗示必须在这些字段中和以下标题之后提供值bmiColors

    位图的红色、绿色和蓝色位域掩码BI_BITFIELD紧跟BITMAPINFOHEADERBITMAPV4HEADER结构之后BITMAPV5HEADERBITMAPV4HEADERBITMAPV5HEADER结构包含红色、绿色和蓝色掩码的附加成员,如下所示。

    (强调我的)。

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

于 2017-09-21T09:42:31.780 回答