ImageEx.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. // GDIPlusHelper.cpp: implementation of the CGDIPlusHelper class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "ImageEx.h"
  6. #include <process.h>
  7. #ifdef _DEBUG
  8. #undef THIS_FILE
  9. static char THIS_FILE[]=__FILE__;
  10. #define new DEBUG_NEW
  11. #endif
  12. //////////////////////////////////////////////////////////////////////
  13. // Construction/Destruction
  14. //////////////////////////////////////////////////////////////////////
  15. ////////////////////////////////////////////////////////////////////////////////
  16. //
  17. // FUNCTION: ImageEx::ImageEx
  18. //
  19. // DESCRIPTION: Constructor for constructing images from a resource
  20. //
  21. // RETURNS:
  22. //
  23. // NOTES:
  24. //
  25. // MODIFICATIONS:
  26. //
  27. // Name Date Version Comments
  28. // N T ALMOND 29012002 1.0 Origin
  29. //
  30. ////////////////////////////////////////////////////////////////////////////////
  31. ImageEx::ImageEx(LPCTSTR sResourceType, LPCTSTR sResource)
  32. {
  33. Initialize();
  34. m_bStretch = false;
  35. if (Load(sResourceType, sResource))
  36. {
  37. nativeImage = NULL;
  38. lastResult = DllExports::GdipLoadImageFromStreamICM(m_pStream, &nativeImage);
  39. TestForAnimatedGIF();
  40. }
  41. }
  42. ////////////////////////////////////////////////////////////////////////////////
  43. //
  44. // FUNCTION: ImageEx::ImageEx
  45. //
  46. // DESCRIPTION: Constructor for constructing images from a file
  47. //
  48. // RETURNS:
  49. //
  50. // NOTES:
  51. //
  52. // MODIFICATIONS:
  53. //
  54. // Name Date Version Comments
  55. // N T ALMOND 29012002 1.0 Origin
  56. //
  57. ////////////////////////////////////////////////////////////////////////////////
  58. ImageEx::ImageEx(const WCHAR* filename, BOOL useEmbeddedColorManagement) : Image(filename, useEmbeddedColorManagement)
  59. {
  60. Initialize();
  61. m_bIsInitialized = true;
  62. TestForAnimatedGIF();
  63. //chn add
  64. delete []filename;
  65. filename = NULL;
  66. }
  67. ////////////////////////////////////////////////////////////////////////////////
  68. //
  69. // FUNCTION: ImageEx::~ImageEx
  70. //
  71. // DESCRIPTION: Free up fresources
  72. //
  73. // RETURNS:
  74. //
  75. // NOTES:
  76. //
  77. // MODIFICATIONS:
  78. //
  79. // Name Date Version Comments
  80. // N T ALMOND 29012002 1.0 Origin
  81. //
  82. ////////////////////////////////////////////////////////////////////////////////
  83. ImageEx::~ImageEx()
  84. {
  85. Destroy();
  86. }
  87. ////////////////////////////////////////////////////////////////////////////////
  88. //
  89. // FUNCTION: InitAnimation
  90. //
  91. // DESCRIPTION: Prepare animated GIF
  92. //
  93. // RETURNS:
  94. //
  95. // NOTES:
  96. //
  97. // MODIFICATIONS:
  98. //
  99. // Name Date Version Comments
  100. // N T ALMOND 29012002 1.0 Origin
  101. //
  102. ////////////////////////////////////////////////////////////////////////////////
  103. bool ImageEx::InitAnimation(HWND hWnd, CPoint pt)
  104. {
  105. m_hWnd = hWnd;
  106. m_pt = pt;
  107. if (!m_bIsInitialized)
  108. {
  109. TRACE(_T("GIF not initialized\n"));
  110. return false;
  111. }
  112. if (IsAnimatedGIF())
  113. {
  114. if (m_hThread == NULL)
  115. {
  116. unsigned int nTID = 0;
  117. m_hThread = (HANDLE) _beginthreadex( NULL, 0, _ThreadAnimationProc, this, CREATE_SUSPENDED,&nTID);
  118. if (!m_hThread)
  119. {
  120. TRACE(_T("Couldn't start a GIF animation thread\n"));
  121. return true;
  122. }
  123. else
  124. ResumeThread(m_hThread);
  125. }
  126. }
  127. return false;
  128. }
  129. bool ImageEx::InitAnimation(HWND hWnd, CRect rect,BOOL bStretch)
  130. {
  131. m_hWnd = hWnd;
  132. m_Rect.X = rect.left;
  133. m_Rect.Y = rect.top;
  134. m_Rect.Width = rect.Width();
  135. m_Rect.Height = rect.Height();
  136. m_bStretch = bStretch;
  137. if (!m_bIsInitialized)
  138. {
  139. TRACE(_T("GIF not initialized\n"));
  140. return false;
  141. }
  142. if (IsAnimatedGIF())
  143. {
  144. if (m_hThread == NULL)
  145. {
  146. unsigned int nTID = 0;
  147. m_hThread = (HANDLE) _beginthreadex( NULL, 0, _ThreadAnimationProc, this, CREATE_SUSPENDED,&nTID);
  148. if (!m_hThread)
  149. {
  150. TRACE(_T("Couldn't start a GIF animation thread\n"));
  151. return true;
  152. }
  153. else
  154. ResumeThread(m_hThread);
  155. }
  156. }
  157. return false;
  158. }
  159. ////////////////////////////////////////////////////////////////////////////////
  160. //
  161. // FUNCTION: InitAnimation
  162. //
  163. // DESCRIPTION: Prepare animated GIF
  164. //
  165. // RETURNS:
  166. //
  167. // NOTES:
  168. //
  169. // MODIFICATIONS:
  170. //
  171. // Name Date Version Comments
  172. // N T ALMOND 100828 1.0 Origin
  173. //
  174. ////////////////////////////////////////////////////////////////////////////////
  175. bool ImageEx::InitAnimation(HDC hDC, CRect rect,BOOL bStretch)
  176. {
  177. m_hDC = hDC;
  178. m_Rect.X = rect.left;
  179. m_Rect.Y = rect.top;
  180. m_Rect.Width = rect.Width();
  181. m_Rect.Height = rect.Height();
  182. m_bStretch = bStretch;
  183. if (!m_bIsInitialized)
  184. {
  185. TRACE(_T("GIF not initialized\n"));
  186. return false;
  187. };
  188. if (IsAnimatedGIF())
  189. {
  190. if (m_hThread == NULL)
  191. {
  192. unsigned int nTID = 0;
  193. m_hThread = (HANDLE) _beginthreadex( NULL, 0, _ThreadAnimationProc, this, CREATE_SUSPENDED,&nTID);
  194. if (!m_hThread)
  195. {
  196. TRACE(_T("Couldn't start a GIF animation thread\n"));
  197. return true;
  198. }
  199. else
  200. ResumeThread(m_hThread);
  201. }
  202. }
  203. return false;
  204. }
  205. ////////////////////////////////////////////////////////////////////////////////
  206. //
  207. // FUNCTION: LoadFromBuffer
  208. //
  209. // DESCRIPTION: Helper function to copy phyical memory from buffer a IStream
  210. //
  211. // RETURNS:
  212. //
  213. // NOTES:
  214. //
  215. // MODIFICATIONS:
  216. //
  217. // Name Date Version Comments
  218. // N T ALMOND 29012002 1.0 Origin
  219. //
  220. ////////////////////////////////////////////////////////////////////////////////
  221. bool ImageEx::LoadFromBuffer(BYTE* pBuff, int nSize)
  222. {
  223. bool bResult = false;
  224. HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize);
  225. if (hGlobal)
  226. {
  227. void* pData = GlobalLock(hGlobal);
  228. if (pData)
  229. memcpy(pData, pBuff, nSize);
  230. GlobalUnlock(hGlobal);
  231. if (CreateStreamOnHGlobal(hGlobal, TRUE, &m_pStream) == S_OK)
  232. bResult = true;
  233. }
  234. return bResult;
  235. }
  236. ////////////////////////////////////////////////////////////////////////////////
  237. //
  238. // FUNCTION: GetResource
  239. //
  240. // DESCRIPTION: Helper function to lock down resource
  241. //
  242. // RETURNS:
  243. //
  244. // NOTES:
  245. //
  246. // MODIFICATIONS:
  247. //
  248. // Name Date Version Comments
  249. // N T ALMOND 29012002 1.0 Origin
  250. //
  251. ////////////////////////////////////////////////////////////////////////////////
  252. bool ImageEx::GetResource(LPCTSTR lpName, LPCTSTR lpType, void* pResource, int& nBufSize)
  253. {
  254. HRSRC hResInfo;
  255. HANDLE hRes;
  256. LPSTR lpRes = NULL;
  257. int nLen = 0;
  258. bool bResult = FALSE;
  259. // Find the resource
  260. hResInfo = FindResource(m_hInst , lpName, lpType);
  261. if (hResInfo == NULL)
  262. {
  263. DWORD dwErr = GetLastError();
  264. return false;
  265. }
  266. // Load the resource
  267. hRes = LoadResource(m_hInst , hResInfo);
  268. if (hRes == NULL)
  269. return false;
  270. // Lock the resource
  271. lpRes = (char*)LockResource(hRes);
  272. if (lpRes != NULL)
  273. {
  274. if (pResource == NULL)
  275. {
  276. nBufSize = SizeofResource(m_hInst , hResInfo);
  277. bResult = true;
  278. }
  279. else
  280. {
  281. if (nBufSize >= (int)SizeofResource(m_hInst , hResInfo))
  282. {
  283. memcpy(pResource, lpRes, nBufSize);
  284. bResult = true;
  285. }
  286. }
  287. UnlockResource(hRes);
  288. }
  289. // Free the resource
  290. FreeResource(hRes);
  291. return bResult;
  292. }
  293. ////////////////////////////////////////////////////////////////////////////////
  294. //
  295. // FUNCTION: Load
  296. //
  297. // DESCRIPTION: Helper function to load resource from memory
  298. //
  299. // RETURNS:
  300. //
  301. // NOTES:
  302. //
  303. // MODIFICATIONS:
  304. //
  305. // Name Date Version Comments
  306. // N T ALMOND 29012002 1.0 Origin
  307. //
  308. ////////////////////////////////////////////////////////////////////////////////
  309. bool ImageEx::Load(CString sResourceType, CString sResource)
  310. {
  311. bool bResult = false;
  312. BYTE* pBuff = NULL;
  313. int nSize = 0;
  314. if (GetResource(sResource.GetBuffer(0), sResourceType.GetBuffer(0), pBuff, nSize))
  315. {
  316. if (nSize > 0)
  317. {
  318. pBuff = new BYTE[nSize];
  319. if (GetResource(sResource, sResourceType.GetBuffer(0), pBuff, nSize))
  320. {
  321. if (LoadFromBuffer(pBuff, nSize))
  322. {
  323. bResult = true;
  324. }
  325. }
  326. delete [] pBuff;
  327. }
  328. }
  329. m_bIsInitialized = bResult;
  330. return bResult;
  331. }
  332. ////////////////////////////////////////////////////////////////////////////////
  333. //
  334. // FUNCTION: GetSize
  335. //
  336. // DESCRIPTION: Returns Width and Height object
  337. //
  338. // RETURNS:
  339. //
  340. // NOTES:
  341. //
  342. // MODIFICATIONS:
  343. //
  344. // Name Date Version Comments
  345. // N T ALMOND 29012002 1.0 Origin
  346. //
  347. ////////////////////////////////////////////////////////////////////////////////
  348. CSize ImageEx::GetSize()
  349. {
  350. return CSize(GetWidth(), GetHeight());
  351. }
  352. ////////////////////////////////////////////////////////////////////////////////
  353. //
  354. // FUNCTION: TestForAnimatedGIF
  355. //
  356. // DESCRIPTION: Check GIF/Image for avialability of animation
  357. //
  358. // RETURNS:
  359. //
  360. // NOTES:
  361. //
  362. // MODIFICATIONS:
  363. //
  364. // Name Date Version Comments
  365. // N T ALMOND 29012002 1.0 Origin
  366. //
  367. ////////////////////////////////////////////////////////////////////////////////
  368. bool ImageEx::TestForAnimatedGIF()
  369. {
  370. UINT count = 0;
  371. count = GetFrameDimensionsCount();
  372. GUID* pDimensionIDs = new GUID[count];
  373. // Get the list of frame dimensions from the Image object.
  374. GetFrameDimensionsList(pDimensionIDs, count);
  375. // Get the number of frames in the first dimension.
  376. m_nFrameCount = GetFrameCount(&pDimensionIDs[0]);
  377. // Assume that the image has a property item of type PropertyItemEquipMake.
  378. // Get the size of that property item.
  379. int nSize = GetPropertyItemSize(PropertyTagFrameDelay);
  380. // Allocate a buffer to receive the property item.
  381. m_pPropertyItem = (PropertyItem*) malloc(nSize);
  382. GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem);
  383. delete []pDimensionIDs;
  384. return m_nFrameCount > 1;
  385. }
  386. ////////////////////////////////////////////////////////////////////////////////
  387. //
  388. // FUNCTION: ImageEx::Initialize
  389. //
  390. // DESCRIPTION: Common function called from Constructors
  391. //
  392. // RETURNS:
  393. //
  394. // NOTES:
  395. //
  396. // MODIFICATIONS:
  397. //
  398. // Name Date Version Comments
  399. // N T ALMOND 29012002 1.0 Origin
  400. //
  401. ////////////////////////////////////////////////////////////////////////////////
  402. void ImageEx::Initialize()
  403. {
  404. m_pStream = NULL;
  405. m_nFramePosition = 0;
  406. m_nFrameCount = 0;
  407. lastResult = InvalidParameter;
  408. m_hThread = NULL;
  409. m_bIsInitialized = false;
  410. m_pPropertyItem = NULL;
  411. #ifdef INDIGO_CTRL_PROJECT
  412. m_hInst = _Module.GetResourceInstance();
  413. #else
  414. m_hInst = AfxGetResourceHandle();
  415. #endif
  416. m_bPause = false;
  417. m_hExitEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  418. m_hPause = CreateEvent(NULL,TRUE,TRUE,NULL);
  419. }
  420. ////////////////////////////////////////////////////////////////////////////////
  421. //
  422. // FUNCTION: ImageEx::_ThreadAnimationProc
  423. //
  424. // DESCRIPTION: Thread to draw animated gifs
  425. //
  426. // RETURNS:
  427. //
  428. // NOTES:
  429. //
  430. // MODIFICATIONS:
  431. //
  432. // Name Date Version Comments
  433. // N T ALMOND 29012002 1.0 Origin
  434. //
  435. ////////////////////////////////////////////////////////////////////////////////
  436. UINT WINAPI ImageEx::_ThreadAnimationProc(LPVOID pParam)
  437. {
  438. ASSERT(pParam);
  439. ImageEx *pImage = reinterpret_cast<ImageEx *> (pParam);
  440. pImage->ThreadAnimation();
  441. return 0;
  442. }
  443. ////////////////////////////////////////////////////////////////////////////////
  444. //
  445. // FUNCTION: ImageEx::ThreadAnimation
  446. //
  447. // DESCRIPTION: Helper function
  448. //
  449. // RETURNS:
  450. //
  451. // NOTES:
  452. //
  453. // MODIFICATIONS:
  454. //
  455. // Name Date Version Comments
  456. // N T ALMOND 29012002 1.0 Origin
  457. //
  458. ////////////////////////////////////////////////////////////////////////////////
  459. void ImageEx::ThreadAnimation()
  460. {
  461. m_nFramePosition = 0;
  462. bool bExit = false;
  463. while (bExit == false)
  464. {
  465. bExit = DrawFrameGIF();
  466. Sleep(10);
  467. }
  468. }
  469. ////////////////////////////////////////////////////////////////////////////////
  470. //
  471. // FUNCTION: ImageEx::DrawFrameGIF
  472. //
  473. // DESCRIPTION:
  474. //
  475. // RETURNS:
  476. //
  477. // NOTES:
  478. //
  479. // MODIFICATIONS:
  480. //
  481. // Name Date Version Comments
  482. // N T ALMOND 29012002 1.0 Origin
  483. //
  484. ////////////////////////////////////////////////////////////////////////////////
  485. bool ImageEx::DrawFrameGIF()
  486. {
  487. ::WaitForSingleObject(m_hPause, INFINITE);
  488. GUID pageGuid = FrameDimensionTime;
  489. #if 1
  490. long hmWidth = GetWidth();
  491. long hmHeight = GetHeight();
  492. HDC hDC = GetDC(m_hWnd);
  493. if (hDC)
  494. {
  495. Graphics graphics(hDC);
  496. if(m_bStretch)
  497. {
  498. graphics.DrawImage(this, m_Rect.X, m_Rect.Y, m_Rect.Width, m_Rect.Height);
  499. }
  500. else
  501. {
  502. graphics.DrawImage( this, m_Rect.X, m_Rect.Y,0,0,m_Rect.Width,m_Rect.Height,UnitPixel );
  503. }
  504. ReleaseDC(m_hWnd, m_hDC);
  505. DeleteObject( hDC );
  506. }
  507. SelectActiveFrame(&pageGuid, m_nFramePosition++);
  508. if (m_nFramePosition == m_nFrameCount)
  509. m_nFramePosition = 0;
  510. long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
  511. DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause);
  512. return dwErr == WAIT_OBJECT_0;
  513. #else
  514. if( m_hDC )
  515. {
  516. Graphics graphics(m_hDC);
  517. //graphics.DrawImage(this, m_Rect);
  518. graphics.DrawImage(this, 10, 10, 20, 20);
  519. }
  520. SelectActiveFrame(&pageGuid, m_nFramePosition++);
  521. if (m_nFramePosition == m_nFrameCount)
  522. m_nFramePosition = 0;
  523. long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
  524. DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause);
  525. return dwErr == WAIT_OBJECT_0;
  526. #endif
  527. }
  528. ////////////////////////////////////////////////////////////////////////////////
  529. //
  530. // FUNCTION: ImageEx::SetPause
  531. //
  532. // DESCRIPTION: Toggle Pause state of GIF
  533. //
  534. // RETURNS:
  535. //
  536. // NOTES:
  537. //
  538. // MODIFICATIONS:
  539. //
  540. // Name Date Version Comments
  541. // N T ALMOND 29012002 1.0 Origin
  542. //
  543. ////////////////////////////////////////////////////////////////////////////////
  544. void ImageEx::SetPause(bool bPause)
  545. {
  546. if (!IsAnimatedGIF())
  547. return;
  548. if (bPause && !m_bPause)
  549. {
  550. ::ResetEvent(m_hPause);
  551. }
  552. else
  553. {
  554. if (m_bPause && !bPause)
  555. {
  556. ::SetEvent(m_hPause);
  557. }
  558. }
  559. m_bPause = bPause;
  560. }
  561. void ImageEx::Destroy()
  562. {
  563. if (m_hThread)
  564. {
  565. // If pause un pause
  566. SetPause(false);
  567. SetEvent(m_hExitEvent);
  568. WaitForSingleObject(m_hThread, INFINITE);
  569. }
  570. CloseHandle(m_hThread);
  571. CloseHandle(m_hExitEvent);
  572. CloseHandle(m_hPause);
  573. free(m_pPropertyItem);
  574. m_pPropertyItem = NULL;
  575. m_hThread = NULL;
  576. m_hExitEvent = NULL;
  577. m_hPause = NULL;
  578. if (m_pStream)
  579. m_pStream->Release();
  580. }