从加载到内存中的24位BMP文件中获取HBITMAP

时间:2013-02-28 03:39:28

标签: winapi bitmap

我有一个24位BMP文件加载到RAM中,我正在尝试为此图像文件创建一个HBITMAP。我找到了一些我一直在试验的例子,但似乎无法开展工作。基本上,我需要一个HBITMAP文件,以便我可以卸载文件并保留HBITMAP,我可以稍后用DeleteObject()处理它。由于在我的应用程序中很早就加载了这个位图,因此没有应用程序窗口,因此没有HDC。这是我到目前为止: -

HBITMAP cBitmap;  // This should be where my bitmap handle ends up.
mem;              // This is a void* pointer to the loaded BMP file


tagBITMAPFILEHEADER bfh = *(tagBITMAPFILEHEADER*)mem;
tagBITMAPINFOHEADER bih = *(tagBITMAPINFOHEADER*)(mem + sizeof(tagBITMAPFILEHEADER));
RGBQUAD rgb = *(RGBQUAD*)(mem + sizeof(tagBITMAPFILEHEADER) + sizeof(tagBITMAPINFOHEADER));

BITMAPINFO bi;
bi.bmiColors[0] = rgb;
bi.bmiHeader = bih;

UINT8* pixels = mem + bfh.bfOffBits;
void* ppv;
HBITMAP hBitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &ppv, NULL, 0);
SetDIBits(NULL, hBitmap, 0, bih.biHeight, pixels, &bi, DIB_RGB_COLORS);
GetObject(hBitmap, sizeof(BITMAP), &cBitmap);

由于某些原因让我感到困惑,cBitmap最终成为NULL。另一件令我困惑的事情...... DIB_RGB_COLORS意味着BITMAPINFO有一个指向文字RGB值的指针,但是如何处理24bit图像,它没有调色板?

2 个答案:

答案 0 :(得分:2)

如果您从磁盘加载文件,最简单的方法是LoadImage()使用LR_LOADFROMFILE标记。

要从已加载到内存中的文件数据创建HBITMAP,您可以执行类似以下操作:

HBITMAP ConvertDibToHBitmap(void* bmpData)
{
    HBITMAP hBitmap = NULL;
    BOOL success = FALSE;

    // NOTE: Assumes the BITMAPFILEHEADER is present (not normally the case for
    // an in-memory DIB)
    LPBITMAPFILEHEADER bfh = (LPBITMAPFILEHEADER) bmpData;
    LPBITMAPINFOHEADER bih = (LPBITMAPINFOHEADER) (bfh + 1);
    void *pixels = (char*) (bih + 1); // NOTE: Assumes no color table (i.e., bpp >= 24)

    HDC hdc = GetDC(NULL);
    if (hdc != NULL) {
        hBitmap = CreateCompatibleBitmap(hdc, bih->biWidth, bih->biHeight);
        if (hBitmap != NULL) {
            HDC hdcMem = CreateCompatibleDC(hdc);
            if (hdcMem != NULL) {
                HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap);
                if (StretchDIBits(hdcMem, 0, 0, bih->biWidth, bih->biHeight,
                        0, 0, bih->biWidth, bih->biHeight, pixels,
                        (LPBITMAPINFO) bih, DIB_RGB_COLORS, SRCCOPY) > 0)
                    success = TRUE;

                SelectObject(hdcMem, hOldBitmap);
                DeleteDC(hdcMem);
            }
        }

        ReleaseDC(NULL, hdc);
    }

    if (!success && hBitmap != NULL) {
        DeleteObject(hBitmap);
        hBitmap = NULL;
    }

    return hBitmap;
}

答案 1 :(得分:1)

嗯,这不是GetObject的工作方式。用法是

GetObject(handle, sizeof(object), &object);

在您的情况下,期望您将其称为

BITMAP bitmap;
GetObject(hBitmap, sizeof(BITMAP), &bitmap);

您没有将指针传递给BITMAP结构,因此行为未定义。

您根本不需要GetObject。您已拥有HBITMAP。它在hBitmap变量中。

cBitmap = hBitmap;