
This tutorial shows how to use the Windows Imaging Component (WIC) to load an image file. After completing the tutorial, register any or all of the LEAD WIC-Enabled Codecs. You will then be able to load any of these image formats without recompiling the demo.
windowscodecs.lib
GdiPlus.lib
#define IFS(fn) \
{ \
if (SUCCEEDED(hr)) \
{ \
hr = (fn); \
} \
}
#define RELEASE_INTERFACE(pi) \
{ \
if (pi) \
{ \
pi->Release(); \
pi = NULL; \
} \
}
#define DELETE_POINTER(p) \
{ \
if (p) \
{ \
delete p; \
p = NULL; \
} \
}
#include <atlstr.h> // For easier string manipulation with CAtlString class
#include <commdlg.h> // For the File Open and File Save common dialogs
#include <wincodec.h> // Since we are using WIC-enabled codecs
#include <wincodecsdk.h>
#include <gdiplus.h> // For this tutorial, we use GDI+ to display the images.
using namespace Gdiplus;
Bitmap *gpGdiPlusBitmap = NULL;
ULONG_PTR gdiplusToken = 0;
IWICBitmapSource *gpiBitmapSource = NULL; // Used for saving an image file
void MyStartup()
{
// Initialize GDI+.
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
CoInitialize(NULL);
}
void MyShutdown()
{
CoUninitialize();
GdiplusShutdown(gdiplusToken);
}
HRESULT BitmapSourceToGdiPlusBitmap(IWICBitmapSource *piBitmapSource, Bitmap **ppGdiPlusBitmap, BYTE **ppbGdiPlusBuffer)
{
HRESULT hr = S_OK;
UINT uWidth = 0;
UINT uHeight = 0;
WICPixelFormatGUID pixelFormat = GUID_NULL;
IWICImagingFactory *piImagingFactory = NULL;
IWICFormatConverter *piFormatConverter = NULL;
Bitmap *pGdiPlusBitmap = NULL;
BYTE *pbBuffer = NULL;
if (!piBitmapSource || !ppGdiPlusBitmap)
return ERROR_INVALID_PARAMETER;
IFS(CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*) &piImagingFactory));
IFS(piImagingFactory->CreateFormatConverter(&piFormatConverter));
IFS(piFormatConverter->Initialize(piBitmapSource, GUID_WICPixelFormat24bppBGR, WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom));
IFS(piFormatConverter->GetSize(&uWidth, &uHeight));
IFS(piFormatConverter->GetPixelFormat(&pixelFormat));
if (SUCCEEDED(hr))
{
UINT cbStride = uWidth * 3;
// Force the stride to be a multiple of sizeof(DWORD)
cbStride = ((cbStride + sizeof(DWORD) - 1) / sizeof(DWORD)) * sizeof(DWORD);
UINT cbBufferSize = cbStride * uHeight;
pbBuffer = new BYTE[cbBufferSize];
if (pbBuffer != NULL)
{
WICRect rc = { 0, 0, uWidth, uHeight };
IFS(piFormatConverter->CopyPixels(&rc, cbStride, cbStride * uHeight, pbBuffer));
pGdiPlusBitmap = new Bitmap(uWidth, uHeight, cbStride, PixelFormat24bppRGB , pbBuffer);
}
else
{
hr = ERROR_NOT_ENOUGH_MEMORY;
}
}
*ppGdiPlusBitmap = pGdiPlusBitmap;
RELEASE_INTERFACE(piFormatConverter);
RELEASE_INTERFACE(piImagingFactory);
if (ppbGdiPlusBuffer)
*ppbGdiPlusBuffer = pbBuffer;
return hr;
}
// Returns TRUE if a global bitmap was freed
BOOL FreeGlobalBitmaps()
{
BOOL bRet = FALSE;
// Release any existing global bitmaps
if (gpGdiPlusBitmap)
{
delete gpGdiPlusBitmap;
gpGdiPlusBitmap= NULL;
bRet = TRUE;
}
return bRet;
}
void SetGlobalBitmaps(IWICBitmapSource *piBitmapSource)
{
Bitmap *pGdiPlusBitmap = NULL;
BYTE *pbGdiPlusBuffer = NULL;
if (!piBitmapSource)
return;
BitmapSourceToGdiPlusBitmap(piBitmapSource, &pGdiPlusBitmap, &pbGdiPlusBuffer);
if (pGdiPlusBitmap)
{
FreeGlobalBitmaps();
gpGdiPlusBitmap= pGdiPlusBitmap;
}
}
void OnPaint(HWND hWnd, LPPAINTSTRUCT pps)
{
if (gpGdiPlusBitmap)
{
RECT rcClient = {0};
GetClientRect(hWnd, &rcClient);
Graphics graphics(pps->hdc);
SizeF sizef = SizeF((REAL)gpGdiPlusBitmap->GetWidth(), (REAL)gpGdiPlusBitmap->GetHeight());
RectF rectf = RectF(PointF(0,0), sizef);
graphics.SetClip(rectf, CombineModeExclude);
Color c = Color(255,0,0,0);
c.SetFromCOLORREF(GetSysColor(COLOR_BTNFACE));
graphics.Clear(c);
graphics.ResetClip();
graphics.DrawImage(gpGdiPlusBitmap,rectf);
}
}
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
OnPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
switch (wmId)
{
case ID_FILE_OPEN:
{
CString csFile;
if (GetOpenFile(hWnd, csFile))
{
LoadFile(csFile);
UpdateMenu(hWnd);
InvalidateRect(hWnd, NULL, TRUE);
}
}
break;
BOOL GetOpenFile(HWND hwnd, CString &csFile)
{
BOOL bRet = TRUE;
OPENFILENAME ofn; // common dialog box structure
WCHAR szFile[260]; // buffer for file name
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"All\0*.*\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
bRet = GetOpenFileName(&ofn);
if (bRet)
csFile = ofn.lpstrFile;
return bRet;
}
HRESULT LoadFile( CString csFile)
{
IWICImagingFactory *piImagingFactory = NULL;
IWICBitmapDecoder *piDecoder = NULL;
IWICBitmapFrameDecode *piBitmapFrame = NULL;
UINT uiFrameCount = 0;
HRESULT hr = S_OK;
FreeGlobalBitmaps();
IFS(CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*) &piImagingFactory));
IFS(piImagingFactory->CreateDecoderFromFilename(csFile, NULL, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &piDecoder));
IFS(piDecoder->GetFrameCount(&uiFrameCount));
if (uiFrameCount > 0)
{
IFS(piDecoder->GetFrame(0, &piBitmapFrame));
if (SUCCEEDED(hr))
{
SetGlobalBitmaps(piBitmapFrame);
piBitmapFrame->Release();
piBitmapFrame = NULL;
}
}
RELEASE_INTERFACE(piDecoder);
RELEASE_INTERFACE(piImagingFactory);
return hr;
}
void UpdateMenu(HWND hwnd)
{
HMENU hMenu = GetMenu(hwnd);
EnableMenuItem(hMenu, ID_FILE_SAVE, (gpGdiPlusBitmap!= 0) ? MF_ENABLED : (MF_GRAYED |MF_DISABLED));
}
case WM_CREATE:
UpdateMenu(hWnd);
break;