Home > Net >  Retrieving the palette of a bitmap image
Retrieving the palette of a bitmap image

Time:10-15

I am loading a bitmap image from a file (type BMP) via the GDI function LoadImage, which returns a BITMAP handle.

I know how to access the bitmap bits. But the image is in the format 8BPP, hence palettized. How can I obtain the palette entries ?

CodePudding user response:

Select the bitmap in to dc and call GetDIBColorTable. A temporary memory dc can be used here:

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

Alternatively use GetDIBits to read BITMAPINFO. You have to reserve enough memory to read the color table all bytes sizeof(BITMAPINFO).

Color table will be copied to BITMAPINFO -> bmiColors

Gdi is another option. Here is GDI example:

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;
}
  • Related