// GDIPlusHelper.cpp: implementation of the CGDIPlusHelper class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "ImageEx.h" #include #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: ImageEx::ImageEx // // DESCRIPTION: Constructor for constructing images from a resource // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// ImageEx::ImageEx(LPCTSTR sResourceType, LPCTSTR sResource) { Initialize(); m_bStretch = false; if (Load(sResourceType, sResource)) { nativeImage = NULL; lastResult = DllExports::GdipLoadImageFromStreamICM(m_pStream, &nativeImage); TestForAnimatedGIF(); } } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: ImageEx::ImageEx // // DESCRIPTION: Constructor for constructing images from a file // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// ImageEx::ImageEx(const WCHAR* filename, BOOL useEmbeddedColorManagement) : Image(filename, useEmbeddedColorManagement) { Initialize(); m_bIsInitialized = true; TestForAnimatedGIF(); //chn add delete []filename; filename = NULL; } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: ImageEx::~ImageEx // // DESCRIPTION: Free up fresources // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// ImageEx::~ImageEx() { Destroy(); } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: InitAnimation // // DESCRIPTION: Prepare animated GIF // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// bool ImageEx::InitAnimation(HWND hWnd, CPoint pt) { m_hWnd = hWnd; m_pt = pt; if (!m_bIsInitialized) { TRACE(_T("GIF not initialized\n")); return false; } if (IsAnimatedGIF()) { if (m_hThread == NULL) { unsigned int nTID = 0; m_hThread = (HANDLE) _beginthreadex( NULL, 0, _ThreadAnimationProc, this, CREATE_SUSPENDED,&nTID); if (!m_hThread) { TRACE(_T("Couldn't start a GIF animation thread\n")); return true; } else ResumeThread(m_hThread); } } return false; } bool ImageEx::InitAnimation(HWND hWnd, CRect rect,BOOL bStretch) { m_hWnd = hWnd; m_Rect.X = rect.left; m_Rect.Y = rect.top; m_Rect.Width = rect.Width(); m_Rect.Height = rect.Height(); m_bStretch = bStretch; if (!m_bIsInitialized) { TRACE(_T("GIF not initialized\n")); return false; } if (IsAnimatedGIF()) { if (m_hThread == NULL) { unsigned int nTID = 0; m_hThread = (HANDLE) _beginthreadex( NULL, 0, _ThreadAnimationProc, this, CREATE_SUSPENDED,&nTID); if (!m_hThread) { TRACE(_T("Couldn't start a GIF animation thread\n")); return true; } else ResumeThread(m_hThread); } } return false; } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: InitAnimation // // DESCRIPTION: Prepare animated GIF // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 100828 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// bool ImageEx::InitAnimation(HDC hDC, CRect rect,BOOL bStretch) { m_hDC = hDC; m_Rect.X = rect.left; m_Rect.Y = rect.top; m_Rect.Width = rect.Width(); m_Rect.Height = rect.Height(); m_bStretch = bStretch; if (!m_bIsInitialized) { TRACE(_T("GIF not initialized\n")); return false; }; if (IsAnimatedGIF()) { if (m_hThread == NULL) { unsigned int nTID = 0; m_hThread = (HANDLE) _beginthreadex( NULL, 0, _ThreadAnimationProc, this, CREATE_SUSPENDED,&nTID); if (!m_hThread) { TRACE(_T("Couldn't start a GIF animation thread\n")); return true; } else ResumeThread(m_hThread); } } return false; } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: LoadFromBuffer // // DESCRIPTION: Helper function to copy phyical memory from buffer a IStream // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// bool ImageEx::LoadFromBuffer(BYTE* pBuff, int nSize) { bool bResult = false; HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize); if (hGlobal) { void* pData = GlobalLock(hGlobal); if (pData) memcpy(pData, pBuff, nSize); GlobalUnlock(hGlobal); if (CreateStreamOnHGlobal(hGlobal, TRUE, &m_pStream) == S_OK) bResult = true; } return bResult; } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: GetResource // // DESCRIPTION: Helper function to lock down resource // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// bool ImageEx::GetResource(LPCTSTR lpName, LPCTSTR lpType, void* pResource, int& nBufSize) { HRSRC hResInfo; HANDLE hRes; LPSTR lpRes = NULL; int nLen = 0; bool bResult = FALSE; // Find the resource hResInfo = FindResource(m_hInst , lpName, lpType); if (hResInfo == NULL) { DWORD dwErr = GetLastError(); return false; } // Load the resource hRes = LoadResource(m_hInst , hResInfo); if (hRes == NULL) return false; // Lock the resource lpRes = (char*)LockResource(hRes); if (lpRes != NULL) { if (pResource == NULL) { nBufSize = SizeofResource(m_hInst , hResInfo); bResult = true; } else { if (nBufSize >= (int)SizeofResource(m_hInst , hResInfo)) { memcpy(pResource, lpRes, nBufSize); bResult = true; } } UnlockResource(hRes); } // Free the resource FreeResource(hRes); return bResult; } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: Load // // DESCRIPTION: Helper function to load resource from memory // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// bool ImageEx::Load(CString sResourceType, CString sResource) { bool bResult = false; BYTE* pBuff = NULL; int nSize = 0; if (GetResource(sResource.GetBuffer(0), sResourceType.GetBuffer(0), pBuff, nSize)) { if (nSize > 0) { pBuff = new BYTE[nSize]; if (GetResource(sResource, sResourceType.GetBuffer(0), pBuff, nSize)) { if (LoadFromBuffer(pBuff, nSize)) { bResult = true; } } delete [] pBuff; } } m_bIsInitialized = bResult; return bResult; } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: GetSize // // DESCRIPTION: Returns Width and Height object // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// CSize ImageEx::GetSize() { return CSize(GetWidth(), GetHeight()); } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: TestForAnimatedGIF // // DESCRIPTION: Check GIF/Image for avialability of animation // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// bool ImageEx::TestForAnimatedGIF() { UINT count = 0; count = GetFrameDimensionsCount(); GUID* pDimensionIDs = new GUID[count]; // Get the list of frame dimensions from the Image object. GetFrameDimensionsList(pDimensionIDs, count); // Get the number of frames in the first dimension. m_nFrameCount = GetFrameCount(&pDimensionIDs[0]); // Assume that the image has a property item of type PropertyItemEquipMake. // Get the size of that property item. int nSize = GetPropertyItemSize(PropertyTagFrameDelay); // Allocate a buffer to receive the property item. m_pPropertyItem = (PropertyItem*) malloc(nSize); GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem); delete []pDimensionIDs; return m_nFrameCount > 1; } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: ImageEx::Initialize // // DESCRIPTION: Common function called from Constructors // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// void ImageEx::Initialize() { m_pStream = NULL; m_nFramePosition = 0; m_nFrameCount = 0; lastResult = InvalidParameter; m_hThread = NULL; m_bIsInitialized = false; m_pPropertyItem = NULL; #ifdef INDIGO_CTRL_PROJECT m_hInst = _Module.GetResourceInstance(); #else m_hInst = AfxGetResourceHandle(); #endif m_bPause = false; m_hExitEvent = CreateEvent(NULL,TRUE,FALSE,NULL); m_hPause = CreateEvent(NULL,TRUE,TRUE,NULL); } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: ImageEx::_ThreadAnimationProc // // DESCRIPTION: Thread to draw animated gifs // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// UINT WINAPI ImageEx::_ThreadAnimationProc(LPVOID pParam) { ASSERT(pParam); ImageEx *pImage = reinterpret_cast (pParam); pImage->ThreadAnimation(); return 0; } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: ImageEx::ThreadAnimation // // DESCRIPTION: Helper function // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// void ImageEx::ThreadAnimation() { m_nFramePosition = 0; bool bExit = false; while (bExit == false) { bExit = DrawFrameGIF(); Sleep(10); } } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: ImageEx::DrawFrameGIF // // DESCRIPTION: // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// bool ImageEx::DrawFrameGIF() { ::WaitForSingleObject(m_hPause, INFINITE); GUID pageGuid = FrameDimensionTime; #if 1 long hmWidth = GetWidth(); long hmHeight = GetHeight(); HDC hDC = GetDC(m_hWnd); if (hDC) { Graphics graphics(hDC); if(m_bStretch) { graphics.DrawImage(this, m_Rect.X, m_Rect.Y, m_Rect.Width, m_Rect.Height); } else { graphics.DrawImage( this, m_Rect.X, m_Rect.Y,0,0,m_Rect.Width,m_Rect.Height,UnitPixel ); } ReleaseDC(m_hWnd, m_hDC); DeleteObject( hDC ); } SelectActiveFrame(&pageGuid, m_nFramePosition++); if (m_nFramePosition == m_nFrameCount) m_nFramePosition = 0; long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10; DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause); return dwErr == WAIT_OBJECT_0; #else if( m_hDC ) { Graphics graphics(m_hDC); //graphics.DrawImage(this, m_Rect); graphics.DrawImage(this, 10, 10, 20, 20); } SelectActiveFrame(&pageGuid, m_nFramePosition++); if (m_nFramePosition == m_nFrameCount) m_nFramePosition = 0; long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10; DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause); return dwErr == WAIT_OBJECT_0; #endif } //////////////////////////////////////////////////////////////////////////////// // // FUNCTION: ImageEx::SetPause // // DESCRIPTION: Toggle Pause state of GIF // // RETURNS: // // NOTES: // // MODIFICATIONS: // // Name Date Version Comments // N T ALMOND 29012002 1.0 Origin // //////////////////////////////////////////////////////////////////////////////// void ImageEx::SetPause(bool bPause) { if (!IsAnimatedGIF()) return; if (bPause && !m_bPause) { ::ResetEvent(m_hPause); } else { if (m_bPause && !bPause) { ::SetEvent(m_hPause); } } m_bPause = bPause; } void ImageEx::Destroy() { if (m_hThread) { // If pause un pause SetPause(false); SetEvent(m_hExitEvent); WaitForSingleObject(m_hThread, INFINITE); } CloseHandle(m_hThread); CloseHandle(m_hExitEvent); CloseHandle(m_hPause); free(m_pPropertyItem); m_pPropertyItem = NULL; m_hThread = NULL; m_hExitEvent = NULL; m_hPause = NULL; if (m_pStream) m_pStream->Release(); }