小太郎
小太郎

Reputation: 5620

Loading an image from resource and converting to bitmap in memory

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

Answers (2)

小太郎
小太郎

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

Marcelo Cantos
Marcelo Cantos

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

Related Questions