/* Popup Plus plugin for Miranda IM Copyright � 2002 Luca Santarelli, � 2004-2007 Victor Pavlychko � 2010 MPK � 2010 Merlin_de This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. =============================================================================== File name : $HeadURL: http://svn.miranda.im/mainrepo/popup/trunk/src/popup_gdiplus.cpp $ Revision : $Revision: 1622 $ Last change on : $Date: 2010-06-23 23:32:21 +0300 (Ср, 23 июн 2010) $ Last change by : $Author: Merlin_de $ =============================================================================== */ /* 99% of this code was adopted from clist_modern by FYR */ #include "headers.h" #undef Translate // fix for old SDK and new GDI+ #define ULONG_PTR unsigned long #include "gdiplus.h" DWORD g_gdiplusToken; bool gbGdiPlusLoaded; void LoadGDIPlus() { Gdiplus::GdiplusStartupInput gdiplusStartupInput; gbGdiPlusLoaded = false; __try { if (g_gdiplusToken == 0) Gdiplus::GdiplusStartup(&g_gdiplusToken, &gdiplusStartupInput, NULL); } __except ( EXCEPTION_EXECUTE_HANDLER ) { gbGdiPlusLoaded = false; } } void UnloadGDIPlus() { Gdiplus::GdiplusStartupInput gdiplusStartupInput; __try { if (g_gdiplusToken && gbGdiPlusLoaded) Gdiplus::GdiplusShutdown(g_gdiplusToken); } __except ( EXCEPTION_EXECUTE_HANDLER ) { // do nothing } gbGdiPlusLoaded = true; g_gdiplusToken = 0; } using namespace Gdiplus; ///////////////////////////////////////////////////////////////////////////////// // GDIPlus_IsAnimatedGIF and GDIPlus_ExtractAnimatedGIF // based on routine from http://www.codeproject.com/vcpp/gdiplus/imageexgdi.asp // HBITMAP SkinEngine_CreateDIB32(int cx, int cy) { BITMAPINFO RGB32BitsBITMAPINFO; UINT * ptPixels; HBITMAP DirectBitmap; if ( cx < 0 || cy < 0 ) { return NULL; } ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO)); RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); RGB32BitsBITMAPINFO.bmiHeader.biWidth=cx;//bm.bmWidth; RGB32BitsBITMAPINFO.bmiHeader.biHeight=cy;//bm.bmHeight; RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1; RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32; // pointer used for direct Bitmap pixels access DirectBitmap = CreateDIBSection(NULL, (BITMAPINFO *)&RGB32BitsBITMAPINFO, DIB_RGB_COLORS, (void **)&ptPixels, NULL, 0); if ((DirectBitmap == NULL || ptPixels == NULL) && cx!= 0 && cy!=0) { ; } else { memset(ptPixels,0,cx*cy*4); } return DirectBitmap; } BOOL GDIPlus_IsAnimatedGIF(TCHAR * szName) { int nFrameCount=0; Image image(szName); UINT count = 0; count = image.GetFrameDimensionsCount(); GUID* pDimensionIDs = new GUID[count]; // Get the list of frame dimensions from the Image object. image.GetFrameDimensionsList(pDimensionIDs, count); // Get the number of frames in the first dimension. nFrameCount = image.GetFrameCount(&pDimensionIDs[0]); delete []pDimensionIDs; return (BOOL) (nFrameCount > 1) && image.GetWidth() && image.GetHeight(); } void GDIPlus_GetGIFSize(TCHAR * szName, int * width, int * height) { Image image(szName); *width = image.GetWidth(); *height = image.GetHeight(); } void GDIPlus_ExtractAnimatedGIF(TCHAR * szName, int width, int height, HBITMAP * pBitmap, int ** pframesDelay, int * pframesCount, SIZE * pSizeAvatar) { int nFrameCount=0; Bitmap image(szName); PropertyItem * pPropertyItem; UINT count = 0; count = image.GetFrameDimensionsCount(); GUID* pDimensionIDs = new GUID[count]; // Get the list of frame dimensions from the Image object. image.GetFrameDimensionsList(pDimensionIDs, count); // Get the number of frames in the first dimension. nFrameCount = image.GetFrameCount(&pDimensionIDs[0]); // Assume that the image has a property item of type PropertyItemEquipMake. // Get the size of that property item. int nSize = image.GetPropertyItemSize(PropertyTagFrameDelay); // Allocate a buffer to receive the property item. pPropertyItem = (PropertyItem*) mir_alloc(nSize); image.GetPropertyItem(PropertyTagFrameDelay, nSize, pPropertyItem); int clipWidth; int clipHeight; int imWidth=image.GetWidth(); int imHeight=image.GetHeight(); float xscale=(float)width/imWidth; float yscale=(float)height/imHeight; xscale=min(xscale,yscale); clipWidth=(int)(xscale*imWidth+.5); clipHeight=(int)(xscale*imHeight+.5); HBITMAP hBitmap=SkinEngine_CreateDIB32(clipWidth*nFrameCount, height); HDC hdc=CreateCompatibleDC(NULL); HBITMAP oldBmp=(HBITMAP)SelectObject(hdc,hBitmap); Graphics graphics(hdc); ImageAttributes attr; ColorMatrix ClrMatrix = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, ((float)255)/255, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f }; //attr.SetColorMatrix(&ClrMatrix, ColorMatrixFlagsDefault,ColorAdjustTypeBitmap); graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic); int * delays=(int*)mir_alloc(nFrameCount*sizeof(int)); memset(delays,0,nFrameCount*sizeof(int)); for (int i=1; ivalue)[i-1] * 10; delays[i-1]=(int)lPause; } SelectObject(hdc,oldBmp); DeleteDC(hdc); mir_free(pPropertyItem); pPropertyItem = NULL; delete []pDimensionIDs; if (pBitmap && pframesDelay && pframesCount && pSizeAvatar) { *pBitmap=hBitmap; *pframesDelay=delays; *pframesCount=nFrameCount; pSizeAvatar->cx=clipWidth; pSizeAvatar->cy=clipHeight; } GdiFlush(); }