Index: src/Utils/MiscUI/Picture.cpp
===================================================================
--- src/Utils/MiscUI/Picture.cpp	(revision 7623)
+++ src/Utils/MiscUI/Picture.cpp	(working copy)
@@ -82,6 +82,29 @@
 		delete lpIcons;
 }
 
+// FreeImage DLL functions
+typedef const char* (__stdcall *FreeImage_GetVersion_t)(void);
+typedef void*		(__stdcall *FreeImage_ConvertTo32Bits_t)(void* dib);
+typedef int			(__stdcall *FreeImage_GetColorType_t)(void* dib);
+typedef unsigned	(__stdcall *FreeImage_GetWidth_t)(void* dib);
+typedef unsigned	(__stdcall *FreeImage_GetHeight_t)(void* dib);
+typedef void		(__stdcall *FreeImage_ConvertToRawBits_t)(BYTE *bits, void *dib, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown);
+typedef void		(__stdcall *FreeImage_Unload_t)(void* dib);
+
+#ifdef UNICODE
+
+typedef int			(__stdcall *FreeImage_GetFileType_t)(const wchar_t *filename, int size);
+typedef int			(__stdcall *FreeImage_GetFIFFromFilename_t)(const wchar_t *filename);
+typedef void*		(__stdcall *FreeImage_Load_t)(int format, const wchar_t *filename, int flags);
+
+#else	// !UNICODE
+
+typedef int			(__stdcall *FreeImage_GetFileType_t)(const char *filename, int size);
+typedef int			(__stdcall *FreeImage_GetFIFFromFilename_t)(const char *filename);
+typedef void*		(__stdcall *FreeImage_Load_t)(int format, const char *filename, int flags);
+
+#endif
+
 bool CPicture::Load(stdstring sFilePathName)
 {
 	bool bResult = false;
@@ -93,132 +116,221 @@
 	m_FileSize.clear();
 	FreePictureData(); // Important - Avoid Leaks...
 
-	HMODULE hLib = LoadLibrary(_T("gdiplus.dll"));
-	if (hLib)
 	{
-		// we have gdiplus, so try loading the picture with that one
-		if (GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, NULL )==Ok)
-		{   
+		HMODULE hFreeImageLib = LoadLibrary(_T("FreeImage.dll"));
+		FreeImage_GetVersion_t FreeImage_GetVersion = NULL;
+		FreeImage_GetFileType_t FreeImage_GetFileType = NULL;
+		FreeImage_GetFIFFromFilename_t FreeImage_GetFIFFromFilename = NULL;
+		FreeImage_Load_t FreeImage_Load = NULL;
+		FreeImage_Unload_t FreeImage_Unload = NULL;
+		FreeImage_GetColorType_t FreeImage_GetColorType = NULL;
+		FreeImage_GetWidth_t FreeImage_GetWidth = NULL;
+		FreeImage_GetHeight_t FreeImage_GetHeight = NULL;
+		FreeImage_ConvertToRawBits_t  FreeImage_ConvertToRawBits = NULL;
+
+		if (hFreeImageLib)
+		{
+			FreeImage_GetVersion = (FreeImage_GetVersion_t)GetProcAddress(hFreeImageLib, "_FreeImage_GetVersion@0");
+			FreeImage_GetWidth = (FreeImage_GetWidth_t)GetProcAddress(hFreeImageLib, "_FreeImage_GetWidth@4");
+			FreeImage_GetHeight = (FreeImage_GetHeight_t)GetProcAddress(hFreeImageLib, "_FreeImage_GetHeight@4");
+			FreeImage_Unload = (FreeImage_Unload_t)GetProcAddress(hFreeImageLib, "_FreeImage_Unload@4");
+			FreeImage_ConvertToRawBits = (FreeImage_ConvertToRawBits_t)GetProcAddress(hFreeImageLib, "_FreeImage_ConvertToRawBits@32");
+
+#ifdef UNICODE
+			FreeImage_GetFileType = (FreeImage_GetFileType_t)GetProcAddress(hFreeImageLib, "_FreeImage_GetFileTypeU@8");
+			FreeImage_GetFIFFromFilename = (FreeImage_GetFIFFromFilename_t)GetProcAddress(hFreeImageLib, "_FreeImage_GetFIFFromFilenameU@4");
+			FreeImage_Load = (FreeImage_Load_t)GetProcAddress(hFreeImageLib, "_FreeImage_LoadU@12");
+#else
+			FreeImage_GetFileType = (FreeImage_GetFileType_t)GetProcAddress(hFreeImageLib, "_FreeImage_GetFileType@8");
+			FreeImage_GetFIFFromFilename = (FreeImage_GetFIFFromFilename_t)GetProcAddress(hFreeImageLib, "_FreeImage_GetFIFFromFilename@4");
+			FreeImage_Load = (FreeImage_Load_t)GetProcAddress(hFreeImageLib, "_FreeImage_Load@12");
+#endif
+
+			const char* version = FreeImage_GetVersion();
+			// TODO: Check version
+
+			// Derive file type from file header.
+			int fileType = FreeImage_GetFileType(sFilePathName.c_str(), 0);
+			if (fileType < 0)
 			{
-				pBitmap = new Bitmap(sFilePathName.c_str(), FALSE);
-				GUID guid;
-				pBitmap->GetRawFormat(&guid);
+				// No file header available, attempt to parse file name for extension.
+				fileType = FreeImage_GetFIFFromFilename(sFilePathName.c_str());
+			}
 
-				// gdiplus only loads the first icon found in an icon file
-				// so we have to handle icon files ourselves :(
+			if (fileType >= 0)
+			{
+				void* dib = FreeImage_Load(fileType, sFilePathName.c_str(), 0);
 
-				// Even though gdiplus can load icons, it can't load the new
-				// icons from Vista - in Vista, the icon format changed slightly.
-				// But the LoadIcon/LoadImage API still can load those icons,
-				// at least those dimensions which are also used on pre-Vista
-				// systems.
-				// For that reason, we don't rely on gdiplus telling us if
-				// the image format is "icon" or not, we also check the
-				// file extension for ".ico".
-				std::transform(sFilePathName.begin(), sFilePathName.end(), sFilePathName.begin(), ::tolower);
-				bool bIco = _tcsstr(sFilePathName.c_str(), _T(".ico"))!=NULL;
-				if ((guid == ImageFormatIcon)||((pBitmap->GetLastStatus() != Ok)&&(bIco)))
+				if (dib)
 				{
-					delete (pBitmap);
-					pBitmap = NULL;
-					bIsIcon = true;
+					unsigned width = FreeImage_GetWidth(dib);
+					unsigned height = FreeImage_GetHeight(dib);
 
-					HANDLE hFile = CreateFile(sFilePathName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-					if (hFile != INVALID_HANDLE_VALUE)
+					pBitmap = new Bitmap(width, height, PixelFormat32bppARGB);
+
+					if (pBitmap->GetLastStatus() == Ok)
 					{
-						BY_HANDLE_FILE_INFORMATION fileinfo;
-						if (GetFileInformationByHandle(hFile, &fileinfo))
+						void* imageData = NULL;
+
+						Rect rect(0, 0, width, height);
+						BitmapData bitmapData;
+						if (pBitmap->LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData) == Ok)
 						{
-							lpIcons = new BYTE[fileinfo.nFileSizeLow];
-							DWORD readbytes;
-							if (ReadFile(hFile, lpIcons, fileinfo.nFileSizeLow, &readbytes, NULL))
+							FreeImage_ConvertToRawBits((BYTE*)bitmapData.Scan0, dib, bitmapData.Stride, 32, 0xff << RED_SHIFT, 0xff << GREEN_SHIFT, 0xff << BLUE_SHIFT, FALSE);
+
+							pBitmap->UnlockBits(&bitmapData);
+
+							m_Width = width;
+							m_Height = height;
+							bResult = true;
+						}
+						else
+						{
+							delete pBitmap;
+							pBitmap = NULL;
+						}
+					}
+
+					FreeImage_Unload(dib);
+					dib = NULL;
+				}
+			}
+
+			FreeLibrary(hFreeImageLib);
+			hFreeImageLib = NULL;
+		}
+	}
+
+	// Fall back on GDI...
+	if (!bResult)
+	{
+		HMODULE hLib = LoadLibrary(_T("gdiplus.dll"));
+		if (hLib)
+		{
+			// we have gdiplus, so try loading the picture with that one
+			if (GdiplusStartup( &gdiplusToken, &gdiplusStartupInput, NULL )==Ok)
+			{   
+				{
+					pBitmap = new Bitmap(sFilePathName.c_str(), FALSE);
+					GUID guid;
+					pBitmap->GetRawFormat(&guid);
+
+					// gdiplus only loads the first icon found in an icon file
+					// so we have to handle icon files ourselves :(
+
+					// Even though gdiplus can load icons, it can't load the new
+					// icons from Vista - in Vista, the icon format changed slightly.
+					// But the LoadIcon/LoadImage API still can load those icons,
+					// at least those dimensions which are also used on pre-Vista
+					// systems.
+					// For that reason, we don't rely on gdiplus telling us if
+					// the image format is "icon" or not, we also check the
+					// file extension for ".ico".
+					std::transform(sFilePathName.begin(), sFilePathName.end(), sFilePathName.begin(), ::tolower);
+					bool bIco = _tcsstr(sFilePathName.c_str(), _T(".ico"))!=NULL;
+					if ((guid == ImageFormatIcon)||((pBitmap->GetLastStatus() != Ok)&&(bIco)))
+					{
+						delete (pBitmap);
+						pBitmap = NULL;
+						bIsIcon = true;
+
+						HANDLE hFile = CreateFile(sFilePathName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+						if (hFile != INVALID_HANDLE_VALUE)
+						{
+							BY_HANDLE_FILE_INFORMATION fileinfo;
+							if (GetFileInformationByHandle(hFile, &fileinfo))
 							{
-								// we have the icon. Now gather the information we need later
-								CloseHandle(hFile);
-								nCurrentIcon = 0;
-								LPICONDIR lpIconDir = (LPICONDIR)lpIcons;
-								hIcons = new HICON[lpIconDir->idCount];
-								m_Width = lpIconDir->idEntries[0].bWidth;
-								m_Height = lpIconDir->idEntries[0].bHeight;
-								for (int i=0; i<lpIconDir->idCount; ++i)
+								lpIcons = new BYTE[fileinfo.nFileSizeLow];
+								DWORD readbytes;
+								if (ReadFile(hFile, lpIcons, fileinfo.nFileSizeLow, &readbytes, NULL))
 								{
-									hIcons[i] = (HICON)LoadImage(NULL, sFilePathName.c_str(), IMAGE_ICON, 
-																lpIconDir->idEntries[i].bWidth,
-																lpIconDir->idEntries[i].bHeight,
-																LR_LOADFROMFILE);
+									// we have the icon. Now gather the information we need later
+									CloseHandle(hFile);
+									nCurrentIcon = 0;
+									LPICONDIR lpIconDir = (LPICONDIR)lpIcons;
+									hIcons = new HICON[lpIconDir->idCount];
+									m_Width = lpIconDir->idEntries[0].bWidth;
+									m_Height = lpIconDir->idEntries[0].bHeight;
+									for (int i=0; i<lpIconDir->idCount; ++i)
+									{
+										hIcons[i] = (HICON)LoadImage(NULL, sFilePathName.c_str(), IMAGE_ICON, 
+																	lpIconDir->idEntries[i].bWidth,
+																	lpIconDir->idEntries[i].bHeight,
+																	LR_LOADFROMFILE);
+									}
+									bResult = true;
 								}
-								bResult = true;
+								else
+								{
+									delete lpIcons;
+									lpIcons = NULL;
+									CloseHandle(hFile);
+								}
 							}
 							else
-							{
-								delete lpIcons;
-								lpIcons = NULL;
 								CloseHandle(hFile);
-							}
 						}
-						else
-							CloseHandle(hFile);
 					}
+					else
+					{
+						m_Height = pBitmap->GetHeight();
+						m_Width = pBitmap->GetWidth();
+						bResult = true;
+					}
 				}
-				else
-				{
-					m_Height = pBitmap->GetHeight();
-					m_Width = pBitmap->GetWidth();
-					bResult = true;
-				}
+				bHaveGDIPlus = true;
 			}
-			bHaveGDIPlus = true;
+			else
+				pBitmap = NULL;
+			FreeLibrary(hLib);
 		}
 		else
+		{
 			pBitmap = NULL;
-		FreeLibrary(hLib);
-	}
-	else
-	{
-		pBitmap = NULL;
-		HANDLE hFile = CreateFile(sFilePathName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_HIDDEN, NULL);
-		if (hFile != INVALID_HANDLE_VALUE)
-		{
-			BY_HANDLE_FILE_INFORMATION fileinfo;
-			if (GetFileInformationByHandle(hFile, &fileinfo))
+			HANDLE hFile = CreateFile(sFilePathName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_HIDDEN, NULL);
+			if (hFile != INVALID_HANDLE_VALUE)
 			{
-				BYTE * buffer = new BYTE[fileinfo.nFileSizeLow];
-				DWORD readbytes;
-				if (ReadFile(hFile, buffer, fileinfo.nFileSizeLow, &readbytes, NULL))
+				BY_HANDLE_FILE_INFORMATION fileinfo;
+				if (GetFileInformationByHandle(hFile, &fileinfo))
 				{
-					if (LoadPictureData(buffer, readbytes))
+					BYTE * buffer = new BYTE[fileinfo.nFileSizeLow];
+					DWORD readbytes;
+					if (ReadFile(hFile, buffer, fileinfo.nFileSizeLow, &readbytes, NULL))
 					{
-						TCHAR buf[100];
-						_stprintf_s(buf, _T("%ld kBytes"), fileinfo.nFileSizeLow/1024);
-						m_FileSize = stdstring(buf);
-						m_nSize = fileinfo.nFileSizeLow;
-						bResult = true;
+						if (LoadPictureData(buffer, readbytes))
+						{
+							TCHAR buf[100];
+							_stprintf_s(buf, _T("%ld kBytes"), fileinfo.nFileSizeLow/1024);
+							m_FileSize = stdstring(buf);
+							m_nSize = fileinfo.nFileSizeLow;
+							bResult = true;
+						}
 					}
+					delete buffer;
 				}
-				delete buffer;
+				CloseHandle(hFile);
 			}
-			CloseHandle(hFile);
-		}
-		else
-			return bResult;
+			else
+				return bResult;
 
-		m_Name = sFilePathName;
-		m_Weight = nSize; // Update Picture Size Info...
+			m_Name = sFilePathName;
+			m_Weight = nSize; // Update Picture Size Info...
 
-		if(m_IPicture != NULL) // Do Not Try To Read From Memory That Does Not Exist...
-		{ 
-			m_IPicture->get_Height(&m_Height);
-			m_IPicture->get_Width(&m_Width);
-			// Calculate Its Size On a "Standard" (96 DPI) Device Context
-			m_Height = MulDiv(m_Height, 96, HIMETRIC_INCH);
-			m_Width  = MulDiv(m_Width,  96, HIMETRIC_INCH);
+			if(m_IPicture != NULL) // Do Not Try To Read From Memory That Does Not Exist...
+			{ 
+				m_IPicture->get_Height(&m_Height);
+				m_IPicture->get_Width(&m_Width);
+				// Calculate Its Size On a "Standard" (96 DPI) Device Context
+				m_Height = MulDiv(m_Height, 96, HIMETRIC_INCH);
+				m_Width  = MulDiv(m_Width,  96, HIMETRIC_INCH);
+			}
+			else // Picture Data Is Not a Known Picture Type
+			{
+				m_Height = 0;
+				m_Width = 0;
+				bResult = false;
+			}
 		}
-		else // Picture Data Is Not a Known Picture Type
-		{
-			m_Height = 0;
-			m_Width = 0;
-			bResult = false;
-		}
 	}
 
 	if ((bResult)&&(m_nSize == 0))
