【问题标题】:Get a HBITMAP from an 24bit BMP file loaded into memory从加载到内存中的 24 位 BMP 文件中获取 HBITMAP
【发布时间】:2013-02-14 03:22:39
【问题描述】:

我有一个 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 值的指针,但是它如何处理没有调色板的 24 位图像?

【问题讨论】:

    标签: winapi bitmap


    【解决方案1】:

    如果您从磁盘加载文件,使用带有LR_LOADFROMFILE 标志的LoadImage() 可能是最简单的。

    要从已加载到内存中的文件数据创建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;
    }
    

    【讨论】:

    • 嗨...感谢您的回答,但您一定错过了我问题中的一些要点。首先,Bitmap 已经加载到内存中,无法使用 LoadImage/LoadBitmap() 加载,因为它是一个嵌入二进制数据块中的 .bmp 文件。我从这个二进制数据块中提取 .bmp 文件,并需要从中创建一个 HBITMAP。其次,正如我所说,创建 HBITMAP 是在我的应用程序启动的早期完成的,所以 IS NO 窗口或 HDC,所以使用 GetDC() 和类似的东西不能用作此时没有应用程序窗口。
    • 我列出了两种方法。如果LoadImage() 在您的情况下不起作用,请使用第二种方法。即使您没有应用程序窗口,您仍然可以使用GetDC(NULL) 来获取屏幕的设备上下文(实际上是桌面窗口)。所以,这应该适合你的情况。
    【解决方案2】:

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

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

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

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

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

    你根本不需要GetObject。你已经有你的HBITMAP。它在hBitmap 变量中。

    cBitmap = hBitmap;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-03
      • 1970-01-01
      • 1970-01-01
      • 2013-06-13
      • 1970-01-01
      • 2022-01-01
      • 1970-01-01
      相关资源
      最近更新 更多