forked from strobejb/winspy
-
Notifications
You must be signed in to change notification settings - Fork 36
Open
Description
//
// LoadPNG.c
//
// www.catch22.net
//
// Copyright (C) 2012 James Brown
// Please refer to the file LICENCE.TXT for copying permission
//
#include "WinSpy.h"
#include <wincodec.h>
// #import "wincodec.idl" no_namespace
// Creates a stream object initialized with the data from an executable resource.
IStream *CreateStreamOnResource(WCHAR *lpName, WCHAR *lpType) {
// find the resource
HRSRC hRes;
DWORD dwResourceSize;
HGLOBAL hglbImage;
PVOID pvSourceResourceData;
HGLOBAL hgblResourceData;
PVOID pvResourceData;
IStream *ipStream;
hRes = FindResource(NULL, lpName, lpType);
// load the resource
hglbImage = LoadResource(NULL, hRes);
// allocate memory to hold the resource data
dwResourceSize = SizeofResource(NULL, hRes);
hgblResourceData = GlobalAlloc(GMEM_MOVEABLE, dwResourceSize);
// get a pointer to the allocated memory
pvResourceData = GlobalLock(hgblResourceData);
// copy the data from the resource to the new memory block
pvSourceResourceData = LockResource(hglbImage);
memcpy(pvResourceData, pvSourceResourceData, dwResourceSize);
GlobalUnlock(hgblResourceData);
// create a stream on the HGLOBAL containing the data
// Specify that the HGLOBAL will be automatically free'd on the last Release()
CreateStreamOnHGlobal(hgblResourceData, TRUE, &ipStream);
// couldn't create stream; free the memory
//GlobalFree(hgblResourceData);
// no need to unlock or free the resource
return ipStream;
}
// Now that we have an IStream pointer to the data of the image,
// we can use WIC to load that image. An important step in this
// process is to use WICConvertBitmapSource to ensure that the image
// is in a 32bpp format suitable for direct conversion into a DIB.
// This method assumes that the input image is in the PNG format;
// for a splash screen, this is an excellent choice because it allows
// an alpha channel as well as lossless compression of the source image.
// (To make the splash screen image as small as possible,
// I highly recommend the PNGOUT compression utility.)
// Loads a PNG image from the specified stream (using Windows Imaging Component).
IWICBitmapSource *LoadBitmapFromStream(IStream *ipImageStream) {
// initialize return value
IWICBitmapSource *ipBitmap;
// load WIC's PNG decoder
IWICBitmapDecoder *ipDecoder;
UINT nFrameCount;
IWICBitmapFrameDecode *ipFrame;
if (FAILED(CoCreateInstance(&CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER,
&IID_IWICBitmapDecoder, (VOID **) &ipDecoder)))
goto Return;
// load the PNG
if (FAILED(ipDecoder->lpVtbl->Initialize(ipDecoder, ipImageStream, WICDecodeMetadataCacheOnLoad)))
goto ReleaseDecoder;
// check for the presence of the first frame in the bitmap
if (FAILED(ipDecoder->lpVtbl->GetFrameCount(ipDecoder, &nFrameCount)) || nFrameCount != 1)
goto ReleaseDecoder;
// load the first frame (i.e., the image)
if (FAILED(ipDecoder->lpVtbl->GetFrame(ipDecoder, 0, &ipFrame)))
goto ReleaseDecoder;
// convert the image to 32bpp BGRA format with pre-multiplied alpha
// (it may not be stored in that format natively in the PNG resource,
// but we need this format to create the DIB to use on-screen)
WICConvertBitmapSource(&GUID_WICPixelFormat32bppPBGRA, (IWICBitmapSource *) ipFrame, &ipBitmap);
ipFrame->lpVtbl->Release(ipFrame);
ReleaseDecoder:
ipDecoder->lpVtbl->Release(ipDecoder);
Return:
return ipBitmap;
}
// Creates a 32-bit DIB from the specified WIC bitmap.
HBITMAP CreateHBITMAP(IWICBitmapSource *ipBitmap, PVOID *bits) {
// initialize return value
HBITMAP hbmp;
BITMAPINFO bminfo;
// get image attributes and check for valid image
UINT width, height;
UINT cbStride, cbImage;
VOID *pvImageBits;
HDC hdcScreen;
if (FAILED(ipBitmap->lpVtbl->GetSize(ipBitmap, &width, &height)) || width == 0 || height == 0)
goto Return;
// prepare structure giving bitmap information (negative height indicates a top-down DIB)
memset(&bminfo, 0, sizeof(bminfo));
bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bminfo.bmiHeader.biWidth = width;
bminfo.bmiHeader.biHeight = -((LONG) height);
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biBitCount = 32;
bminfo.bmiHeader.biCompression = BI_RGB;
// create a DIB section that can hold the image
hdcScreen = GetDC(NULL);
hbmp = CreateDIBSection(hdcScreen, &bminfo, DIB_RGB_COLORS, &pvImageBits, NULL, 0);
ReleaseDC(NULL, hdcScreen);
if (bits)
*bits = pvImageBits;
if (hbmp == NULL)
goto Return;
// extract the image into the HBITMAP
cbStride = width * 4;
cbImage = cbStride * height;
if (FAILED(ipBitmap->lpVtbl->CopyPixels(ipBitmap, NULL, cbStride, cbImage, (BYTE *) pvImageBits))) {
// couldn't extract image; delete HBITMAP
DeleteObject(hbmp);
hbmp = NULL;
}
Return:
return hbmp;
}
// Loads the PNG bitmap into a 32bit HBITMAP.
HBITMAP LoadPNGImage(UINT id, OUT VOID **bits) {
HBITMAP hbmpSplash;
// load the PNG image data into a stream
IStream *ipImageStream;
IWICBitmapSource *ipBitmap;
ipImageStream = CreateStreamOnResource(MAKEINTRESOURCE(id), L"PNG");
if (ipImageStream == NULL)
goto Return;
// load the bitmap with WIC
ipBitmap = LoadBitmapFromStream(ipImageStream);
if (ipBitmap == NULL)
goto ReleaseStream;
// create a HBITMAP containing the image
hbmpSplash = CreateHBITMAP(ipBitmap, bits);
ipBitmap->lpVtbl->Release(ipBitmap);
ReleaseStream:
ipImageStream->lpVtbl->Release(ipImageStream);
Return:
return hbmpSplash;
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels