/* 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. */ /* 99% of this code was adopted from clist_modern by FYR */ #include "stdafx.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, nullptr); } __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) { if (cx < 0 || cy < 0) { return nullptr; } BITMAPINFO RGB32BitsBITMAPINFO; memset(&RGB32BitsBITMAPINFO, 0, 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 UINT *ptPixels; HBITMAP DirectBitmap = CreateDIBSection(nullptr, &RGB32BitsBITMAPINFO, DIB_RGB_COLORS, (void **)&ptPixels, nullptr, 0); if ((DirectBitmap == nullptr || ptPixels == nullptr) && cx != 0 && cy != 0) { ; } else { memset(ptPixels, 0, cx*cy * 4); } return DirectBitmap; } BOOL GDIPlus_IsAnimatedGIF(wchar_t * szName) { int nFrameCount = 0; Image image(szName); UINT 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(wchar_t *szName, int *width, int *height) { Image image(szName); *width = image.GetWidth(); *height = image.GetHeight(); } void GDIPlus_ExtractAnimatedGIF(wchar_t *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(nullptr); HBITMAP oldBmp = (HBITMAP)SelectObject(hdc, hBitmap); Graphics graphics(hdc); ImageAttributes attr; graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic); int * delays = (int*)mir_alloc(nFrameCount*sizeof(int)); memset(delays, 0, nFrameCount*sizeof(int)); for (int i = 1; i < nFrameCount + 1; i++) { GUID pageGuid = FrameDimensionTime; RectF rect((float)(i - 1)*clipWidth, (float)0, (float)clipWidth, (float)clipHeight); graphics.DrawImage(&image, rect, (float)0, (float)0, (float)imWidth, (float)imHeight, UnitPixel, &attr, nullptr, nullptr); image.SelectActiveFrame(&pageGuid, i); long lPause = ((long*)pPropertyItem->value)[i - 1] * 10; delays[i - 1] = (int)lPause; } SelectObject(hdc, oldBmp); DeleteDC(hdc); mir_free(pPropertyItem); pPropertyItem = nullptr; delete[]pDimensionIDs; pBitmap = hBitmap; pframesDelay = delays; pframesCount = nFrameCount; pSizeAvatar.cx = clipWidth; pSizeAvatar.cy = clipHeight; GdiFlush(); }