PictureEx.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. //////////////////////////////////////////////////////////////////////
  2. // PictureEx.cpp: implementation of the CPictureEx class.
  3. //
  4. // Picture displaying control with support for the following formats:
  5. // GIF (including animated GIF87a and GIF89a), JPEG, BMP, WMF, ICO, CUR
  6. //
  7. // Written by Oleg Bykov (oleg_bykoff@rsdn.ru)
  8. // Copyright (c) 2001
  9. //
  10. // To use CPictureEx, follow these steps:
  11. // - place a static control on your dialog (either a text or a bitmap)
  12. // - change its identifier to something else (e.g. IDC_MYPIC)
  13. // - associate a CStatic with it using ClassWizard
  14. // - in your dialog's header file replace CStatic with CPictureEx
  15. // (don't forget to #include "PictureEx.h" and add
  16. // PictureEx.h and PictureEx.cpp to your project)
  17. // - call one of the overloaded CPictureEx::Load() functions somewhere
  18. // (OnInitDialog is a good place to start)
  19. // - if the preceding Load() succeeded call Draw()
  20. //
  21. // You can also add the control by defining a member variable of type
  22. // CPictureEx, calling CPictureEx::Create (derived from CStatic), then
  23. // CPictureEx::Load and CPictureEx::Draw.
  24. //
  25. // By default, the control initializes its background to COLOR_3DFACE
  26. // (see CPictureEx::PrepareDC()). You can change the background by
  27. // calling CPictureEx::SetBkColor(COLORREF) after CPictureEx::Load().
  28. //
  29. // I decided to leave in the class the functions to write separate frames from
  30. // animated GIF to disk. If you want to use them, uncomment #define GIF_TRACING
  31. // and an appropriate section in CPictureEx::Load(HGLOBAL, DWORD). These functions
  32. // won't be compiled and linked to your project unless you uncomment #define GIF_TRACING,
  33. // so you don't have to worry.
  34. //
  35. // Warning: this code hasn't been subject to a heavy testing, so
  36. // use it on your own risk. The author accepts no liability for the
  37. // possible damage caused by this code.
  38. //
  39. // Version 1.0 7 Aug 2001
  40. // Initial release
  41. //
  42. // Version 1.1 6 Sept 2001
  43. // ATL version of the class
  44. //
  45. // Version 1.2 14 Oct 2001
  46. // - Fixed a problem with loading GIFs from resources
  47. // in MFC-version of the class for multi-modules apps.
  48. // Thanks to Ruben Avila-Carretero for finding this out.
  49. //
  50. // - Got rid of waitable timer in ThreadAnimation()
  51. // Now CPictureEx[Wnd] works in Win95 too.
  52. // Thanks to Alex Egiazarov and Wayne King for the idea.
  53. //
  54. // - Fixed a visual glitch of using SetBkColor.
  55. // Thanks to Kwangjin Lee for finding this out.
  56. //
  57. // Version 1.3 10 Nov 2001
  58. // - Fixed a DC leak. One DC leaked per each UnLoad()
  59. // (forgot to put a ReleaseDC() in the end of
  60. // CPictureExWnd::PrepareDC() function).
  61. //
  62. // - Now it is possible to set a clipping rectangle using
  63. // CPictureEx[Wnd]::SetPaintRect(const LPRECT) function.
  64. // The LPRECT parameter tells the class what portion of
  65. // a picture should it display. If the clipping rect is
  66. // not set, the whole picture is shown.
  67. // Thanks to Fabrice Rodriguez for the idea.
  68. //
  69. // - Added support for Stop/Draw. Now you can Stop() an
  70. // animated GIF, then Draw() it again, it will continue
  71. // animation from the frame it was stopped on. You can
  72. // also know if a GIF is currently playing with the
  73. // IsPlaying() function.
  74. //
  75. // - Got rid of math.h and made m_bExitThread volatile.
  76. // Thanks to Piotr Sawicki for the suggestion.
  77. //
  78. //////////////////////////////////////////////////////////////////////
  79. #if !defined(AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_)
  80. #define AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_
  81. #if _MSC_VER > 1000
  82. #pragma once
  83. #endif // _MSC_VER > 1000
  84. #include <vector>
  85. //#define GIF_TRACING // uncomment it if you want detailed TRACEs
  86. class CPictureEx : public CStatic
  87. {
  88. public:
  89. struct TFrame // structure that keeps a single frame info
  90. {
  91. IPicture *m_pPicture; // pointer to the interface used for drawing
  92. SIZE m_frameSize;
  93. SIZE m_frameOffset;
  94. UINT m_nDelay; // delay (in 1/100s of a second)
  95. UINT m_nDisposal; // disposal method
  96. };
  97. #pragma pack(1) // turn byte alignment on
  98. enum GIFBlockTypes
  99. {
  100. BLOCK_UNKNOWN,
  101. BLOCK_APPEXT,
  102. BLOCK_COMMEXT,
  103. BLOCK_CONTROLEXT,
  104. BLOCK_PLAINTEXT,
  105. BLOCK_IMAGE,
  106. BLOCK_TRAILER
  107. };
  108. enum ControlExtValues // graphic control extension packed field values
  109. {
  110. GCX_PACKED_DISPOSAL, // disposal method
  111. GCX_PACKED_USERINPUT,
  112. GCX_PACKED_TRANSPCOLOR
  113. };
  114. enum LSDPackedValues // logical screen descriptor packed field values
  115. {
  116. LSD_PACKED_GLOBALCT,
  117. LSD_PACKED_CRESOLUTION,
  118. LSD_PACKED_SORT,
  119. LSD_PACKED_GLOBALCTSIZE
  120. };
  121. enum IDPackedValues // image descriptor packed field values
  122. {
  123. ID_PACKED_LOCALCT,
  124. ID_PACKED_INTERLACE,
  125. ID_PACKED_SORT,
  126. ID_PACKED_LOCALCTSIZE
  127. };
  128. struct TGIFHeader // GIF header
  129. {
  130. char m_cSignature[3]; // Signature - Identifies the GIF Data Stream
  131. // This field contains the fixed value 'GIF'
  132. char m_cVersion[3]; // Version number. May be one of the following:
  133. // "87a" or "89a"
  134. };
  135. struct TGIFLSDescriptor // Logical Screen Descriptor
  136. {
  137. WORD m_wWidth; // 2 bytes. Logical screen width
  138. WORD m_wHeight; // 2 bytes. Logical screen height
  139. unsigned char m_cPacked; // packed field
  140. unsigned char m_cBkIndex; // 1 byte. Background color index
  141. unsigned char m_cPixelAspect; // 1 byte. Pixel aspect ratio
  142. inline int GetPackedValue(enum LSDPackedValues Value);
  143. };
  144. struct TGIFAppExtension // application extension block
  145. {
  146. unsigned char m_cExtIntroducer; // extension introducer (0x21)
  147. unsigned char m_cExtLabel; // app. extension label (0xFF)
  148. unsigned char m_cBlockSize; // fixed value of 11
  149. char m_cAppIdentifier[8]; // application identifier
  150. char m_cAppAuth[3]; // application authentication code
  151. };
  152. struct TGIFControlExt // graphic control extension block
  153. {
  154. unsigned char m_cExtIntroducer; // extension introducer (0x21)
  155. unsigned char m_cControlLabel; // control extension label (0xF9)
  156. unsigned char m_cBlockSize; // fixed value of 4
  157. unsigned char m_cPacked; // packed field
  158. WORD m_wDelayTime; // delay time
  159. unsigned char m_cTColorIndex; // transparent color index
  160. unsigned char m_cBlockTerm; // block terminator (0x00)
  161. public:
  162. inline int GetPackedValue(enum ControlExtValues Value);
  163. };
  164. struct TGIFCommentExt // comment extension block
  165. {
  166. unsigned char m_cExtIntroducer; // extension introducer (0x21)
  167. unsigned char m_cCommentLabel; // comment extension label (0xFE)
  168. };
  169. struct TGIFPlainTextExt // plain text extension block
  170. {
  171. unsigned char m_cExtIntroducer; // extension introducer (0x21)
  172. unsigned char m_cPlainTextLabel; // text extension label (0x01)
  173. unsigned char m_cBlockSize; // fixed value of 12
  174. WORD m_wLeftPos; // text grid left position
  175. WORD m_wTopPos; // text grid top position
  176. WORD m_wGridWidth; // text grid width
  177. WORD m_wGridHeight; // text grid height
  178. unsigned char m_cCellWidth; // character cell width
  179. unsigned char m_cCellHeight; // character cell height
  180. unsigned char m_cFgColor; // text foreground color index
  181. unsigned char m_cBkColor; // text background color index
  182. };
  183. struct TGIFImageDescriptor // image descriptor block
  184. {
  185. unsigned char m_cImageSeparator; // image separator byte (0x2C)
  186. WORD m_wLeftPos; // image left position
  187. WORD m_wTopPos; // image top position
  188. WORD m_wWidth; // image width
  189. WORD m_wHeight; // image height
  190. unsigned char m_cPacked; // packed field
  191. inline int GetPackedValue(enum IDPackedValues Value);
  192. };
  193. #pragma pack() // turn byte alignment off
  194. public:
  195. BOOL GetPaintRect(RECT *lpRect);
  196. BOOL SetPaintRect(const RECT *lpRect);
  197. CPictureEx();
  198. virtual ~CPictureEx();
  199. void Stop(); // stops animation
  200. void UnLoad(); // stops animation plus releases all resources
  201. BOOL IsGIF() const;
  202. BOOL IsPlaying() const;
  203. BOOL IsAnimatedGIF() const;
  204. SIZE GetSize() const;
  205. int GetFrameCount() const;
  206. COLORREF GetBkColor() const;
  207. void SetBkColor(COLORREF clr);
  208. // draws the picture (starts an animation thread if needed)
  209. // if an animation was previously stopped by Stop(),
  210. // continues it from the last displayed frame
  211. BOOL Draw();
  212. // loads a picture from a file
  213. // i.e. Load(_T("mypic.gif"));
  214. BOOL Load(LPCTSTR szFileName);
  215. // loads a picture from a global memory block (allocated by GlobalAlloc)
  216. // Warning: this function DOES NOT free the global memory, pointed to by hGlobal
  217. BOOL Load(HGLOBAL hGlobal, DWORD dwSize);
  218. // loads a picture from a program resource
  219. // i.e. Load(MAKEINTRESOURCE(IDR_MYPIC),_T("GIFTYPE"));
  220. BOOL Load(LPCTSTR szResourceName,LPCTSTR szResourceType);
  221. protected:
  222. #ifdef GIF_TRACING
  223. void EnumGIFBlocks();
  224. void WriteDataOnDisk(CString szFileName, HGLOBAL hData, DWORD dwSize);
  225. #endif // GIF_TRACING
  226. RECT m_PaintRect;
  227. SIZE m_PictureSize;
  228. COLORREF m_clrBackground;
  229. UINT m_nCurrFrame;
  230. UINT m_nDataSize;
  231. UINT m_nCurrOffset;
  232. UINT m_nGlobalCTSize;
  233. BOOL m_bIsGIF;
  234. BOOL m_bIsPlaying;
  235. volatile BOOL m_bExitThread;
  236. BOOL m_bIsInitialized;
  237. HDC m_hMemDC;
  238. HDC m_hDispMemDC;
  239. HBITMAP m_hDispMemBM;
  240. HBITMAP m_hDispOldBM;
  241. HBITMAP m_hBitmap;
  242. HBITMAP m_hOldBitmap;
  243. HANDLE m_hThread;
  244. HANDLE m_hExitEvent;
  245. IPicture * m_pPicture;
  246. TGIFHeader * m_pGIFHeader;
  247. unsigned char * m_pRawData;
  248. TGIFLSDescriptor * m_pGIFLSDescriptor;
  249. std::vector<TFrame> m_arrFrames;
  250. void ThreadAnimation();
  251. static UINT WINAPI _ThreadAnimation(LPVOID pParam);
  252. int GetNextBlockLen() const;
  253. BOOL SkipNextBlock();
  254. BOOL SkipNextGraphicBlock();
  255. BOOL PrepareDC(int nWidth, int nHeight);
  256. void ResetDataPointer();
  257. enum GIFBlockTypes GetNextBlock() const;
  258. UINT GetSubBlocksLen(UINT nStartingOffset) const;
  259. HGLOBAL GetNextGraphicBlock(UINT *pBlockLen, UINT *pDelay,
  260. SIZE *pBlockSize, SIZE *pBlockOffset, UINT *pDisposal);
  261. // Generated message map functions
  262. //{{AFX_MSG(CPictureEx)
  263. afx_msg void OnDestroy();
  264. afx_msg void OnPaint();
  265. //}}AFX_MSG
  266. DECLARE_MESSAGE_MAP()
  267. };
  268. #endif // !defined(AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_)