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

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

  • this answer to another question
  • Chromium source code

  • 我感觉这很合理(可以将BITMAPV5HEADER视为BITMAPINFO wrt结构布局的“扩展版本”),但是我找不到关于该主题的任何官方文档。

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

    最佳答案

    简短的答案必须为否。 BITMAPV5HEADER*不能替代BITMAPINFO*,并且每当需要BITMAPINFO*时都可能无法传递ojit(原因是BITMAPINFO在 header 之后包含调色板颜色,而BITMAPV5HEADER只是 header )。

    如果BITMAPV5HEADER*BITMAPINFO*的一部分并在其后需要某种调色板颜色数据,则传递BITMAPV5HEADER而不是BITMAPINFO当然很好。通过使用说明和常识可以间接地记录下来:

  • BITMAPV5HEADERdocumented,是“BITMAPINFOHEADER结构的扩展版本”,因此该部分很清楚。
  • BITMAPINFOdocumented,用于组合标题和颜色数据。 header 包含值,而不是指针,因此很明显 header 可能不只是随便增加大小,否则将无法访问BITMAPINFO.bmiColors和拥有 header 扩展版本的整个想法毫无意义。
  • 然后在another place in the documentation(“备注”部分)中解决了该问题:


  • 尽管我相信这部分不会让您开始感到困惑。

    现在长答案。

    可以将BITMAPV5HEADER*传递给BITMAPINFO*似乎有两种情况。两者均未以具体方式记录,并且如果对于第一个,我们可以应用与上面所应用的相同的常识,则第二个似乎是文档中的错误:
  • BITMAPINFO.bmiColors被记录为NULL时。您可以在documentation for BITMAPINFOHEADER 中找到此类案例的完整列表。
  • 当 header 是BITMAPV4HEADERBITMAPV5HEADER时,位图具有16或32位颜色,并且压缩设置为BI_BITFIELDS。在那种情况下,记录在标题之后的颜色掩码取而代之的是从标题的各个专用字段中获取,并且忽略标题之后的三个DWORD

    通过稍微修改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

    似乎应该在最后两个修订本时,将文档遗忘在BITMAPINFOHEADERBITMAPV4HEADERBITMAPV5HEADER之间。我能找到的最接近的解释是Bitmap Header Types,它至少可以识别专用掩码字段的存在,但仍然暗示必须在这些字段中以及bmiColors的 header 之后提供值:



    (强调我的)。

    我们只能从证据中得出结论,那就是事实并非如此。
    它比我希望的要少的文档。
  • 关于windows - Windows位图: BITMAPV5HEADER and BITMAPINFO compatible?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46338924/

    10-11 00:12