Reputation: 5620
I've searched around using google but I'm completely confused on how to load an image (PNG in my case) from resource and then converting it to a bitmap in memory for use in my splash screen. I've read about GDI+ and libpng but I don't really know how to do what I want. Could anyone help?
Upvotes: 0
Views: 2027
Reputation: 5620
I ended up using PicoPNG to convert the PNG to a two dimensional vector which I then manually contructed a bitmap from. My final code looked like this:
HBITMAP LoadPNGasBMP(const HMODULE hModule, const LPCTSTR lpPNGName)
{
/* First we need to get an pointer to the PNG */
HRSRC found = FindResource(hModule, lpPNGName, "PNG");
unsigned int size = SizeofResource(hModule, found);
HGLOBAL loaded = LoadResource(hModule, found);
void* resource_data = LockResource(loaded);
/* Now we decode the PNG */
vector<unsigned char> raw;
unsigned long width, height;
int err = decodePNG(raw, width, height, (const unsigned char*)resource_data, size);
if (err != 0)
{
log_debug("Error while decoding png splash: %d", err);
return NULL;
}
/* Create the bitmap */
BITMAPV5HEADER bmpheader = {0};
bmpheader.bV5Size = sizeof(BITMAPV5HEADER);
bmpheader.bV5Width = width;
bmpheader.bV5Height = height;
bmpheader.bV5Planes = 1;
bmpheader.bV5BitCount = 32;
bmpheader.bV5Compression = BI_BITFIELDS;
bmpheader.bV5SizeImage = width*height*4;
bmpheader.bV5RedMask = 0x00FF0000;
bmpheader.bV5GreenMask = 0x0000FF00;
bmpheader.bV5BlueMask = 0x000000FF;
bmpheader.bV5AlphaMask = 0xFF000000;
bmpheader.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
bmpheader.bV5Intent = LCS_GM_BUSINESS;
void* converted = NULL;
HDC screen = GetDC(NULL);
HBITMAP result = CreateDIBSection(screen, reinterpret_cast<BITMAPINFO*>(&bmpheader), DIB_RGB_COLORS, &converted, NULL, 0);
ReleaseDC(NULL, screen);
/* Copy the decoded image into the bitmap in the correct order */
for (unsigned int y1 = height - 1, y2 = 0; y2 < height; y1--, y2++)
for (unsigned int x = 0; x < width; x++)
{
*((char*)converted+0+4*x+4*width*y2) = raw[2+4*x+4*width*y1]; // Blue
*((char*)converted+1+4*x+4*width*y2) = raw[1+4*x+4*width*y1]; // Green
*((char*)converted+2+4*x+4*width*y2) = raw[0+4*x+4*width*y1]; // Red
*((char*)converted+3+4*x+4*width*y2) = raw[3+4*x+4*width*y1]; // Alpha
}
/* Done! */
return result;
}
Upvotes: 0
Reputation: 186118
GDI+ supports PNG directly. See here and here.
EDIT: The GDI+ documentation offers some advice for how to use GDI+ in a DLL. In your case, the best solution is probably to define initialisation and teardown functions that the client code is required to call.
Upvotes: 1