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;