可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a 24bit BMP file loaded into RAM and I'm trying to create a HBITMAP for this image file. I have found some examples around which I've been experimenting with, but can't seem to make work. Basically, I need a HBITMAP for the file, so that I can unload the file and just keep the HBITMAP which I can dispose of later with DeleteObject(). Since this bitmap is loaded very early on in my application, there is no application Window and therefore no HDC. This is what I have so far:-
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);
For some reason that just baffles me, cBitmap ends up being NULL. And another thing that puzzles me... DIB_RGB_COLORS means that the BITMAPINFO has a pointer to literal RGB values, but how does that work with a 24bit image, which doesn't have a palette?
回答1:
Um, that's not how GetObject
works. The usage is
GetObject(handle, sizeof(object), &object);
In your case, the expectation is that you call it as
BITMAP bitmap; GetObject(hBitmap, sizeof(BITMAP), &bitmap);
You are not passing a pointer to a BITMAP
structure, so the behavior is undefined.
You don't need GetObject
at all. You already have your HBITMAP
. It's in the hBitmap
variable.
cBitmap = hBitmap;
回答2:
If you are loading a file from disk, it's probably easiest to use LoadImage()
with the LR_LOADFROMFILE
flag.
To create a HBITMAP
from file data that has already been loaded into memory, you can do something similar to the following:
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; }