How Would I Load a Png Image Using Win32/Gdi (No Gdi+ If Possible)

How would I load a PNG image using Win32/GDI (no GDI+ if possible)?

You can use the Windows Imaging Component to load PNG files (on Windows XP SP2 and later). See MSDN Magazine for an introduction on how to use the API and my blog post for a code sample that loads a PNG from an IStream and converts it to an HBITMAP.

How would I draw a PNG image using LoadImage and StretchDIBits?

I think the PNG support inside bitmaps is only really for use by printer drivers. For screen display, you will probably have to decompress the PNG data yourself using some code such as libpng.

Is there any way to load a .png from my resources without using GDI+?

The "new" way to do it would be Direct2D and WIC, which is demonstrated in the Windows Imaging Component and Direct2D Image Viewer Win32 Sample.

But if the rest of your application is basic controls, Direct2D is overkill. The image has to be converted to a bitmap at some point to be displayed – whether in your GPU or in memory – and GDI+ fits this use case.

If these resources are icons or some other small-ish file (<2mp), I would reccomend embedding the resource as a bitmap. You can keep your asset pipeline as PNG, just add a pre-build step to convert your PNGs to pre-multiplied BGRA bitmaps and use LoadResource. There are pre-built tools to meet this need.

C++ GDI+ how to get and load image from resource?

TLDR: FindResource, LoadResource, and LockResource to get a pointer to the image bytes. Then make an IStream from it. The IStream can be used to initialize a Gdi+ Image or Bitmap object. (Gdiplus::Bitmap derives from Gdiplus::Image)

Stick a new line into your .rc file:

IDI_MY_IMAGE_FILE    PNG      "foo.png"

And make sure IDI_MY_IMAGE_FILE is defined as an integer in your resource.h header file.

#define IDI_MY_IMAGE_FILE               131

Then to load the image at runtime:

Gdiplus::Bitmap* pBmp = LoadImageFromResource(hInstance, MAKEINTRESOURCE(IDI_MY_IMAGE_FILE), L"PNG");

Where LoadImageFromResource is a helper function that does all the heavy work of loading a PNG from your application resources.

Gdiplus::Bitmap* LoadImageFromResource(HMODULE hMod, const wchar_t* resid, const wchar_t* restype)
{
IStream* pStream = nullptr;
Gdiplus::Bitmap* pBmp = nullptr;
HGLOBAL hGlobal = nullptr;

HRSRC hrsrc = FindResourceW(hInst, resid, restype); // get the handle to the resource
if (hrsrc)
{
DWORD dwResourceSize = SizeofResource(hMod, hrsrc);
if (dwResourceSize > 0)
{
HGLOBAL hGlobalResource = LoadResource(hMod, hrsrc); // load it
if (hGlobalResource)
{
void* imagebytes = LockResource(hGlobalResource); // get a pointer to the file bytes

// copy image bytes into a real hglobal memory handle
hGlobal = ::GlobalAlloc(GHND, dwResourceSize);
if (hGlobal)
{
void* pBuffer = ::GlobalLock(hGlobal);
if (pBuffer)
{
memcpy(pBuffer, imagebytes, dwResourceSize);
HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
if (SUCCEEDED(hr))
{
// pStream now owns the global handle and will invoke GlobalFree on release
hGlobal = nullptr;
pBmp = new Gdiplus::Bitmap(pStream);
}
}
}
}
}
}

if (pStream)
{
pStream->Release();
pStream = nullptr;
}

if (hGlobal)
{
GlobalFree(hGlobal);
hGlobal = nullptr;
}

return pBmp;
}

Save HBITMAP as PNG image using GDI?

Unfortunately, GDI does not support PNGs.

Button with PNG using GDI+

As Jonathan Potter pointed out in the comments, STM_SETIMAGE needs the HBITMAP to stick around. The clean-up semantics are somewhat convoluted, but you cannot generally call DeleteObject before WM_DESTROY.

Loading png-file from resources (without MFC, ATL)

Well, GDI+ can easily create an HBITMAP from PNG data in an IStream or file, but going from a resource to an IStream takes some work.

If you call CreateStreamOnHGlobal(NULL, TRUE, &stm), where stm is an IStream* variable, it will basically give you a temporary in-memory stream. You can use FindResource, LoadResource, LockResource, and SizeofResource to get a pointer to your resource data and its size. Once you have both of those things, you can use IStream::Write to copy the data from your resource into the IStream.

Once you have an IStream with your PNG data, pass the IStream to the GDI+ Bitmap constructor, and use the GetHBITMAP method to get an HBITMAP.

Save HBITMAP as PNG image using GDI?

Unfortunately, GDI does not support PNGs.



Related Topics



Leave a reply



Submit