OSDN Git Service

Add TortoiseProc
[tortoisegit/TortoiseGitJp.git] / Utils / MiscUI / Picture.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 \r
19 #include "stdafx.h"\r
20 #include <olectl.h>\r
21 #include "shlwapi.h"\r
22 #include <locale>\r
23 #include <algorithm>\r
24 #include "Picture.h"\r
25 \r
26 #pragma comment(lib, "shlwapi.lib")\r
27 #pragma comment(lib, "gdiplus.lib")\r
28 \r
29 #define HIMETRIC_INCH 2540\r
30 \r
31 CPicture::CPicture()\r
32 {\r
33         m_IPicture = NULL;\r
34         m_Height = 0;\r
35         m_Weight = 0;\r
36         m_Width = 0;\r
37         pBitmap = NULL;\r
38         bHaveGDIPlus = false;\r
39         m_ip = InterpolationModeDefault;\r
40         hIcons = NULL;\r
41         lpIcons = NULL;\r
42         nCurrentIcon = 0;\r
43         bIsIcon = false;\r
44         m_nSize = 0;\r
45         m_ColorDepth = 0;\r
46 }\r
47 \r
48 CPicture::~CPicture()\r
49 {\r
50         FreePictureData(); // Important - Avoid Leaks...\r
51         if (pBitmap)\r
52                 delete (pBitmap);\r
53         if (bHaveGDIPlus)\r
54                 GdiplusShutdown(gdiplusToken);\r
55 }\r
56 \r
57 \r
58 void CPicture::FreePictureData()\r
59 {\r
60         if (m_IPicture != NULL)\r
61         {\r
62                 m_IPicture->Release();\r
63                 m_IPicture = NULL;\r
64                 m_Height = 0;\r
65                 m_Weight = 0;\r
66                 m_Width = 0;\r
67                 m_nSize = 0;\r
68         }\r
69         if (hIcons)\r
70         {\r
71                 LPICONDIR lpIconDir = (LPICONDIR)lpIcons;\r
72                 if (lpIconDir)\r
73                 {\r
74                         for (int i=0; i<lpIconDir->idCount; ++i)\r
75                         {\r
76                                 DestroyIcon(hIcons[i]);\r
77                         }\r
78                 }\r
79                 delete [] hIcons;\r
80                 hIcons = NULL;\r
81         }\r
82         if (lpIcons)\r
83                 delete [] lpIcons;\r
84 }\r
85 \r
86 // Util function to ease loading of FreeImage library\r
87 static FARPROC s_GetProcAddressEx(HMODULE hDll, const char* procName, bool& valid)\r
88 {\r
89         FARPROC proc = NULL;\r
90 \r
91         if (valid)\r
92         {\r
93                 proc = GetProcAddress(hDll, procName);\r
94 \r
95                 if (!proc)\r
96                         valid = false;\r
97         }\r
98 \r
99         return proc;\r
100 }\r
101 \r
102 stdstring CPicture::GetFileSizeAsText(bool bAbbrev /* = true */)\r
103 {\r
104         TCHAR buf[100] = {0};\r
105         if (bAbbrev)\r
106                 StrFormatByteSize(m_nSize, buf, 100);\r
107         else\r
108                 _stprintf_s(buf, _T("%ld Bytes"), m_nSize);\r
109 \r
110         return stdstring(buf);\r
111 }\r
112 \r
113 bool CPicture::Load(stdstring sFilePathName)\r
114 {\r
115         bool bResult = false;\r
116         bIsIcon = false;\r
117         lpIcons = NULL;\r
118         //CFile PictureFile;\r
119         //CFileException e;\r
120         int     nSize = 0;\r
121         FreePictureData(); // Important - Avoid Leaks...\r
122 \r
123         // No-op if no file specified\r
124         if (sFilePathName.empty())\r
125                 return true;\r
126 \r
127         // Load & initialize the GDI+ library if available\r
128         HMODULE hGdiPlusLib = LoadLibrary(_T("gdiplus.dll"));\r
129         if (hGdiPlusLib && GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) == Ok)\r
130         {\r
131                 bHaveGDIPlus = true;\r
132         }\r
133         // Since we loaded the gdiplus.dll only to check if it's available, we\r
134         // can safely free the library here again - GdiplusStartup() loaded it too\r
135         // and reference counting will make sure that it stays loaded until GdiplusShutdown()\r
136         // is called.\r
137         FreeLibrary(hGdiPlusLib);\r
138 \r
139         // Attempt to load using GDI+ if available\r
140         if (bHaveGDIPlus)\r
141         {\r
142                 pBitmap = new Bitmap(sFilePathName.c_str(), FALSE);\r
143                 GUID guid;\r
144                 pBitmap->GetRawFormat(&guid);\r
145 \r
146                 if (pBitmap->GetLastStatus() != Ok)\r
147                 {\r
148                         delete pBitmap;\r
149                         pBitmap = NULL;\r
150                 }\r
151 \r
152                 // gdiplus only loads the first icon found in an icon file\r
153                 // so we have to handle icon files ourselves :(\r
154 \r
155                 // Even though gdiplus can load icons, it can't load the new\r
156                 // icons from Vista - in Vista, the icon format changed slightly.\r
157                 // But the LoadIcon/LoadImage API still can load those icons,\r
158                 // at least those dimensions which are also used on pre-Vista\r
159                 // systems.\r
160                 // For that reason, we don't rely on gdiplus telling us if\r
161                 // the image format is "icon" or not, we also check the\r
162                 // file extension for ".ico".\r
163                 std::transform(sFilePathName.begin(), sFilePathName.end(), sFilePathName.begin(), ::tolower);\r
164                 bIsIcon = (guid == ImageFormatIcon) || (_tcsstr(sFilePathName.c_str(), _T(".ico")) != NULL);\r
165 \r
166                 if (bIsIcon)\r
167                 {\r
168                         // Icon file, get special treatment...\r
169                         if (pBitmap)\r
170                         {\r
171                                 // Cleanup first...\r
172                                 delete (pBitmap);\r
173                                 pBitmap = NULL;\r
174                                 bIsIcon = true;\r
175                         }\r
176 \r
177                         HANDLE hFile = CreateFile(sFilePathName.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\r
178                         if (hFile != INVALID_HANDLE_VALUE)\r
179                         {\r
180                                 BY_HANDLE_FILE_INFORMATION fileinfo;\r
181                                 if (GetFileInformationByHandle(hFile, &fileinfo))\r
182                                 {\r
183                                         lpIcons = new BYTE[fileinfo.nFileSizeLow];\r
184                                         DWORD readbytes;\r
185                                         if (ReadFile(hFile, lpIcons, fileinfo.nFileSizeLow, &readbytes, NULL))\r
186                                         {\r
187                                                 // we have the icon. Now gather the information we need later\r
188                                                 CloseHandle(hFile);\r
189                                                 if (readbytes >= sizeof(ICONDIR))\r
190                                                 {\r
191                                                         nCurrentIcon = 0;\r
192                                                         LPICONDIR lpIconDir = (LPICONDIR)lpIcons;\r
193                                                         hIcons = new HICON[lpIconDir->idCount];\r
194                                                         m_Width = lpIconDir->idEntries[0].bWidth;\r
195                                                         m_Height = lpIconDir->idEntries[0].bHeight;\r
196                                                         for (int i=0; i<lpIconDir->idCount; ++i)\r
197                                                         {\r
198                                                                 hIcons[i] = (HICON)LoadImage(NULL, sFilePathName.c_str(), IMAGE_ICON, \r
199                                                                         lpIconDir->idEntries[i].bWidth,\r
200                                                                         lpIconDir->idEntries[i].bHeight,\r
201                                                                         LR_LOADFROMFILE);\r
202                                                         }\r
203                                                         bResult = true;\r
204                                                 }\r
205                                                 else\r
206                                                 {\r
207                                                         delete [] lpIcons;\r
208                                                         lpIcons = NULL;\r
209                                                         bResult = false;\r
210                                                 }\r
211                                         }\r
212                                         else\r
213                                         {\r
214                                                 delete [] lpIcons;\r
215                                                 lpIcons = NULL;\r
216                                                 CloseHandle(hFile);\r
217                                         }\r
218                                 }\r
219                                 else\r
220                                         CloseHandle(hFile);\r
221                         }\r
222                 }\r
223                 else if (pBitmap)       // Image loaded successfully with GDI+\r
224                 {\r
225                         m_Height = pBitmap->GetHeight();\r
226                         m_Width = pBitmap->GetWidth();\r
227                         bResult = true;\r
228                 }\r
229 \r
230                 // If still failed to load the file...\r
231                 if (!bResult)\r
232                 {\r
233                         // Attempt to load the FreeImage library as an optional DLL to support additional formats\r
234 \r
235                         // NOTE: Currently just loading via FreeImage & using GDI+ for drawing.\r
236                         // It might be nice to remove this dependency in the future.\r
237                         HMODULE hFreeImageLib = LoadLibrary(_T("FreeImage.dll"));\r
238 \r
239                         // FreeImage DLL functions\r
240                         typedef const char* (__stdcall *FreeImage_GetVersion_t)(void);\r
241                         typedef int                     (__stdcall *FreeImage_GetFileType_t)(const TCHAR *filename, int size);\r
242                         typedef int                     (__stdcall *FreeImage_GetFIFFromFilename_t)(const TCHAR *filename);\r
243                         typedef void*           (__stdcall *FreeImage_Load_t)(int format, const TCHAR *filename, int flags);\r
244                         typedef void            (__stdcall *FreeImage_Unload_t)(void* dib);\r
245                         typedef int                     (__stdcall *FreeImage_GetColorType_t)(void* dib);\r
246                         typedef unsigned        (__stdcall *FreeImage_GetWidth_t)(void* dib);\r
247                         typedef unsigned        (__stdcall *FreeImage_GetHeight_t)(void* dib);\r
248                         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);\r
249 \r
250                         FreeImage_GetVersion_t FreeImage_GetVersion = NULL;\r
251                         FreeImage_GetFileType_t FreeImage_GetFileType = NULL;\r
252                         FreeImage_GetFIFFromFilename_t FreeImage_GetFIFFromFilename = NULL;\r
253                         FreeImage_Load_t FreeImage_Load = NULL;\r
254                         FreeImage_Unload_t FreeImage_Unload = NULL;\r
255                         FreeImage_GetColorType_t FreeImage_GetColorType = NULL;\r
256                         FreeImage_GetWidth_t FreeImage_GetWidth = NULL;\r
257                         FreeImage_GetHeight_t FreeImage_GetHeight = NULL;\r
258                         FreeImage_ConvertToRawBits_t  FreeImage_ConvertToRawBits = NULL;\r
259 \r
260                         if (hFreeImageLib)\r
261                         {\r
262                                 bool exportsValid = true;\r
263 \r
264                                 //FreeImage_GetVersion = (FreeImage_GetVersion_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetVersion@0", valid);\r
265                                 FreeImage_GetWidth = (FreeImage_GetWidth_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetWidth@4", exportsValid);\r
266                                 FreeImage_GetHeight = (FreeImage_GetHeight_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetHeight@4", exportsValid);\r
267                                 FreeImage_Unload = (FreeImage_Unload_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_Unload@4", exportsValid);\r
268                                 FreeImage_ConvertToRawBits = (FreeImage_ConvertToRawBits_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_ConvertToRawBits@32", exportsValid);\r
269 \r
270 #ifdef UNICODE\r
271                                 FreeImage_GetFileType = (FreeImage_GetFileType_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFileTypeU@8", exportsValid);\r
272                                 FreeImage_GetFIFFromFilename = (FreeImage_GetFIFFromFilename_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFIFFromFilenameU@4", exportsValid);\r
273                                 FreeImage_Load = (FreeImage_Load_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_LoadU@12", exportsValid);\r
274 #else\r
275                                 FreeImage_GetFileType = (FreeImage_GetFileType_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFileType@8", exportsValid);\r
276                                 FreeImage_GetFIFFromFilename = (FreeImage_GetFIFFromFilename_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_GetFIFFromFilename@4", exportsValid);\r
277                                 FreeImage_Load = (FreeImage_Load_t)s_GetProcAddressEx(hFreeImageLib, "_FreeImage_Load@12", exportsValid);\r
278 #endif\r
279 \r
280                                 //const char* version = FreeImage_GetVersion();\r
281 \r
282                                 // Check the DLL is using compatible exports\r
283                                 if (exportsValid)\r
284                                 {\r
285                                         // Derive file type from file header.\r
286                                         int fileType = FreeImage_GetFileType(sFilePathName.c_str(), 0);\r
287                                         if (fileType < 0)\r
288                                         {\r
289                                                 // No file header available, attempt to parse file name for extension.\r
290                                                 fileType = FreeImage_GetFIFFromFilename(sFilePathName.c_str());\r
291                                         }\r
292 \r
293                                         // If we have a valid file type\r
294                                         if (fileType >= 0)\r
295                                         {\r
296                                                 void* dib = FreeImage_Load(fileType, sFilePathName.c_str(), 0);\r
297 \r
298                                                 if (dib)\r
299                                                 {\r
300                                                         unsigned width = FreeImage_GetWidth(dib);\r
301                                                         unsigned height = FreeImage_GetHeight(dib);\r
302 \r
303                                                         // Create a GDI+ bitmap to load into...\r
304                                                         pBitmap = new Bitmap(width, height, PixelFormat32bppARGB);\r
305 \r
306                                                         if (pBitmap && pBitmap->GetLastStatus() == Ok)\r
307                                                         {\r
308                                                                 void* imageData = NULL;\r
309 \r
310                                                                 // Write & convert the loaded data into the GDI+ Bitmap\r
311                                                                 Rect rect(0, 0, width, height);\r
312                                                                 BitmapData bitmapData;\r
313                                                                 if (pBitmap->LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData) == Ok)\r
314                                                                 {\r
315                                                                         FreeImage_ConvertToRawBits((BYTE*)bitmapData.Scan0, dib, bitmapData.Stride, 32, 0xff << RED_SHIFT, 0xff << GREEN_SHIFT, 0xff << BLUE_SHIFT, FALSE);\r
316 \r
317                                                                         pBitmap->UnlockBits(&bitmapData);\r
318 \r
319                                                                         m_Width = width;\r
320                                                                         m_Height = height;\r
321                                                                         bResult = true;\r
322                                                                 }\r
323                                                                 else    // Failed to lock the destination Bitmap\r
324                                                                 {\r
325                                                                         delete pBitmap;\r
326                                                                         pBitmap = NULL;\r
327                                                                 }\r
328                                                         }\r
329                                                         else    // Bitmap allocation failed\r
330                                                         {\r
331                                                                 if (pBitmap)\r
332                                                                 {\r
333                                                                         delete pBitmap;\r
334                                                                         pBitmap = NULL;\r
335                                                                 }\r
336                                                         }\r
337 \r
338                                                         FreeImage_Unload(dib);\r
339                                                         dib = NULL;\r
340                                                 }\r
341                                         }\r
342                                 }\r
343 \r
344                                 FreeLibrary(hFreeImageLib);\r
345                                 hFreeImageLib = NULL;\r
346                         }\r
347                 }\r
348         }\r
349         else    // GDI+ Unavailable...\r
350         {\r
351                 pBitmap = NULL;\r
352                 HANDLE hFile = CreateFile(sFilePathName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_HIDDEN, NULL);\r
353                 if (hFile != INVALID_HANDLE_VALUE)\r
354                 {\r
355                         BY_HANDLE_FILE_INFORMATION fileinfo;\r
356                         if (GetFileInformationByHandle(hFile, &fileinfo))\r
357                         {\r
358                                 BYTE * buffer = new BYTE[fileinfo.nFileSizeLow];\r
359                                 DWORD readbytes;\r
360                                 if (ReadFile(hFile, buffer, fileinfo.nFileSizeLow, &readbytes, NULL))\r
361                                 {\r
362                                         if (LoadPictureData(buffer, readbytes))\r
363                                         {\r
364                                                 m_nSize = fileinfo.nFileSizeLow;\r
365                                                 bResult = true;\r
366                                         }\r
367                                 }\r
368                                 delete [] buffer;\r
369                         }\r
370                         CloseHandle(hFile);\r
371                 }\r
372                 else\r
373                         return bResult;\r
374 \r
375                 m_Name = sFilePathName;\r
376                 m_Weight = nSize; // Update Picture Size Info...\r
377 \r
378                 if(m_IPicture != NULL) // Do Not Try To Read From Memory That Does Not Exist...\r
379                 { \r
380                         m_IPicture->get_Height(&m_Height);\r
381                         m_IPicture->get_Width(&m_Width);\r
382                         // Calculate Its Size On a "Standard" (96 DPI) Device Context\r
383                         m_Height = MulDiv(m_Height, 96, HIMETRIC_INCH);\r
384                         m_Width  = MulDiv(m_Width,  96, HIMETRIC_INCH);\r
385                 }\r
386                 else // Picture Data Is Not a Known Picture Type\r
387                 {\r
388                         m_Height = 0;\r
389                         m_Width = 0;\r
390                         bResult = false;\r
391                 }\r
392         }\r
393 \r
394         if ((bResult)&&(m_nSize == 0))\r
395         {\r
396                 HANDLE hFile = CreateFile(sFilePathName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_HIDDEN, NULL);\r
397                 if (hFile != INVALID_HANDLE_VALUE)\r
398                 {\r
399                         BY_HANDLE_FILE_INFORMATION fileinfo;\r
400                         if (GetFileInformationByHandle(hFile, &fileinfo))\r
401                         {\r
402                                 m_nSize = fileinfo.nFileSizeLow;\r
403                         }\r
404                         CloseHandle(hFile);\r
405                 }\r
406         }\r
407 \r
408         m_ColorDepth = GetColorDepth();\r
409 \r
410         return(bResult);\r
411 }\r
412 \r
413 bool CPicture::LoadPictureData(BYTE *pBuffer, int nSize)\r
414 {\r
415         bool bResult = false;\r
416 \r
417         HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize);\r
418 \r
419         if(hGlobal == NULL)\r
420         {\r
421                 return(false);\r
422         }\r
423 \r
424         void* pData = GlobalLock(hGlobal);\r
425         if (pData == NULL)\r
426                 return false;\r
427         memcpy(pData, pBuffer, nSize);\r
428         GlobalUnlock(hGlobal);\r
429 \r
430         IStream* pStream = NULL;\r
431 \r
432         if ((CreateStreamOnHGlobal(hGlobal, true, &pStream) == S_OK)&&(pStream))\r
433         {\r
434                 HRESULT hr;\r
435                 if((hr = OleLoadPicture(pStream, nSize, false, IID_IPicture, (LPVOID *)&m_IPicture)) == S_OK)\r
436                 {\r
437                         pStream->Release();\r
438                         pStream = NULL;\r
439                         bResult = true;\r
440                 }\r
441                 else\r
442                 {\r
443                         return false;\r
444                 }\r
445         }\r
446 \r
447         FreeResource(hGlobal); // 16Bit Windows Needs This (32Bit - Automatic Release)\r
448 \r
449         return(bResult);\r
450 }\r
451 \r
452 bool CPicture::Show(HDC hDC, RECT DrawRect)\r
453 {\r
454         if (hDC == NULL) \r
455                 return false;\r
456         if (bIsIcon && lpIcons)\r
457         {\r
458                 ::DrawIconEx(hDC, DrawRect.left, DrawRect.top, hIcons[nCurrentIcon], DrawRect.right-DrawRect.left, DrawRect.bottom-DrawRect.top, 0, NULL, DI_NORMAL);\r
459                 return true;\r
460         }\r
461         if ((m_IPicture == NULL)&&(pBitmap == NULL))\r
462                 return false;\r
463 \r
464         if (m_IPicture)\r
465         {\r
466                 long Width  = 0;\r
467                 long Height = 0;\r
468                 m_IPicture->get_Width(&Width);\r
469                 m_IPicture->get_Height(&Height);\r
470 \r
471                 HRESULT hrP = NULL;\r
472 \r
473                 hrP = m_IPicture->Render(hDC,\r
474                         DrawRect.left,                  // Left\r
475                         DrawRect.top,                   // Top\r
476                         DrawRect.right - DrawRect.left, // Right\r
477                         DrawRect.bottom - DrawRect.top, // Bottom\r
478                         0,\r
479                         Height,\r
480                         Width,\r
481                         -Height,\r
482                         &DrawRect);\r
483 \r
484                 if (SUCCEEDED(hrP)) \r
485                         return(true);\r
486         }\r
487         else if (pBitmap)\r
488         {\r
489                 Graphics graphics(hDC);\r
490                 graphics.SetInterpolationMode(m_ip);\r
491                 graphics.SetPixelOffsetMode(PixelOffsetModeHighQuality);\r
492                 ImageAttributes attr;\r
493                 attr.SetWrapMode(WrapModeTileFlipXY);\r
494                 Rect rect(DrawRect.left, DrawRect.top, DrawRect.right-DrawRect.left, DrawRect.bottom-DrawRect.top);\r
495                 graphics.DrawImage(pBitmap, rect, 0, 0, m_Width, m_Height, UnitPixel, &attr);\r
496                 return true;\r
497         }\r
498 \r
499         return(false);\r
500 }\r
501 \r
502 bool CPicture::UpdateSizeOnDC(HDC hDC)\r
503 {\r
504         if(hDC == NULL || m_IPicture == NULL) { m_Height = 0; m_Width = 0; return(false); };\r
505 \r
506         m_IPicture->get_Height(&m_Height);\r
507         m_IPicture->get_Width(&m_Width);\r
508 \r
509         // Get Current DPI - Dot Per Inch\r
510         int CurrentDPI_X = GetDeviceCaps(hDC, LOGPIXELSX);\r
511         int CurrentDPI_Y = GetDeviceCaps(hDC, LOGPIXELSY);\r
512 \r
513         m_Height = MulDiv(m_Height, CurrentDPI_Y, HIMETRIC_INCH);\r
514         m_Width  = MulDiv(m_Width,  CurrentDPI_X, HIMETRIC_INCH);\r
515 \r
516         return(true);\r
517 }\r
518 \r
519 UINT CPicture::GetColorDepth() const\r
520 {\r
521         if (bIsIcon && lpIcons)\r
522         {\r
523                 LPICONDIR lpIconDir = (LPICONDIR)lpIcons;\r
524                 return lpIconDir->idEntries[nCurrentIcon].wBitCount;\r
525         }\r
526         switch (GetPixelFormat())\r
527         {\r
528         case PixelFormat1bppIndexed:\r
529                 return 1;\r
530         case PixelFormat4bppIndexed:\r
531                 return 4;\r
532         case PixelFormat8bppIndexed:\r
533                 return 8;\r
534         case PixelFormat16bppARGB1555:\r
535         case PixelFormat16bppGrayScale:\r
536         case PixelFormat16bppRGB555:\r
537         case PixelFormat16bppRGB565:\r
538                 return 16;\r
539         case PixelFormat24bppRGB:\r
540                 return 24;\r
541         case PixelFormat32bppARGB:\r
542         case PixelFormat32bppPARGB:\r
543         case PixelFormat32bppRGB:\r
544                 return 32;\r
545         case PixelFormat48bppRGB:\r
546                 return 48;\r
547         case PixelFormat64bppARGB:\r
548         case PixelFormat64bppPARGB:\r
549                 return 64;\r
550         }\r
551         return 0;\r
552 }\r
553 \r
554 UINT CPicture::GetNumberOfFrames(int dimension)\r
555 {\r
556         if (bIsIcon && lpIcons)\r
557         {\r
558                 return 1;\r
559         }\r
560         if (pBitmap == NULL)\r
561                 return 0;\r
562         UINT count = 0;\r
563         count = pBitmap->GetFrameDimensionsCount();\r
564         GUID* pDimensionIDs = (GUID*)malloc(sizeof(GUID)*count);\r
565 \r
566         pBitmap->GetFrameDimensionsList(pDimensionIDs, count);\r
567 \r
568         UINT frameCount = pBitmap->GetFrameCount(&pDimensionIDs[dimension]);\r
569 \r
570         free(pDimensionIDs);\r
571         return frameCount;\r
572 }\r
573 \r
574 UINT CPicture::GetNumberOfDimensions()\r
575 {\r
576         if (bIsIcon && lpIcons)\r
577         {\r
578                 LPICONDIR lpIconDir = (LPICONDIR)lpIcons;\r
579                 return lpIconDir->idCount;\r
580         }\r
581         return pBitmap ? pBitmap->GetFrameDimensionsCount() : 0;\r
582 }\r
583 \r
584 long CPicture::SetActiveFrame(UINT frame)\r
585 {\r
586         if (bIsIcon && lpIcons)\r
587         {\r
588                 nCurrentIcon = frame-1;\r
589                 m_Height = GetHeight();\r
590                 m_Width = GetWidth();\r
591                 return 0;\r
592         }\r
593         if (pBitmap == NULL)\r
594                 return 0;\r
595         UINT count = 0;\r
596         count = pBitmap->GetFrameDimensionsCount();\r
597         GUID* pDimensionIDs = (GUID*)malloc(sizeof(GUID)*count);\r
598 \r
599         pBitmap->GetFrameDimensionsList(pDimensionIDs, count);\r
600 \r
601         UINT frameCount = pBitmap->GetFrameCount(&pDimensionIDs[0]);\r
602 \r
603         free(pDimensionIDs);\r
604 \r
605         if (frame > frameCount)\r
606                 return 0;\r
607 \r
608         GUID pageGuid = FrameDimensionTime;\r
609         pBitmap->SelectActiveFrame(&pageGuid, frame);\r
610 \r
611         // Assume that the image has a property item of type PropertyItemEquipMake.\r
612         // Get the size of that property item.\r
613         int nSize = pBitmap->GetPropertyItemSize(PropertyTagFrameDelay);\r
614 \r
615         // Allocate a buffer to receive the property item.\r
616         PropertyItem* pPropertyItem = (PropertyItem*) malloc(nSize);\r
617 \r
618         pBitmap->GetPropertyItem(PropertyTagFrameDelay, nSize, pPropertyItem);\r
619 \r
620         UINT prevframe = frame;\r
621         prevframe--;\r
622         if (prevframe < 0)\r
623                 prevframe = 0;\r
624         long delay = ((long*)pPropertyItem->value)[prevframe] * 10;\r
625         free(pPropertyItem);\r
626         m_Height = GetHeight();\r
627         m_Width = GetWidth();\r
628         return delay;\r
629 }\r
630 \r
631 UINT CPicture::GetHeight() const\r
632 {\r
633         if ((bIsIcon)&&(lpIcons))\r
634         {\r
635                 LPICONDIR lpIconDir = (LPICONDIR)lpIcons;\r
636                 return lpIconDir->idEntries[nCurrentIcon].bHeight;\r
637         }\r
638         return pBitmap ? pBitmap->GetHeight() : 0;\r
639 }\r
640 \r
641 UINT CPicture::GetWidth() const\r
642 {\r
643         if ((bIsIcon)&&(lpIcons))\r
644         {\r
645                 LPICONDIR lpIconDir = (LPICONDIR)lpIcons;\r
646                 return lpIconDir->idEntries[nCurrentIcon].bWidth;\r
647         }\r
648         return pBitmap ? pBitmap->GetWidth() : 0;\r
649 }\r
650 \r
651 PixelFormat CPicture::GetPixelFormat() const\r
652 {\r
653         if ((bIsIcon)&&(lpIcons))\r
654         {\r
655                 LPICONDIR lpIconDir = (LPICONDIR)lpIcons;\r
656                 if (lpIconDir->idEntries[nCurrentIcon].wPlanes == 1)\r
657                 {\r
658                         if (lpIconDir->idEntries[nCurrentIcon].wBitCount == 1)\r
659                                 return PixelFormat1bppIndexed;\r
660                         if (lpIconDir->idEntries[nCurrentIcon].wBitCount == 4)\r
661                                 return PixelFormat4bppIndexed;\r
662                         if (lpIconDir->idEntries[nCurrentIcon].wBitCount == 8)\r
663                                 return PixelFormat8bppIndexed;\r
664                 }\r
665                 if (lpIconDir->idEntries[nCurrentIcon].wBitCount == 32)\r
666                 {\r
667                         return PixelFormat32bppARGB;\r
668                 }\r
669         }\r
670         return pBitmap ? pBitmap->GetPixelFormat() : 0;\r
671 }\r