GifImage.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. #include "Stdafx.h"
  2. #include <OLECtl.h>
  3. #include "GIFImage.h"
  4. //////////////////////////////////////////////////////////////////////////
  5. //构造函数
  6. CGIFImage::CGIFImage()
  7. {
  8. //设置变量
  9. m_wImageWidth=0;
  10. m_wImageHeight=0;
  11. m_nCurrentFrame=0;
  12. m_crBackGroundColor=RGB(255,255,255);
  13. return;
  14. }
  15. //析构函数
  16. CGIFImage::~CGIFImage()
  17. {
  18. //释放图像
  19. DestroyImage();
  20. return;
  21. }
  22. //加载动画
  23. bool CGIFImage::LoadFromFile(LPCTSTR pszFileName)
  24. {
  25. //效验参数
  26. ASSERT(pszFileName!=NULL);
  27. if (pszFileName==NULL) return false;
  28. //释放图像
  29. DestroyImage();
  30. //打开文件
  31. CFile GIFFile;
  32. if (GIFFile.Open(pszFileName,CFile::modeRead|CFile::shareDenyWrite)==FALSE)
  33. {
  34. ASSERT(FALSE);
  35. return false;
  36. }
  37. //创建内存
  38. DWORD dwFileSize=(DWORD)GIFFile.GetLength();
  39. BYTE * pcbData=(BYTE *)GlobalAlloc(GMEM_FIXED,dwFileSize);
  40. //效验结果
  41. ASSERT(pcbData!=NULL);
  42. if (pcbData==NULL) return false;
  43. //读取文件
  44. GIFFile.Read(pcbData,dwFileSize);
  45. GIFFile.Close();
  46. //加载动画
  47. bool bSuccess=LoadFromMemroy(pcbData,dwFileSize);
  48. //释放内存
  49. GlobalFree(pcbData);
  50. return bSuccess;
  51. }
  52. //加载动画
  53. bool CGIFImage::LoadFromMemroy(BYTE * pcbData, LONG lDataSize)
  54. {
  55. //效验大小
  56. ASSERT(pcbData!=NULL);
  57. ASSERT(lDataSize>=sizeof(tagGIFHeader));
  58. if ((pcbData==NULL)||(lDataSize<sizeof(tagGIFHeader))) return false;
  59. //释放图像
  60. DestroyImage();
  61. //变量定义
  62. tagImageDataInfo ImageDataInfo;
  63. ZeroMemory(&ImageDataInfo,sizeof(ImageDataInfo));
  64. //设置变量
  65. ImageDataInfo.lDataSize=lDataSize;
  66. ImageDataInfo.cbImageDataBuffer=pcbData;
  67. //判断文件
  68. tagGIFHeader * pGIFHeader=(tagGIFHeader *)pcbData;
  69. if (memcmp(&pGIFHeader->cbSignature,"GIF",3)!= 0) return false;
  70. if ((memcmp(&pGIFHeader->cbVersion,"87a",3)!= 0)&&(memcmp(&pGIFHeader->cbVersion,"89a",3)!= 0)) return false;
  71. //逻辑屏幕
  72. tagGIFLSDescriptor * pGIFLSDescriptor=(tagGIFLSDescriptor *)(pcbData+sizeof(tagGIFHeader));
  73. if (GetPackedValue(pGIFLSDescriptor,LSD_PACKED_GLOBALCT)==1)
  74. {
  75. ImageDataInfo.lColorTableSize=3*(1<<(GetPackedValue(pGIFLSDescriptor,LSD_PACKED_GLOBALCTSIZE)+1));
  76. BYTE * pcbBkColor=pcbData+sizeof(tagGIFHeader)+sizeof(tagGIFLSDescriptor)+3*pGIFLSDescriptor->cbBkIndex;
  77. m_crBackGroundColor=RGB(pcbBkColor[0],pcbBkColor[1],pcbBkColor[2]);
  78. };
  79. //设置变量
  80. tagGIFFrameInfo GIFFrameInfo;
  81. enGIFBlockTypes GIFBlockTypes;
  82. m_GIFFrameInfoArray.RemoveAll();
  83. m_wImageWidth=pGIFLSDescriptor->wWidth;
  84. m_wImageHeight=pGIFLSDescriptor->wHeight;
  85. ImageDataInfo.lCurentPos=sizeof(tagGIFHeader)+sizeof(tagGIFLSDescriptor)+ImageDataInfo.lColorTableSize;
  86. //生成图帧
  87. do
  88. {
  89. //获取信息
  90. GIFBlockTypes=GetCurrentBlockType(ImageDataInfo);
  91. if ((GIFBlockTypes==BLOCK_UNKNOWN)||(GIFBlockTypes==BLOCK_TRAILER)) break;
  92. //变量定义
  93. LONG lStartPos=ImageDataInfo.lCurentPos;
  94. LONG lBlockSize=GetCurrentBlockSize(ImageDataInfo);
  95. //图形控制
  96. if (GIFBlockTypes==BLOCK_CONTROLEXT)
  97. {
  98. //变量定义
  99. tagGIFControlExt * pGIFControlExt=(tagGIFControlExt *)(pcbData+ImageDataInfo.lCurentPos);
  100. //获取信息
  101. GIFFrameInfo.nDelay=pGIFControlExt->wDelayTime;
  102. GIFFrameInfo.nDisposal=GetPackedValue(pGIFControlExt,GCX_PACKED_DISPOSAL);
  103. do
  104. {
  105. //切换区块
  106. if (SwitchNextBlock(ImageDataInfo)==false) return false;
  107. //获取类型
  108. GIFBlockTypes=GetCurrentBlockType(ImageDataInfo);
  109. if ((GIFBlockTypes==BLOCK_UNKNOWN)||(GIFBlockTypes==BLOCK_TRAILER)) return false;
  110. //类型判断
  111. lBlockSize+=GetCurrentBlockSize(ImageDataInfo);
  112. if ((GIFBlockTypes==BLOCK_IMAGE)||(GIFBlockTypes==BLOCK_PLAINTEXT)) break;
  113. } while (true);
  114. }
  115. else
  116. {
  117. GIFFrameInfo.nDisposal=0;
  118. GIFFrameInfo.nDelay=0xFFFF;
  119. }
  120. //图形类型
  121. if (GIFBlockTypes==BLOCK_IMAGE)
  122. {
  123. //变量定义
  124. tagGIFImageDescriptor * pGIFImageDescriptor=(tagGIFImageDescriptor *)(pcbData+ImageDataInfo.lCurentPos);
  125. //获取信息
  126. GIFFrameInfo.wImageWidth=pGIFImageDescriptor->wWidth;
  127. GIFFrameInfo.wImageHeight=pGIFImageDescriptor->wHeight;
  128. GIFFrameInfo.wXExcursion=pGIFImageDescriptor->wXExcursion;
  129. GIFFrameInfo.wYExcursion=pGIFImageDescriptor->wYExcursion;
  130. //申请内存
  131. LONG lAllocSize=sizeof(tagGIFHeader)+sizeof(tagGIFLSDescriptor)+ImageDataInfo.lColorTableSize+lBlockSize+1;
  132. BYTE * pcbGlobal=(BYTE *)GlobalAlloc(GMEM_FIXED,lAllocSize);
  133. if (pcbGlobal==NULL) break;
  134. //拷贝内存
  135. LONG lOffset=0L;
  136. CopyMemory(pcbGlobal,pcbData,sizeof(tagGIFHeader)+sizeof(tagGIFLSDescriptor)+ImageDataInfo.lColorTableSize);
  137. lOffset+=sizeof(tagGIFHeader)+sizeof(tagGIFLSDescriptor)+ImageDataInfo.lColorTableSize;
  138. CopyMemory(pcbGlobal+lOffset,pcbData+lStartPos,lBlockSize);
  139. lOffset+=lBlockSize;
  140. pcbGlobal[lOffset++]=0x3B;
  141. //创建图像
  142. IStream * pIStream=NULL;
  143. if (CreateStreamOnHGlobal(pcbGlobal,TRUE,&pIStream)!=S_OK)
  144. {
  145. ASSERT(FALSE);
  146. GlobalFree(pcbGlobal);
  147. break;
  148. };
  149. //加载图片
  150. if (OleLoadPicture(pIStream,lOffset,FALSE,IID_IPicture,(VOID * *)&GIFFrameInfo.pIFramePicture)!=S_OK)
  151. {
  152. ASSERT(FALSE);
  153. SafeRelease(pIStream);
  154. break;
  155. };
  156. //释放资源
  157. SafeRelease(pIStream);
  158. //加入图帧
  159. m_GIFFrameInfoArray.Add(GIFFrameInfo);
  160. }
  161. //切换区块
  162. if (SwitchNextBlock(ImageDataInfo)==false) break;
  163. } while (true);
  164. return true;
  165. }
  166. //加载动画
  167. bool CGIFImage::LoadFromResource(LPCTSTR pszResourceName, LPCTSTR pszResourceType)
  168. {
  169. //效验参数
  170. ASSERT(pszResourceName!=NULL);
  171. ASSERT(pszResourceType!=NULL);
  172. if ((pszResourceName==NULL)||(pszResourceType==NULL)) return false;
  173. //释放图像
  174. DestroyImage();
  175. //获取资源
  176. HRSRC hPicture=FindResource(AfxGetResourceHandle(),pszResourceName,pszResourceType);
  177. if (hPicture==NULL) return false;
  178. HGLOBAL hResData=LoadResource(AfxGetResourceHandle(),hPicture);
  179. if (hResData=NULL) return false;
  180. //创建内存
  181. DWORD dwResourceSize=SizeofResource(AfxGetResourceHandle(),hPicture);
  182. BYTE * pcbData=(BYTE *)GlobalAlloc(GMEM_FIXED,dwResourceSize);
  183. if (pcbData==NULL)
  184. {
  185. FreeResource(hResData);
  186. return false;
  187. }
  188. //锁定资源
  189. BYTE * pcbSrc=(BYTE *)LockResource(hResData);
  190. if (pcbSrc==NULL)
  191. {
  192. GlobalFree(pcbData);
  193. FreeResource(hResData);
  194. return false;
  195. }
  196. //拷贝数据
  197. CopyMemory(pcbData,pcbSrc,dwResourceSize);
  198. FreeResource(hResData);
  199. //加载动画
  200. bool bSuccess=LoadFromMemroy(pcbData,dwResourceSize);
  201. //释放内存
  202. GlobalFree(pcbData);
  203. return bSuccess;
  204. }
  205. //是否加载
  206. bool CGIFImage::IsNull()
  207. {
  208. return (m_GIFFrameInfoArray.GetCount()==0);
  209. }
  210. //释放图像
  211. VOID CGIFImage::DestroyImage()
  212. {
  213. //设置变量
  214. m_wImageWidth=0;
  215. m_wImageHeight=0;
  216. m_nCurrentFrame=0;
  217. m_crBackGroundColor=RGB(255,255,255);
  218. //释放图帧
  219. if (m_GIFFrameInfoArray.GetCount()>0)
  220. {
  221. for (INT_PTR i=0;i<m_GIFFrameInfoArray.GetCount();i++)
  222. {
  223. //获取对象
  224. tagGIFFrameInfo * pGIFFrameInfo=&m_GIFFrameInfoArray[i];
  225. //释放接口
  226. SafeRelease(pGIFFrameInfo->pIFramePicture);
  227. }
  228. //删除数组
  229. m_GIFFrameInfoArray.RemoveAll();
  230. }
  231. return;
  232. }
  233. //当前图像
  234. tagGIFFrameInfo * CGIFImage::GetCurrentFrame()
  235. {
  236. //状态效验
  237. ASSERT(IsNull()==false);
  238. if (IsNull()==true) return NULL;
  239. return &m_GIFFrameInfoArray[m_nCurrentFrame];
  240. }
  241. //绘画图像
  242. VOID CGIFImage::DrawImageFrame(CDC * pDC, INT nXPos, INT nYPos)
  243. {
  244. //绘画图片
  245. DrawImageFrame(pDC,nXPos,nYPos,m_nCurrentFrame);
  246. //调整图帧
  247. m_nCurrentFrame=((m_nCurrentFrame+1)==m_GIFFrameInfoArray.GetCount())?0L:(m_nCurrentFrame+1L);
  248. return;
  249. }
  250. //绘画图像
  251. VOID CGIFImage::DrawImageFrame(CDC * pDC, INT nXPos, INT nYPos, INT_PTR nFrameIndex)
  252. {
  253. //获取数据
  254. ASSERT(nFrameIndex<m_GIFFrameInfoArray.GetCount());
  255. tagGIFFrameInfo * pGIFFrameInfo=&m_GIFFrameInfoArray[nFrameIndex];
  256. //获取大小
  257. OLE_XSIZE_HIMETRIC hmWidth=0L;
  258. OLE_YSIZE_HIMETRIC hmHeight=0L;
  259. pGIFFrameInfo->pIFramePicture->get_Width(&hmWidth);
  260. pGIFFrameInfo->pIFramePicture->get_Height(&hmHeight);
  261. //绘画图片
  262. pGIFFrameInfo->pIFramePicture->Render(pDC->m_hDC,nXPos+pGIFFrameInfo->wXExcursion,nYPos+pGIFFrameInfo->wYExcursion,
  263. pGIFFrameInfo->wImageWidth,pGIFFrameInfo->wImageHeight,0,hmHeight,hmWidth,-hmHeight,NULL);
  264. return;
  265. }
  266. //区块长度
  267. LONG CGIFImage::GetCurrentBlockSize(tagImageDataInfo & ImageDataInfo)
  268. {
  269. enGIFBlockTypes GIFBlockTypes=GetCurrentBlockType(ImageDataInfo);
  270. switch (GIFBlockTypes)
  271. {
  272. case BLOCK_UNKNOWN: { return -1; }
  273. case BLOCK_TRAILER: { return 1; }
  274. case BLOCK_APPEXT:
  275. {
  276. LONG lSubSize=GetSubBlockSize(ImageDataInfo,ImageDataInfo.lCurentPos+sizeof(tagGIFAppExtension));
  277. return sizeof(tagGIFAppExtension)+lSubSize;
  278. }
  279. case BLOCK_COMMEXT:
  280. {
  281. LONG lSubSize=GetSubBlockSize(ImageDataInfo,ImageDataInfo.lCurentPos+sizeof(tagGIFCommentExt));
  282. return sizeof(tagGIFCommentExt)+lSubSize;
  283. }
  284. case BLOCK_CONTROLEXT:
  285. {
  286. return sizeof(tagGIFControlExt);
  287. }
  288. case BLOCK_PLAINTEXT:
  289. {
  290. LONG lSubSize=GetSubBlockSize(ImageDataInfo,ImageDataInfo.lCurentPos+sizeof(tagGIFPlainTextExt));
  291. return sizeof(tagGIFPlainTextExt)+lSubSize;
  292. }
  293. case BLOCK_IMAGE:
  294. {
  295. INT nLCTSize=0;
  296. tagGIFImageDescriptor * pGIFImageDescriptor=(tagGIFImageDescriptor *)(ImageDataInfo.cbImageDataBuffer+ImageDataInfo.lCurentPos);
  297. if (GetPackedValue(pGIFImageDescriptor,ID_PACKED_LOCALCT)==1)
  298. {
  299. nLCTSize=(1<<(GetPackedValue(pGIFImageDescriptor,ID_PACKED_LOCALCTSIZE)+1))*3;
  300. }
  301. LONG lSubSize=GetSubBlockSize(ImageDataInfo,ImageDataInfo.lCurentPos+sizeof(tagGIFImageDescriptor)+nLCTSize+1);
  302. return sizeof(tagGIFImageDescriptor)+nLCTSize+lSubSize+1;
  303. }
  304. };
  305. return 0;
  306. }
  307. //获取类型
  308. enGIFBlockTypes CGIFImage::GetCurrentBlockType(tagImageDataInfo & ImageDataInfo)
  309. {
  310. switch (ImageDataInfo.cbImageDataBuffer[ImageDataInfo.lCurentPos])
  311. {
  312. case 0x21:
  313. {
  314. switch (ImageDataInfo.cbImageDataBuffer[ImageDataInfo.lCurentPos+1])
  315. {
  316. case 0x01: { return BLOCK_PLAINTEXT; }
  317. case 0xF9: { return BLOCK_CONTROLEXT; }
  318. case 0xFE: { return BLOCK_COMMEXT; }
  319. case 0xFF: { return BLOCK_APPEXT; }
  320. };
  321. break;
  322. }
  323. case 0x3B: { return BLOCK_TRAILER; }
  324. case 0x2C: { return BLOCK_IMAGE; }
  325. }
  326. return BLOCK_UNKNOWN;
  327. }
  328. //区块长度
  329. LONG CGIFImage::GetSubBlockSize(tagImageDataInfo & ImageDataInfo,LONG lBlockPos)
  330. {
  331. LONG lBlockLength=0;
  332. while (ImageDataInfo.cbImageDataBuffer[lBlockPos]!=0)
  333. {
  334. lBlockLength+=ImageDataInfo.cbImageDataBuffer[lBlockPos]+1;
  335. lBlockPos+=ImageDataInfo.cbImageDataBuffer[lBlockPos]+1;
  336. };
  337. return lBlockLength+1;
  338. }
  339. //切换区块
  340. bool CGIFImage::SwitchNextBlock(tagImageDataInfo & ImageDataInfo)
  341. {
  342. LONG lBlockSize=GetCurrentBlockSize(ImageDataInfo);
  343. if ((lBlockSize<=0)||((ImageDataInfo.lCurentPos+lBlockSize)>ImageDataInfo.lDataSize)) return false;
  344. ImageDataInfo.lCurentPos+=lBlockSize;
  345. return true;
  346. }
  347. //获取数值
  348. INT CGIFImage::GetPackedValue(const tagGIFControlExt * pGIFControlExt, enum enControlExtValues Value)
  349. {
  350. switch (Value)
  351. {
  352. case GCX_PACKED_DISPOSAL: //处置方法
  353. {
  354. return (pGIFControlExt->cbPacked&28)>>2;
  355. }
  356. case GCX_PACKED_USERINPUT: //输入标志
  357. {
  358. return (pGIFControlExt->cbPacked&2)>>1;
  359. }
  360. case GCX_PACKED_TRANSPCOLOR: //透明标志
  361. {
  362. return pGIFControlExt->cbPacked&1;
  363. }
  364. };
  365. ASSERT(FALSE);
  366. return 0;
  367. }
  368. //获取数值
  369. INT CGIFImage::GetPackedValue(const tagGIFImageDescriptor * pGIFImageDescriptor, enum enIDPackedValues Value)
  370. {
  371. switch (Value)
  372. {
  373. case ID_PACKED_LOCALCT: //颜色标志
  374. {
  375. return pGIFImageDescriptor->cbPacked>>7;
  376. }
  377. case ID_PACKED_INTERLACE: //交织标志
  378. {
  379. return (pGIFImageDescriptor->cbPacked&0x40)>>6;
  380. }
  381. case ID_PACKED_SORT: //分类标志
  382. {
  383. return (pGIFImageDescriptor->cbPacked&0x20)>>5;
  384. }
  385. case ID_PACKED_LOCALCTSIZE: //颜色大小
  386. {
  387. return pGIFImageDescriptor->cbPacked&7;
  388. }
  389. };
  390. ASSERT(FALSE);
  391. return 0;
  392. }
  393. //获取数值
  394. INT CGIFImage::GetPackedValue(const tagGIFLSDescriptor * pGIFLSDescriptor, enum enLSDPackedValues Value)
  395. {
  396. switch (Value)
  397. {
  398. case LSD_PACKED_GLOBALCT: //颜色标志
  399. {
  400. return pGIFLSDescriptor->cbPacked>>7;
  401. }
  402. case LSD_PACKED_CRESOLUTION: //颜色深度
  403. {
  404. return ((pGIFLSDescriptor->cbPacked&0x70)>>4)+1;
  405. }
  406. case LSD_PACKED_SORT: //分类标志
  407. {
  408. return (pGIFLSDescriptor->cbPacked&8)>>3;
  409. }
  410. case LSD_PACKED_GLOBALCTSIZE: //全局颜色
  411. {
  412. return pGIFLSDescriptor->cbPacked & 0x07;
  413. }
  414. };
  415. ASSERT(FALSE);
  416. return 0;
  417. }
  418. //////////////////////////////////////////////////////////////////////////