【问题标题】:Retrieving the palette of a bitmap image检索位图图像的调色板
【发布时间】:2021-12-03 00:38:04
【问题描述】:

我正在通过 GDI 函数 LoadImage 从文件(BMP 类型)加载位图图像,该函数返回 BITMAP 句柄。

我知道如何访问位图位。但是图像的格式是 8BPP,因此是调色板的。如何获取调色板条目?

【问题讨论】:

    标签: windows gdi color-palette


    【解决方案1】:

    在 dc 中选择位图并调用 GetDIBColorTable。此处可以使用临时内存 dc:

    RGBQUAD rgb[256] = { 0 };
    HDC memdc = CreateCompatibleDC(hdc);
    auto oldbmp = SelectObject(memdc, hbitmap);
    GetDIBColorTable(memdc, 0, 256, rgb);
    SelectObject(memdc, oldbmp);
    DeleteDC(memdc);
    

    也可以使用GetDIBits 来读取BITMAPINFO。您必须保留足够的内存来读取颜色表 + 所有字节 + sizeof(BITMAPINFO)

    颜色表将被复制到BITMAPINFO -> bmiColors

    Gdi+ 是另一种选择。这是 GDI 示例:

    int main()
    {
        HBITMAP hbitmap = (HBITMAP)LoadImage(0, L"source.bmp", 
                IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
        if (!hbitmap)
            return 0;
    
        BITMAP bm;
        GetObject(hbitmap, sizeof(bm), &bm);
        int width = bm.bmWidth;
        int height = bm.bmHeight;
    
        WORD clrbits = (WORD)(bm.bmPlanes * bm.bmBitsPixel);
        if (clrbits == 8)       clrbits = 1;
        else if (clrbits <= 4)  clrbits = 4;
        else if (clrbits <= 8)  clrbits = 8;
        else if (clrbits <= 16) clrbits = 16;
        else if (clrbits <= 24) clrbits = 24;
        else clrbits = 32;
    
        HDC hdc = GetDC(0);
    
        if(clrbits == 8)
        {
            RGBQUAD rgb[256] = { 0 };
            HDC memdc = CreateCompatibleDC(hdc);
            auto oldbmp = SelectObject(memdc, hbitmap);
            GetDIBColorTable(memdc, 0, 256, rgb);
            SelectObject(memdc, oldbmp);
            DeleteDC(memdc);
        }
    
        int palette_size = (clrbits < 24) ? sizeof(RGBQUAD) * (1 << clrbits) : 0;
        BITMAPINFO* bmpinfo = (BITMAPINFO*)new BYTE[sizeof(BITMAPINFO) + palette_size];
        int width_in_bytes = ((width * clrbits + 31) & ~31) / 8;
        DWORD size = width_in_bytes * height;
        bmpinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmpinfo->bmiHeader.biWidth = width;
        bmpinfo->bmiHeader.biHeight = height;
        bmpinfo->bmiHeader.biPlanes = bm.bmPlanes;
        bmpinfo->bmiHeader.biBitCount = bm.bmBitsPixel;
        bmpinfo->bmiHeader.biClrUsed = (clrbits < 24) ? (1 << clrbits) : 0;
        bmpinfo->bmiHeader.biCompression = BI_RGB;
        bmpinfo->bmiHeader.biSizeImage = size;
    
        BYTE* bits = new BYTE[size];
        GetDIBits(hdc, hbitmap, 0, height, bits, bmpinfo, 0);
       
        //palette size should be 1024 for 256 color
        //it should be stored in `bmpinfo->bmiColors`
    
        delete[]bits;
        delete[](BYTE*)bmpinfo;
        DeleteObject(hbitmap);
        ReleaseDC(0, hdc);
    
        return 0;
    }
    

    【讨论】:

    • 这确实有效(第一种方法),谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 2014-12-29
    • 2011-04-20
    • 2012-07-02
    • 2022-01-04
    相关资源
    最近更新 更多