views:

526

answers:

5

I want to load a image (.bmp) file on a Win32 application, but I do not want to use the standard LoadBitmap/LoadImage from Windows API: I want it to load from a buffer that is already in memory. I can easily load a bitmap directly from file and print it on the screen, but this issue is making me stuck :(

What I'm looking for is a function that works like this:

HBITMAP LoadBitmapFromBuffer(char* buffer, int width, int height);

Thanks.

A: 

No, but you can create a new bitmap the size of the current one in memory, and write your memory structure onto it.

You're looking for the CreateBitmap function. Set lpvBits to your data.

Billy ONeal
+1  A: 

Try CreateBitmap():

HBITMAP LoadBitmapFromBuffer(char *buffer, int width, int height)
{
    return CreateBitmap(width, height, 1, 24, buffer);
}
Adam Rosenfield
+2  A: 

CreateDIBSection can be a little complicated to use, but one of the things it can do is create a device independent bitmap and give you a pointer to the buffer for the bitmap bits. Granted you already have a buffer full of bitmap bits, but at least you could copy the data.

Speculating a bit: CreateDIBSection can also create bitmaps from file objects, and there's probably a way to get windows to give you a file object representing a chunk of memory, which might trick CreateDIBSection into giving you a bitmap built from your buffer directly.

JustJeff
CreateDIBSection is the correct API to use. The memory it uses has to be a particular kind of kernel memory (as the graphics device driver needs to access it) - which can be satisfied by a file section (being a kernel structure itself) or by letting CreateDIBSection allocate the memory.
Chris Becke
A: 

oh, i didn't know CreateBitmap... but still, something's wrong... it seems to be creating the bitmap, but still i can't see it on the window. here's my code:

std::ifstream is;
is.open ("Image.bmp", std::ios::binary );
is.seekg (0, std::ios::end);
length = is.tellg();
is.seekg (0, std::ios::beg);
pBuffer = new char [length];
is.read (pBuffer,length);
is.close();

tagBITMAPFILEHEADER bfh = *(tagBITMAPFILEHEADER*)pBuffer;
tagBITMAPINFOHEADER bih = *(tagBITMAPINFOHEADER*)(pBuffer+sizeof(tagBITMAPFILEHEADER));
char* pPixels = (pBuffer+bfh.bfOffBits);
hBitmap = CreateBitmap(bih.biWidth, bih.biHeight, bih.biPlanes, bih.biBitCount, pPixels);
GetObject(hBitmap, sizeof(BITMAP), &cBitmap);

and on WM_PAINT:

hdc = BeginPaint(hWnd, &ps);
if(hBitmap != 0)
{
    HDC hdcMem = CreateCompatibleDC(hDC);   
    SelectObject(hdcMem, hBitmap);
    BitBlt(hDC, 10, 10, cBitmap.bmWidth, cBitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);
    DeleteDC(hdcMem);
}   
EndPaint(hWnd, &ps);

What can I be doing wrong?

Bruno
yes, forgot to mention this in the code above:HBITMAP hBitmap;BITMAP cBitmap;
Bruno
A: 

Nevermind, I found my solution! Here's the initializing code:

std::ifstream is;
is.open("Image.bmp", std::ios::binary);
is.seekg (0, std::ios::end);
length = is.tellg();
is.seekg (0, std::ios::beg);
pBuffer = new char [length];
is.read (pBuffer,length);
is.close();

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

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

char* pPixels = (pBuffer+bfh.bfOffBits);

char* ppvBits;

hBitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**) &ppvBits, NULL, 0);
SetDIBits(NULL, hBitmap, 0, bih.biHeight, pPixels, &bi, DIB_RGB_COLORS);

GetObject(hBitmap, sizeof(BITMAP), &cBitmap);
Bruno