GIFAPI.CPP
上传用户:gzboli
上传日期:2013-04-10
资源大小:471k
文件大小:40k
源码类别:

图片显示

开发平台:

Visual C++

  1. // ************************************************************************
  2. //  文件名:GIFAPI.cpp
  3. //
  4. //  GIF(Graphics Interchange Format) API函数库:
  5. //
  6. //  DIBToGIF()          - 将指定的DIB对象(< 256色)保存为GIF文件
  7. //  EncodeGIF() - 对指定图像进行GIF_LZW编码
  8. //  WriteCodeGIF() - 输出一个编码
  9. //  ReadGIF()           - 读取GIF文件
  10. //  DecodeGIF()     - 对GIF_LZW编码结果进行解码
  11. //  ReadSrcDataGIF()       - 读取GIF_LZW编码
  12. //
  13. // ************************************************************************
  14. #include "stdafx.h"
  15. #include "GIFAPI.h"
  16. #include <io.h>
  17. #include <errno.h>
  18. #include <math.h>
  19. #include <direct.h>
  20. /*************************************************************************
  21.  *
  22.  * 函数名称:
  23.  *   DIBToGIF()
  24.  *
  25.  * 参数:
  26.  *   LPSTR lpDIB        - 指向DIB对象的指针
  27.  *   CFile& file        - 要保存的文件
  28.  *   BOOL bInterlace - 是否按照交错方式保存
  29.  *
  30.  * 返回值:
  31.  *   BOOL               - 成功返回True,否则返回False。
  32.  *
  33.  * 说明:
  34.  *   该函数将指定的DIB对象(< 256色)保存为GIF文件。
  35.  *
  36.  *************************************************************************/
  37. BOOL SaveGIF(LPCSTR lpszFileName, LPSTR lpDIB, BOOL bInterlace)
  38. {
  39. // 循环变量
  40. WORD i;
  41. WORD j;
  42. // DIB高度
  43. WORD wHeight;
  44. // DIB宽度
  45. WORD wWidth;
  46. // 指向DIB象素指针
  47. LPSTR   lpDIBBits;
  48. // GIF文件头
  49. GIFHEADER          GIFH;
  50. // GIF逻辑屏幕描述块
  51. GIFSCRDESC         GIFS;
  52. // GIF图像描述块
  53. GIFIMAGE           GIFI;
  54. // GIF编码参数
  55. GIFCONTROLPARAM    GIFControlParam;
  56. // 颜色数目
  57. WORD               wColors;
  58. // 每行字节数
  59. WORD               wWidthBytes;
  60. // 调色板
  61. BYTE               byGIF_Pal[768];
  62. // 字节变量
  63. BYTE               byChar;
  64. // 指向BITMAPINFO结构的指针(Win3.0)
  65. LPBITMAPINFO    lpbmi;
  66. // 指向BITMAPCOREINFO结构的指针
  67. LPBITMAPCOREINFO   lpbmc;
  68. // 表明是否是Win3.0 DIB的标记
  69. BOOL    bWinStyleDIB;
  70. // open file
  71. CFile file;
  72. if (! file.Open(lpszFileName, CFile::modeCreate | CFile::modeWrite))
  73. return FALSE;
  74. // 获取DIB高度
  75. wHeight = (WORD) DIBHeight(lpDIB);
  76. // 获取DIB宽度
  77. wWidth  = (WORD) DIBWidth(lpDIB);
  78. // 找到DIB图像象素起始位置
  79. lpDIBBits = (LPSTR)FindDIBBits((LPSTR)lpDIB);
  80. // 给GIFControlParam结构赋值
  81. GIFControlParam.wWidth     = wWidth;
  82. GIFControlParam.wDepth     = wHeight;
  83. GIFControlParam.wBits      = DIBBitCount(lpDIB);
  84. GIFControlParam.wLineBytes = (WORD)BYTE_WBYTES((DWORD)GIFControlParam.wWidth *
  85.    (DWORD)GIFControlParam.wBits);
  86. // 计算每行字节数
  87. wWidthBytes = (WORD)DWORD_WBYTES(wWidth * (DWORD)GIFControlParam.wBits);
  88. // 计算颜色数目
  89. wColors     = 1 << GIFControlParam.wBits;
  90. // 获取指向BITMAPINFO结构的指针(Win3.0)
  91. lpbmi = (LPBITMAPINFO)lpDIB;
  92. // 获取指向BITMAPCOREINFO结构的指针
  93. lpbmc = (LPBITMAPCOREINFO)lpDIB;
  94. // 判断是否是WIN3.0的DIB
  95. bWinStyleDIB = IS_WIN30_DIB(lpDIB);
  96. // 给调色板赋值
  97. if (bWinStyleDIB)
  98. {
  99. j = 0;
  100. for (i = 0; i < wColors; i++)
  101. {
  102. // 读取红色分量
  103. byGIF_Pal[j++] = lpbmi->bmiColors[i].rgbRed;
  104. // 读取绿色分量
  105. byGIF_Pal[j++] = lpbmi->bmiColors[i].rgbGreen;
  106. // 读取蓝色分量
  107. byGIF_Pal[j++] = lpbmi->bmiColors[i].rgbBlue;
  108. }
  109. }
  110. else
  111. {
  112. j = 0;
  113. for (i = 0; i < wColors; i++)
  114. {
  115. // 读取红色分量
  116. byGIF_Pal[j++] = lpbmc->bmciColors[i].rgbtRed;
  117. // 读取绿色分量
  118. byGIF_Pal[j++] = lpbmc->bmciColors[i].rgbtGreen;
  119. // 读取红色分量
  120. byGIF_Pal[j++] = lpbmc->bmciColors[i].rgbtBlue;
  121. }
  122. }
  123. ////////////////////////////////////////////////////////////////////////////////////////
  124. // 开始写GIF文件
  125. // 写GIF文件头
  126. GIFH.bySignature[0] = 'G';
  127. GIFH.bySignature[1] = 'I';
  128. GIFH.bySignature[2] = 'F';
  129. GIFH.byVersion[0]='8';
  130. GIFH.byVersion[1]='9';
  131. GIFH.byVersion[2]='a';
  132. file.Write((LPSTR)&GIFH, 6);
  133. // 写GIF逻辑屏幕描述块
  134. GIFS.wWidth               = GIFControlParam.wWidth;
  135. GIFS.wDepth               = GIFControlParam.wDepth;
  136. GIFS.GlobalFlag.PalBits   = (BYTE)(GIFControlParam.wBits - 1);
  137. GIFS.GlobalFlag.SortFlag  = 0x00;
  138. GIFS.GlobalFlag.ColorRes  = (BYTE)(GIFControlParam.wBits - 1);
  139. GIFS.GlobalFlag.GlobalPal = 0x01;
  140. GIFS.byBackground         = 0x00;
  141. GIFS.byAspect             = 0x00;
  142. file.Write((LPSTR)&GIFS, 7);
  143. // 写GIF全局调色板
  144. file.Write((LPSTR)byGIF_Pal,(wColors*3));
  145. // 写GIF图像描述间隔符
  146. byChar      = 0x2C;
  147. file.Write((LPSTR)&byChar,1);
  148. // 写GIF图像描述块
  149. GIFI.wLeft                = 0;
  150. GIFI.wTop                 = 0;
  151. GIFI.wWidth               = GIFControlParam.wWidth;
  152. GIFI.wDepth               = GIFControlParam.wDepth;
  153. GIFI.LocalFlag.PalBits    = 0x00;
  154. GIFI.LocalFlag.Reserved   = 0x00;
  155. GIFI.LocalFlag.SortFlag   = 0x00;
  156. GIFI.LocalFlag.Interlace  = (BYTE)(bInterlace ? 0x01 : 0x00);
  157. GIFI.LocalFlag.LocalPal   = 0x00;
  158. file.Write((LPSTR)&GIFI, 9);
  159. // 写GIF图像压缩数据
  160. HANDLE hSrcBuff = GlobalAlloc(GHND,(DWORD)MAX_BUFF_SIZE);
  161. GIFControlParam.lpDataBuff = (LPSTR)GlobalLock(hSrcBuff);
  162. GIFControlParam.lpEndBuff  = GIFControlParam.lpDataBuff;
  163. GIFControlParam.dwTempCode = 0UL;
  164. GIFControlParam.wByteCnt   = 0;
  165. GIFControlParam.wBlockNdx  = 1;
  166. GIFControlParam.byLeftBits = 0x00;
  167. // 进行GIF_LZW编码
  168. EncodeGIF(file, lpDIBBits, &GIFControlParam,wWidthBytes, bInterlace);
  169. // 判断是否编码成功
  170. if (GIFControlParam.wByteCnt)
  171. {
  172. // 写入文件
  173. file.Write(GIFControlParam.lpDataBuff, GIFControlParam.wByteCnt);
  174. }
  175. // 释放内存
  176. GlobalUnlock(hSrcBuff);
  177. GlobalFree(hSrcBuff);
  178. // 写GIF Block Terminator
  179. byChar   = 0x00;
  180. file.Write((LPSTR)&byChar,1);
  181. // 写GIF文件结尾块
  182. byChar   = 0x3B;
  183. file.Write((LPSTR)&byChar,1);
  184. // 返回
  185. return TRUE;
  186. }
  187. /*************************************************************************
  188.  *
  189.  * 函数名称:
  190.  *   EncodeGIF()
  191.  *
  192.  * 参数:
  193.  *   LPSTR lpDIBBits - 指向源DIB图像指针
  194.  *   CFile& file - 要保存的文件
  195.  *   LPGIFCONTROLPARAM lpGIFControlParam - 指向GIFCONTROLPARAM结构的指针
  196.  *  WORD wWidthBytes - 每行图像字节数
  197.  *  BOOL bInterlace - 是否按照交错方式保存
  198.  *
  199.  * 返回值:
  200.  *   无
  201.  *
  202.  * 说明:
  203.  *   该函数对指定图像进行GIF_LZW编码。
  204.  *
  205.  *************************************************************************/
  206. void EncodeGIF(CFile& file, LPSTR lpDIBBits, 
  207.   LPGIFCONTROLPARAM lpGIFControlParam,WORD wWidthBytes, BOOL bInterlace)
  208. {
  209. // 内存分配句柄
  210. HANDLE hTableNdx;
  211. HANDLE hPrefix;
  212. HANDLE hSuffix;
  213. // 指向字串表指针
  214. LPWORD lpwTableNdx;
  215. // 用于字串表搜索的索引
  216. LPWORD lpwPrefix;
  217. LPBYTE lpbySuffix;
  218. // 指向当前编码像素的指针
  219. LPSTR  lpImage;
  220. // 计算当前数据图像的偏移量
  221. DWORD  dwDataNdx;
  222. // LZW_CLEAR
  223. WORD   wLZW_CLEAR;
  224. // LZW_EOI
  225. WORD   wLZW_EOI;
  226. // LZW_MinCodeLen
  227. BYTE   byLZW_MinCodeLen;
  228. // 字串表索引
  229. WORD   wPreTableNdx;
  230. WORD   wNowTableNdx;
  231. WORD   wTopTableNdx;
  232. // 哈希表索引
  233. WORD   wHashNdx;
  234. WORD   wHashGap;
  235. WORD   wPrefix;
  236. WORD   wShiftBits;
  237. // 当前图像的行数
  238. WORD   wRowNum;
  239. WORD   wWidthCnt;
  240. // 循环变量
  241. WORD   wi;
  242. WORD   wj;
  243. // 交错方式存储时每次增加的行数
  244. WORD   wIncTable[5]  = { 8,8,4,2,0 }; 
  245. // 交错方式存储时起始行数
  246. WORD   wBgnTable[5]  = { 0,4,2,1,0 }; 
  247. BOOL   bStart;
  248. BYTE   bySuffix;
  249. BYTE   bySubBlock[256];
  250. BYTE   byCurrentBits;
  251. BYTE   byMask;
  252. BYTE   byChar;
  253. BYTE   byPass;
  254. // 临时字节变量
  255. BYTE   byTemp;
  256. // 给字串表分配内存
  257. hTableNdx        = GlobalAlloc(GHND,(DWORD)(MAX_HASH_SIZE<<1));
  258. hPrefix          = GlobalAlloc(GHND,(DWORD)(MAX_HASH_SIZE<<1));
  259. hSuffix          = GlobalAlloc(GHND,(DWORD)MAX_HASH_SIZE);
  260. // 锁定内存
  261. lpwTableNdx      = (LPWORD)GlobalLock(hTableNdx);
  262. lpwPrefix        = (LPWORD)GlobalLock(hPrefix);
  263. lpbySuffix       = (LPBYTE)GlobalLock(hSuffix);
  264. // 计算LZW_MinCodeLen
  265. byLZW_MinCodeLen = (BYTE)((lpGIFControlParam->wBits>1) ? lpGIFControlParam->wBits : 0x02);
  266. // 写GIF LZW最小代码大小
  267. file.Write((LPSTR)&byLZW_MinCodeLen,1);
  268. wRowNum          = 0;
  269. bStart           = TRUE;
  270. byPass           = 0x00;
  271. // 计算LZW_CLEAR
  272. wLZW_CLEAR       = 1 << byLZW_MinCodeLen;
  273. // 计算LZW_EOI
  274. wLZW_EOI         = wLZW_CLEAR + 1;
  275. // 初始化字串表
  276. byCurrentBits    = byLZW_MinCodeLen + (BYTE)0x01;
  277. wNowTableNdx     = wLZW_CLEAR + 2;
  278. wTopTableNdx     = 1 << byCurrentBits;
  279. for(wi=0; wi<MAX_HASH_SIZE; wi++)
  280. {
  281. // 初始化为0xFFFF
  282. *(lpwTableNdx+wi) = 0xFFFF;
  283. }
  284. // 输出LZW_CLEAR
  285. WriteCodeGIF(file, wLZW_CLEAR, (LPSTR)bySubBlock,
  286.   &byCurrentBits, lpGIFControlParam);
  287. // 逐行编码
  288. for(wi=0; wi<lpGIFControlParam->wDepth; wi++)
  289. {
  290. // 计算当前偏移量
  291. dwDataNdx  = (DWORD)(lpGIFControlParam->wDepth - 1 - wRowNum) * (DWORD)wWidthBytes;
  292. // 指向当前行图像的指针
  293. lpImage    = (LPSTR) (((BYTE*)lpDIBBits) + dwDataNdx);
  294. wWidthCnt  = 0;
  295. wShiftBits = 8 - lpGIFControlParam->wBits;
  296. byMask     = (BYTE)((lpGIFControlParam->wBits==1) ? 0x80 : 0xF0);
  297. if (bStart)
  298. {
  299. // 判断是否是256色位图(一个像素一字节)
  300. if (lpGIFControlParam->wBits==8)
  301. {
  302. // 256色,直接赋值即可
  303. byTemp      = *lpImage++;
  304. }
  305. else
  306. {
  307. // 非256色,需要移位获取像素值
  308. wShiftBits  = 8 - lpGIFControlParam->wBits;
  309. byMask      = (BYTE)((lpGIFControlParam->wBits==1) ? 0x80 : 0xF0);
  310. byTemp      = (BYTE)((*lpImage & byMask) >> wShiftBits);
  311. byMask    >>= lpGIFControlParam->wBits;
  312. wShiftBits -= lpGIFControlParam->wBits;
  313. }
  314. wPrefix    = (WORD)byTemp;
  315. bStart     = FALSE;
  316. wWidthCnt ++;
  317. }
  318. // 每行编码
  319. while(wWidthCnt < lpGIFControlParam->wWidth)
  320. {
  321. // 判断是否是256色位图(一个像素一字节)
  322. if (lpGIFControlParam->wBits==8)
  323. {
  324. // 256色,直接赋值即可
  325. byTemp = *lpImage++;
  326. }
  327. else
  328. {
  329. // 非256色,需要移位获取像素值
  330. byChar = *lpImage;
  331. byTemp = (BYTE)((byChar & byMask) >> wShiftBits);
  332. if (wShiftBits)
  333. {
  334. byMask    >>= lpGIFControlParam->wBits;
  335. wShiftBits -= lpGIFControlParam->wBits;
  336. }
  337. else
  338. {
  339. wShiftBits  = 8 - lpGIFControlParam->wBits;
  340. byMask      = (BYTE)((lpGIFControlParam->wBits==1) ? 0x80 : 0xF0);
  341. lpImage    ++;
  342. }
  343. }
  344. bySuffix   = byTemp;
  345. wWidthCnt ++;
  346. // 查找当前字符串是否存在于字串表中
  347. wHashNdx = wPrefix ^ ((WORD)bySuffix << 4);
  348. wHashGap = (wHashNdx ? (MAX_HASH_SIZE - wHashNdx) : 1);
  349. // 判断当前字符串是否在字串表中
  350. while(TRUE)
  351. {
  352. // 当前字符串不在字串表中
  353. if (*(lpwTableNdx + wHashNdx) == 0xFFFF)
  354. {
  355.    // 新字符串,退出循环
  356.    break;
  357. }
  358. // 判断是否找到该字符串
  359. if ((*(lpwPrefix+wHashNdx)  == wPrefix) &&
  360. (*(lpbySuffix+wHashNdx) == bySuffix))
  361. {
  362. // 找到,退出循环
  363. break;
  364. }
  365. // 第二哈希表
  366. if (wHashNdx < wHashGap)
  367. {
  368. wHashNdx += MAX_HASH_SIZE;
  369. }
  370. wHashNdx -= wHashGap;
  371. }
  372. // 判断是否是新字符串
  373. if (*(lpwTableNdx+wHashNdx) != 0xFFFF)
  374. {
  375. // 不是新字符串
  376. wPrefix = *(lpwTableNdx + wHashNdx);
  377.  }
  378.  else
  379.  {
  380. // 新字符串
  381. // 输出该编码
  382. WriteCodeGIF(file,wPrefix,(LPSTR)bySubBlock,
  383.    &byCurrentBits,lpGIFControlParam);
  384. // 将该新字符串添加到字串表中
  385. wPreTableNdx = wNowTableNdx;
  386. // 判断是否达到最大字串表大小
  387. if (wNowTableNdx < MAX_TABLE_SIZE)
  388. {
  389. *(lpwTableNdx+wHashNdx) = wNowTableNdx++;
  390. *(lpwPrefix+wHashNdx)   = wPrefix;
  391. *(lpbySuffix+wHashNdx)  = bySuffix;
  392. }
  393. if (wPreTableNdx == wTopTableNdx)
  394. {
  395. if (byCurrentBits<12)
  396. {
  397. byCurrentBits ++;
  398. wTopTableNdx <<= 1;
  399. }
  400. else
  401. {
  402. // 字串表到达最大长度
  403. // 输出LZW_CLEAR
  404. WriteCodeGIF(file, wLZW_CLEAR, (LPSTR)bySubBlock,
  405.  &byCurrentBits,lpGIFControlParam);
  406. // 重新初始化字串表
  407. byCurrentBits    = byLZW_MinCodeLen + (BYTE)0x01;
  408. wLZW_CLEAR       = 1 << byLZW_MinCodeLen;
  409. wLZW_EOI         = wLZW_CLEAR + 1;
  410. wNowTableNdx     = wLZW_CLEAR + 2;
  411. wTopTableNdx     = 1 << byCurrentBits;
  412. for(wj=0;wj<MAX_HASH_SIZE;wj++)
  413. {
  414. // 初始化为0xFFFF
  415. *(lpwTableNdx+wj) = 0xFFFF;
  416. }
  417. }
  418. }
  419. wPrefix = (WORD)bySuffix;
  420. }
  421. }
  422. // 判断是否是交错方式
  423. if (bInterlace)
  424. {
  425. // 交错方式,计算下一行位置
  426. wRowNum += wIncTable[byPass];
  427. if (wRowNum>=lpGIFControlParam->wDepth)
  428. {
  429. byPass ++;
  430. wRowNum = wBgnTable[byPass];
  431. }
  432. }
  433. else
  434. {
  435. // 非交错方式,直接将行数加一即可
  436. wRowNum ++;
  437. }
  438. }
  439. // 输出当前编码
  440. WriteCodeGIF(file, wPrefix, (LPSTR)bySubBlock,
  441.   &byCurrentBits,lpGIFControlParam);
  442. // 输出LZW_EOI
  443. WriteCodeGIF(file,wLZW_EOI,(LPSTR)bySubBlock,
  444.   &byCurrentBits,lpGIFControlParam);
  445. if (lpGIFControlParam->byLeftBits)
  446. {
  447. // 加入该字符
  448. bySubBlock[lpGIFControlParam->wBlockNdx++] = (BYTE)lpGIFControlParam->dwTempCode;
  449. // 判断是否超出MAX_SUBBLOCK_SIZE
  450. if (lpGIFControlParam->wBlockNdx > MAX_SUBBLOCK_SIZE)
  451. {
  452. // 判断wByteCnt + 256是否超过MAX_BUFF_SIZE
  453. if ((lpGIFControlParam->wByteCnt + 256) >= MAX_BUFF_SIZE)
  454. {
  455. // 输出
  456. file.Write(lpGIFControlParam->lpDataBuff,
  457.   lpGIFControlParam->wByteCnt);
  458. lpGIFControlParam->lpEndBuff = lpGIFControlParam->lpDataBuff;
  459. lpGIFControlParam->wByteCnt  = 0;
  460. }
  461. bySubBlock[0]           = (BYTE)(lpGIFControlParam->wBlockNdx - 1);
  462. memcpy(lpGIFControlParam->lpEndBuff,(LPSTR)bySubBlock,lpGIFControlParam->wBlockNdx);
  463. lpGIFControlParam->lpEndBuff   += lpGIFControlParam->wBlockNdx;
  464. lpGIFControlParam->wByteCnt    += lpGIFControlParam->wBlockNdx;
  465. lpGIFControlParam->wBlockNdx    = 1;
  466. }
  467. lpGIFControlParam->dwTempCode = 0UL;
  468. lpGIFControlParam->byLeftBits = 0x00;
  469. }
  470. if (lpGIFControlParam->wBlockNdx > 1)
  471. {
  472. // 判断wByteCnt + 256是否超过MAX_BUFF_SIZE
  473. if ((lpGIFControlParam->wByteCnt + 256) >= MAX_BUFF_SIZE)
  474. {
  475. // 输出
  476. file.Write(lpGIFControlParam->lpDataBuff,
  477.    lpGIFControlParam->wByteCnt);
  478. lpGIFControlParam->lpEndBuff = lpGIFControlParam->lpDataBuff;
  479. lpGIFControlParam->wByteCnt  = 0;
  480. }
  481. bySubBlock[0]           = (BYTE)(lpGIFControlParam->wBlockNdx - 1);
  482. memcpy(lpGIFControlParam->lpEndBuff,(LPSTR)bySubBlock,lpGIFControlParam->wBlockNdx);
  483. lpGIFControlParam->lpEndBuff   += lpGIFControlParam->wBlockNdx;
  484. lpGIFControlParam->wByteCnt    += lpGIFControlParam->wBlockNdx;
  485. lpGIFControlParam->wBlockNdx    = 1;
  486. }
  487. // 解除锁定
  488. GlobalUnlock(hTableNdx);
  489. GlobalUnlock(hPrefix);
  490. GlobalUnlock(hSuffix);
  491. // 释放内存
  492. GlobalFree(hTableNdx);
  493. GlobalFree(hPrefix);
  494. GlobalFree(hSuffix);
  495. // 退出
  496. return;
  497. }
  498. /*************************************************************************
  499.  *
  500.  * 函数名称:
  501.  *   WriteCodeGIF()
  502.  *
  503.  * 参数:
  504.  *   CFile& file - 要保存的文件
  505.  *  WORD wCode - 要添加的编码
  506.  *   LPSTR lpSubBlock - 子块
  507.  *  LPBYTE lpbyCurrentBits - 当前位数
  508.  *  LPGIFCONTROLPARAM lpGIFControlParam - 指向GIFCONTROLPARAM结构的指针
  509.  *
  510.  * 返回值:
  511.  *   无
  512.  *
  513.  * 说明:
  514.  *   该函数用来输出一个编码。
  515.  *
  516.  *************************************************************************/
  517. void WriteCodeGIF(CFile& file, WORD wCode, LPSTR lpSubBlock,
  518.                               LPBYTE lpbyCurrentBits,LPGIFCONTROLPARAM lpGIFControlParam)
  519. {
  520. // 输出该编码
  521. lpGIFControlParam->dwTempCode |= ((DWORD)wCode << lpGIFControlParam->byLeftBits);
  522. lpGIFControlParam->byLeftBits += (*lpbyCurrentBits);
  523. while(lpGIFControlParam->byLeftBits >= 0x08)
  524. {
  525. lpSubBlock[lpGIFControlParam->wBlockNdx++] = (BYTE)lpGIFControlParam->dwTempCode;
  526.       
  527. // 判断是否超出MAX_SUBBLOCK_SIZE
  528. if (lpGIFControlParam->wBlockNdx > MAX_SUBBLOCK_SIZE)
  529. {
  530. // 判断wByteCnt + 256是否超过MAX_BUFF_SIZE
  531. if ((lpGIFControlParam->wByteCnt + 256) >= MAX_BUFF_SIZE)
  532. {
  533. // 输出
  534. file.Write(lpGIFControlParam->lpDataBuff,
  535. lpGIFControlParam->wByteCnt);
  536.             lpGIFControlParam->lpEndBuff = lpGIFControlParam->lpDataBuff;
  537.         lpGIFControlParam->wByteCnt  = 0;
  538. }
  539. lpSubBlock[0]           = (BYTE)(lpGIFControlParam->wBlockNdx - 1);
  540. memcpy(lpGIFControlParam->lpEndBuff,lpSubBlock,lpGIFControlParam->wBlockNdx);
  541. lpGIFControlParam->lpEndBuff   += lpGIFControlParam->wBlockNdx;
  542. lpGIFControlParam->wByteCnt    += lpGIFControlParam->wBlockNdx;
  543. lpGIFControlParam->wBlockNdx    = 1;
  544. }
  545. lpGIFControlParam->dwTempCode >>= 8;
  546. lpGIFControlParam->byLeftBits  -= 0x08;
  547. }
  548. // 返回
  549. return;
  550. }
  551. /*************************************************************************
  552.  *
  553.  * 函数名称:
  554.  *   ReadGIF()
  555.  *
  556.  * 参数:
  557.  *   CFile& file        - 要读取的文件
  558.  *
  559.  * 返回值:
  560.  *   HDIB               - 成功返回DIB的句柄,否则返回NULL。
  561.  *
  562.  * 说明:
  563.  *   该函数将读取指定的GIF文件。将读取的结果保存在一个未压缩
  564.  * 编码的DIB对象中。
  565.  *
  566.  *************************************************************************/
  567. HDIB ReadGIF(LPCTSTR lpszFileName)
  568. {
  569. // DIB句柄
  570. HDIB    hDIB;
  571. // DIB指针
  572. LPSTR    pDIB;
  573. // 指向DIB像素的指针
  574. LPSTR    lpDIBBits;
  575. // 指向BITMAPINFOHEADER的指针
  576. LPBITMAPINFOHEADER lpBIH;
  577. // 指向BITMAPINFO的指针
  578. LPBITMAPINFO       lpBI;
  579. // GIF文件头
  580. GIFHEADER          GIFH;
  581. // GIF逻辑屏幕描述块
  582. GIFSCRDESC         GIFS;
  583. // GIF图像描述块
  584. GIFIMAGE           GIFI;
  585. // GIF图像控制扩充块
  586. GIFCONTROL         GIFC;
  587. // GIF图像说明扩充块
  588. GIFPLAINTEXT       GIFP;
  589. // GIF应用程序扩充块
  590. GIFAPPLICATION     GIFA;
  591. // GIF编码参数
  592. GIFDATAPARAM           GIFDataParam;
  593. // 颜色数目
  594. WORD               wColors;
  595. // 每行字节数
  596. WORD               wWidthBytes;
  597. // 调色板
  598. BYTE               byGIF_Pal[768];
  599. // 16色系统调色板
  600. BYTE               bySysPal16[48] = { 0,   0,   0,   0,   0, 128,
  601. 0, 128,   0,   0, 128, 128,
  602.   128,   0,   0, 128,   0, 128,
  603.   128, 128,   0, 128, 128, 128,
  604.   192, 192, 192,   0,   0, 255,
  605. 0, 255,   0,   0, 255, 255,
  606.   255,   0,   0, 255,   0, 255,
  607.   255, 255,   0, 255, 255, 255
  608.    };
  609. // DIB大小(字节数)
  610. DWORD              dwDIB_Size;
  611. // 调色板大小(字节数)
  612. WORD               wPalSize;
  613. // 字节变量
  614. BYTE               byTemp;
  615. // 内存句柄
  616. HANDLE    hSrcBuff;
  617. HANDLE             hTemp;
  618. // 内存指针
  619. LPSTR              lpTemp;
  620. // 字变量
  621. WORD               wTemp;
  622. // 循环变量
  623. WORD               wi;
  624. // 标签
  625. BYTE               byLabel;
  626. // 块大小
  627. BYTE               byBlockSize;
  628. // open file
  629. CFile file;
  630. if (! file.Open(lpszFileName, CFile::modeRead))
  631. return FALSE;
  632. // 读取GIF文件头
  633. file.Read((LPSTR)&GIFH, sizeof(GIFH));
  634. // 判断是否是GIF文件
  635. if (memicmp((LPSTR)GIFH.bySignature,"GIF",3) != 0)
  636. {
  637. // 非GIF文件,返回NULL
  638. return NULL;
  639. }
  640. // 判断版本号是否正确
  641. if ((memicmp((LPSTR)GIFH.byVersion,"87a",3) != 0) &&
  642. (memicmp((LPSTR)GIFH.byVersion,"89a",3) != 0))
  643. {
  644. // 不支持该版本,返回NULL
  645. AfxMessageBox("Not support format!");
  646. return NULL;
  647. }
  648. // 读取GIF逻辑屏幕描述块
  649. file.Read((LPSTR)&GIFS, 7);
  650. // 获取调色板的位数
  651. GIFDataParam.wBits = (WORD)GIFS.GlobalFlag.PalBits + 1;
  652. // 判断是否有全局调色板
  653. if (GIFS.GlobalFlag.GlobalPal)
  654. {
  655. // 赋初值
  656. memset((LPSTR)byGIF_Pal,0,768);
  657. // 全局调色板大小
  658. wPalSize = 3 * (1 << GIFDataParam.wBits);
  659. // 读取全局调色板
  660. file.Read((LPSTR)byGIF_Pal,wPalSize);
  661. }
  662. // 读取下一个字节
  663. file.Read((LPSTR)&byTemp,1);
  664. // 对每一个描述块循环
  665. while(TRUE)
  666. {
  667. // 判断是否是图像描述块
  668. if (byTemp == 0x2C)
  669. {
  670. // 是图像描述块,退出循环
  671. break;
  672. }
  673. // 判断是否是GIF扩展块
  674. if (byTemp==0x21)
  675. {
  676. // 是GIF扩展块
  677. // 分配内存
  678. hTemp  = GlobalAlloc(GHND,(DWORD)MAX_BUFF_SIZE);
  679. // 锁定内存
  680. lpTemp = (LPSTR) GlobalLock(hTemp);
  681. // 读取下一个字节
  682. file.Read((LPSTR)&byLabel, 1);
  683. // 针对各种扩充块,进行分别处理
  684. switch(byLabel)
  685. {
  686. case 0xF9:
  687. {
  688. // 图像控制扩充块
  689. file.Read((LPSTR)&GIFC, 6);
  690. // 跳出
  691. break;
  692. }
  693. case 0x01:
  694. {
  695. // 图像说明扩充块
  696. file.Read((LPSTR)&GIFP,sizeof(GIFP));
  697. // 读取扩充块大小
  698. file.Read((LPSTR)&byBlockSize,1);
  699. // 当byBlockSize > 0时循环读取
  700. while(byBlockSize)
  701. {
  702. // 读取图像说明扩充块(这里没有进行任何处理)
  703. file.Read(lpTemp,byBlockSize);
  704. // 读取扩充块大小
  705. file.Read((LPSTR)&byBlockSize,1);
  706. }
  707. // 跳出
  708. break;
  709. }
  710. case 0xFE:
  711. {
  712. // 注释说明扩充块
  713. // 读取扩充块大小
  714. file.Read((LPSTR)&byBlockSize,1);
  715. // 当byBlockSize > 0时循环读取
  716. while(byBlockSize)
  717. {
  718. // 读取注释说明扩充块(这里没有进行任何处理)
  719. file.Read(lpTemp,byBlockSize);
  720. // 读取扩充块大小
  721. file.Read((LPSTR)&byBlockSize,1);
  722. }
  723. // 跳出
  724. break;
  725. }
  726. case 0xFF:
  727. {
  728. // 应用程序扩充块
  729. file.Read((LPSTR)&GIFA, sizeof(GIFA));
  730. // 读取扩充块大小
  731. file.Read((LPSTR)&byBlockSize,1);
  732. // 当byBlockSize > 0时循环读取
  733. while(byBlockSize)
  734. {
  735. // 读取应用程序扩充块(这里没有进行任何处理)
  736. file.Read(lpTemp,byBlockSize);
  737. // 读取扩充块大小
  738. file.Read((LPSTR)&byBlockSize,1);
  739. }
  740. // 跳出
  741. break;
  742. }
  743. default:
  744. {
  745. // 忽略未知的扩充块
  746. // 读取扩充块大小
  747. file.Read((LPSTR)&byBlockSize,1);
  748. // 当byBlockSize > 0时循环读取
  749. while(byBlockSize)
  750. {
  751. // 读取未知的扩充块(这里没有进行任何处理)
  752. file.Read(lpTemp,byBlockSize);
  753. // 读取扩充块大小
  754. file.Read((LPSTR)&byBlockSize,1);
  755. }
  756. // 跳出
  757. break;
  758. }
  759. // 释放内存
  760. GlobalUnlock(hTemp);
  761. GlobalFree(hTemp);
  762. }
  763. }
  764. // 读取下一个字节
  765. file.Read((LPSTR)&byTemp,1);
  766. }
  767. // 读取GIF图像描述块
  768. file.Read((LPSTR)&GIFI, 9);
  769. // 获取图像宽度
  770. GIFDataParam.wWidth         = GIFI.wWidth;
  771. // 获取图像高度
  772. GIFDataParam.wDepth         = GIFI.wDepth;
  773. // 判断是否有区域调色板
  774. if (GIFI.LocalFlag.LocalPal)
  775. {
  776. // 赋初值
  777. memset((LPSTR)byGIF_Pal, 0, 768);
  778. // 读取区域调色板位数
  779. GIFDataParam.wBits = (WORD)GIFI.LocalFlag.PalBits + 1;
  780. // 区域调色板大小
  781. wPalSize      = 3 * (1 << GIFDataParam.wBits);
  782. // 读取区域调色板
  783. file.Read((LPSTR)byGIF_Pal,wPalSize);
  784. }
  785. // 给GIFDataParam成员赋值
  786. GIFDataParam.wBits          = ((GIFDataParam.wBits==1) ? 1 :
  787.   (GIFDataParam.wBits<=4) ? 4 : 8);
  788. GIFDataParam.wLineBytes     = (WORD)BYTE_WBYTES((DWORD)GIFDataParam.wWidth *
  789.    (DWORD)GIFDataParam.wBits);
  790. GIFDataParam.bEOF           = FALSE;
  791. // 交错方式
  792. GIFDataParam.bInterlace     = (GIFI.LocalFlag.Interlace ? TRUE : FALSE);
  793. // 每行字节数
  794. wWidthBytes    = (WORD)DWORD_WBYTES((DWORD)GIFDataParam.wWidth *
  795.    (DWORD)GIFDataParam.wBits);
  796. // 颜色数目
  797. wColors    = 1 << GIFDataParam.wBits;
  798. // 调色板大小
  799. wPalSize    = wColors * sizeof(RGBQUAD);
  800. // 计算DIB长度(字节)
  801. dwDIB_Size    = sizeof(BITMAPINFOHEADER) + wPalSize
  802.  + GIFDataParam.wDepth * wWidthBytes;
  803. // 为DIB分配内存
  804. hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIB_Size);
  805. if (hDIB == 0)
  806. {
  807. // 内存分配失败,返回NULL。
  808. return NULL;
  809. }
  810. // 锁定
  811. pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  812. ///////////////////////////////////////////////////////////////////////////
  813. // 设置BITMAPINFOHEADER
  814. // 赋值
  815. lpBIH = (LPBITMAPINFOHEADER) pDIB;
  816. lpBI  = (LPBITMAPINFO) pDIB;
  817. // 给lpBIH成员赋值
  818. lpBIH->biSize = (DWORD)sizeof(BITMAPINFOHEADER);
  819. lpBIH->biWidth = (DWORD)GIFDataParam.wWidth;
  820. lpBIH->biHeight = (DWORD)GIFDataParam.wDepth;
  821. lpBIH->biPlanes = 1;
  822. lpBIH->biBitCount = GIFDataParam.wBits;
  823. lpBIH->biCompression = BI_RGB;
  824. lpBIH->biSizeImage = (DWORD)wWidthBytes * GIFDataParam.wDepth;
  825. lpBIH->biXPelsPerMeter = 0;
  826. lpBIH->biYPelsPerMeter = 0;
  827. lpBIH->biClrUsed = wColors;
  828. lpBIH->biClrImportant = 0;
  829. ///////////////////////////////////////////////////////////////////////////
  830. // 设置调色板
  831. // 判断是否指定全局或区域调色板
  832. if (GIFS.GlobalFlag.GlobalPal || GIFI.LocalFlag.LocalPal)
  833. {
  834. wTemp = 0;
  835. for(wi=0; wi<wColors; wi++)
  836. {
  837. lpBI->bmiColors[wi].rgbRed      = byGIF_Pal[wTemp++];
  838. lpBI->bmiColors[wi].rgbGreen    = byGIF_Pal[wTemp++];
  839. lpBI->bmiColors[wi].rgbBlue     = byGIF_Pal[wTemp++];
  840. lpBI->bmiColors[wi].rgbReserved = 0x00;
  841. }
  842. }
  843. else
  844. {
  845. // 没有指定全局和区域调色板,采用系统调色板
  846. // 按照颜色数目来分别给调色板赋值
  847. switch(wColors)
  848. {
  849. case   2:
  850. {
  851. // 单色位图
  852. lpBI->bmiColors[0].rgbRed          = 0x00;
  853. lpBI->bmiColors[0].rgbGreen        = 0x00;
  854. lpBI->bmiColors[0].rgbBlue         = 0x00;
  855. lpBI->bmiColors[0].rgbReserved     = 0x00;
  856. lpBI->bmiColors[1].rgbRed          = 0xFF;
  857. lpBI->bmiColors[1].rgbGreen        = 0xFF;
  858. lpBI->bmiColors[1].rgbBlue         = 0xFF;
  859. lpBI->bmiColors[1].rgbReserved     = 0x00;
  860. // 跳出
  861. break;
  862. }
  863. case  16:
  864. {
  865. // 16色位图
  866. wTemp = 0;
  867. for(wi=0;wi<wColors;wi++)
  868. {
  869. lpBI->bmiColors[wi].rgbRed      = bySysPal16[wTemp++];
  870. lpBI->bmiColors[wi].rgbGreen    = bySysPal16[wTemp++];
  871. lpBI->bmiColors[wi].rgbBlue     = bySysPal16[wTemp++];
  872. lpBI->bmiColors[wi].rgbReserved = 0x00;
  873. }
  874. // 跳出
  875. break;
  876. }
  877. case 256:
  878. {
  879. // 256色位图
  880. for(wi=0; wi<wColors; wi++)
  881. {
  882. lpBI->bmiColors[wi].rgbRed      = (BYTE)wi;
  883. lpBI->bmiColors[wi].rgbGreen    = (BYTE)wi;
  884. lpBI->bmiColors[wi].rgbBlue     = (BYTE)wi;
  885. lpBI->bmiColors[wi].rgbReserved = 0x00;
  886. }
  887. // 跳出
  888. break;
  889. }
  890. }
  891. }
  892. ///////////////////////////////////////////////////////////////////////////
  893. // 解码
  894. // 获取编码数据长度
  895. GIFDataParam.dwDataLen  = (DWORD) (file.GetLength() - file.GetPosition());
  896. // 计算内存大小(最大不超过MAX_BUFF_SIZE)
  897. GIFDataParam.wMemLen    = ((GIFDataParam.dwDataLen > (DWORD)MAX_BUFF_SIZE) ?
  898.   (WORD)MAX_BUFF_SIZE : (WORD)GIFDataParam.dwDataLen);
  899. // 分配内存
  900. hSrcBuff = GlobalAlloc(GHND, (DWORD)GIFDataParam.wMemLen);
  901. // 锁定内存
  902. GIFDataParam.lpDataBuff = (LPSTR)GlobalLock(hSrcBuff);
  903. // 读取编码数据
  904. ReadSrcDataGIF(file,&GIFDataParam.wMemLen,&GIFDataParam.dwDataLen,
  905. GIFDataParam.lpDataBuff,&GIFDataParam.bEOF);
  906. // 缓冲区起始位置
  907. GIFDataParam.lpBgnBuff  = GIFDataParam.lpDataBuff;
  908. // 缓冲区中止位置
  909. GIFDataParam.lpEndBuff  = GIFDataParam.lpBgnBuff + GIFDataParam.wMemLen;
  910. // 计算DIB中像素位置
  911. lpDIBBits = (LPSTR) FindDIBBits(pDIB);
  912. // 解码
  913. DecodeGIF(file, lpDIBBits, &GIFDataParam, wWidthBytes);
  914. // 释放内存
  915. GlobalUnlock(hSrcBuff);
  916. GlobalFree(hSrcBuff);
  917. // 返回DIB句柄
  918. return hDIB;
  919. }
  920. /*************************************************************************
  921.  *
  922.  * 函数名称:
  923.  *   ReadSrcDataGIF()
  924.  *
  925.  * 参数:
  926.  *   CFile& file - 源GIF文件
  927.  *   LPWORD lpwMemLen - 缓冲区长度(指针)
  928.  *   LPDWORD lpdwDataLen - 剩余数据长度(指针)
  929.  *   LPSTR lpSrcBuff - 缓冲区指针
  930.  *  LPBOOL lpbEOF - 结束标志
  931.  *
  932.  * 返回值:
  933.  *   无
  934.  *
  935.  * 说明:
  936.  *   该函数用来读取指定GIF文件中的图像编码,每次最多读取MAX_BUFF_SIZE
  937.  * 字节,是否读完由标志lpbEOF指定。
  938.  *
  939.  *************************************************************************/
  940. void ReadSrcDataGIF(CFile& file, LPWORD lpwMemLen, LPDWORD lpdwDataLen,
  941.                         LPSTR lpSrcBuff, LPBOOL lpbEOF)
  942. {
  943. // 判断数据长度是否仍然大于内存大小
  944. if ((*lpdwDataLen) > (DWORD)(*lpwMemLen))
  945. {
  946. // 数据长度大于内存大小,表示没有解码完
  947. // 数据长度减内存大小
  948. (*lpdwDataLen) -= (DWORD)(*lpwMemLen);
  949. }
  950. else
  951. {
  952. // 数据长度不大于内存大小,表示解码将要完成
  953. // 内存大小就是剩余数据长度
  954. (*lpwMemLen)    = (WORD)(*lpdwDataLen);
  955. // EOF标志设置为TRUE
  956. (*lpbEOF)       = TRUE;
  957. }
  958. // 读取编码数据
  959. file.Read(lpSrcBuff, (*lpwMemLen));
  960. // 返回
  961. return;
  962. }
  963. /*************************************************************************
  964.  *
  965.  * 函数名称:
  966.  *   DecodeGIF()
  967.  *
  968.  * 参数:
  969.  *   CFile& file - 源GIF文件
  970.  *   LPSTR lpDIBBits - 指向要保存的DIB图像指针
  971.  *   LPGIFDATAPARAM lpGIFDataParam - 指向GIFCONTROLPARAM结构的指针
  972.  *  WORD wWidthBytes - 每行图像字节数
  973.  *
  974.  * 返回值:
  975.  *   无
  976.  *
  977.  * 说明:
  978.  *   该函数对指定GIF_LZW编码数据进行解码。
  979.  *
  980.  *************************************************************************/
  981. void DecodeGIF(CFile& file, LPSTR lpDIBBits,
  982.   LPGIFDATAPARAM lpGIFDataParam,WORD wWidthBytes)
  983. {
  984. // 指向编码后图像数据的指针
  985. BYTE * lpDst;
  986. // 内存分配句柄
  987. HANDLE hPrefix;
  988. HANDLE hSuffix;
  989. HANDLE hStack;
  990. HANDLE hImage;
  991. // 用于字串表搜索的索引
  992. LPWORD lpwPrefix;
  993. LPBYTE lpbySuffix;
  994. LPBYTE lpbyStack;
  995. LPBYTE lpbyStackBgn;
  996. // 指向图像当前行解码结果的指针
  997. LPSTR  lpImageBgn;
  998. // 指向当前编码像素的指针
  999. LPSTR  lpImage;
  1000. // 计算当前数据图像的偏移量
  1001. DWORD  dwDataNdx;
  1002. // LZW_CLEAR
  1003. WORD   wLZW_CLEAR;
  1004. // LZW_EOI
  1005. WORD   wLZW_EOI;
  1006. // LZW_MinCodeLen
  1007. BYTE   byLZW_MinCodeLen;
  1008. // 字串表索引
  1009. WORD   wNowTableNdx;
  1010. WORD   wTopTableNdx;
  1011. // 当前图像的行数
  1012. WORD   wRowNum;
  1013. // 计数
  1014. WORD   wWidthCnt;
  1015. WORD   wBitCnt;
  1016. WORD   wRowCnt;
  1017. // 循环变量
  1018. WORD   wi;
  1019. // 交错方式存储时每次增加的行数
  1020. WORD   wIncTable[5]  = { 8,8,4,2,0 }; 
  1021. // 交错方式存储时起始行数
  1022. WORD   wBgnTable[5]  = { 0,4,2,1,0 }; 
  1023. // 块大小
  1024. BYTE   byBlockSize;
  1025. // 块索引
  1026. BYTE   byBlockNdx;
  1027. DWORD  dwData;
  1028. // 当前编码
  1029. WORD   wCode;
  1030. // 上一个编码
  1031. WORD   wOldCode;
  1032. // 临时索引
  1033. WORD   wTempNdx;
  1034. WORD   wCodeMask[13] = {0x0000,
  1035. 0x0001,0x0003,0x0007,0x000F,
  1036. 0x001F,0x003F,0x007F,0x00FF,
  1037. 0x01FF,0x03FF,0x07FF,0x0FFF
  1038. };
  1039. BYTE   byLeftBits;
  1040. BYTE   byFirstChar;
  1041. BYTE   byCode;
  1042. BYTE   byCurrentBits;
  1043. BYTE   byPass;
  1044. // 临时字节变量
  1045. BYTE   byTempChar;
  1046. // 给字串表分配内存
  1047. hPrefix          = GlobalAlloc(GHND,(DWORD)(MAX_TABLE_SIZE<<1));
  1048. hSuffix          = GlobalAlloc(GHND,(DWORD)MAX_TABLE_SIZE);
  1049. hStack           = GlobalAlloc(GHND,(DWORD)MAX_TABLE_SIZE);
  1050. hImage           = GlobalAlloc(GHND,(DWORD)wWidthBytes);
  1051. // 锁定内存
  1052. lpwPrefix        = (LPWORD)GlobalLock(hPrefix);
  1053. lpbySuffix       = (LPBYTE)GlobalLock(hSuffix);
  1054. lpbyStack        = (LPBYTE)GlobalLock(hStack);
  1055. lpbyStackBgn     = lpbyStack;
  1056. lpImage          = (LPSTR)GlobalLock(hImage);
  1057. lpImageBgn       = lpImage;
  1058. // 读取GIF LZW最小编码大小
  1059. byLZW_MinCodeLen = *lpGIFDataParam->lpBgnBuff++;
  1060. byCurrentBits    = byLZW_MinCodeLen + (BYTE)0x01;
  1061. // 计算LZW_CLEAR
  1062. wLZW_CLEAR       = 1 << byLZW_MinCodeLen;
  1063. // 计算LZW_EOI
  1064. wLZW_EOI         = wLZW_CLEAR + 1;
  1065. // 计算字串表索引
  1066. wNowTableNdx     = wLZW_CLEAR + 2;
  1067. wTopTableNdx     = 1 << byCurrentBits;
  1068. // 赋初值
  1069. dwData           = 0UL;
  1070. wBitCnt          = lpGIFDataParam->wBits;
  1071. wRowNum          = 0;
  1072. wRowCnt          = 1;
  1073. wWidthCnt        = 0;
  1074. wCode            = 0;
  1075. wOldCode         = 0xFFFF;
  1076. byBlockSize      = 0x01;
  1077. byBlockNdx       = 0x00;
  1078. byLeftBits       = 0x00;
  1079. byTempChar       = 0x00;
  1080. byPass           = 0x00;
  1081. // 读取下一个编码
  1082. while(byLeftBits < byCurrentBits)
  1083. {
  1084. // 读取下一个字符
  1085. // 判断是否读完一个数据块
  1086. if (++byBlockNdx == byBlockSize)
  1087. {
  1088. // 读取下一个数据块
  1089. byBlockSize = *lpGIFDataParam->lpBgnBuff++;
  1090. byBlockNdx  = 0x00;
  1091. // 判断是否读完
  1092. if ((lpGIFDataParam->lpBgnBuff == lpGIFDataParam->lpEndBuff) &&
  1093.     !lpGIFDataParam->bEOF)
  1094. {
  1095. // 读取下一个数据块
  1096. ReadSrcDataGIF(file,&lpGIFDataParam->wMemLen,
  1097. &lpGIFDataParam->dwDataLen,
  1098. lpGIFDataParam->lpDataBuff,&lpGIFDataParam->bEOF);
  1099. // 指针重新赋值
  1100. lpGIFDataParam->lpBgnBuff = lpGIFDataParam->lpDataBuff;
  1101. lpGIFDataParam->lpEndBuff = lpGIFDataParam->lpBgnBuff + lpGIFDataParam->wMemLen;
  1102. }
  1103. }
  1104. // 下一个字符
  1105. byCode      = *lpGIFDataParam->lpBgnBuff++;
  1106. // 移位
  1107. dwData     |= ((DWORD)byCode << byLeftBits);
  1108. byLeftBits += 0x08;
  1109. // 判断是否读完
  1110. if ((lpGIFDataParam->lpBgnBuff == lpGIFDataParam->lpEndBuff) &&
  1111.     !lpGIFDataParam->bEOF)
  1112. {
  1113. // 读取下一个数据块
  1114. ReadSrcDataGIF(file,&lpGIFDataParam->wMemLen,
  1115. &lpGIFDataParam->dwDataLen,
  1116. lpGIFDataParam->lpDataBuff,&lpGIFDataParam->bEOF);
  1117. // 指针重新赋值
  1118. lpGIFDataParam->lpBgnBuff = lpGIFDataParam->lpDataBuff;
  1119. lpGIFDataParam->lpEndBuff = lpGIFDataParam->lpBgnBuff + lpGIFDataParam->wMemLen;
  1120. }
  1121. }
  1122. wCode       = (WORD)dwData & wCodeMask[byCurrentBits];
  1123. dwData    >>= byCurrentBits;
  1124. byLeftBits -= byCurrentBits;
  1125. // 解码
  1126. while(wCode != wLZW_EOI)
  1127. {
  1128. // 当前编码不是LZW_EOI码
  1129. // 判断是否是LZW_CLEAR码
  1130. if (wCode == wLZW_CLEAR)
  1131. {
  1132. // 是LZW_CLEAR,清除字串表
  1133. // 重新初始化字串表
  1134. for(wi = 0; wi < wLZW_CLEAR; wi++)
  1135. {
  1136. *(lpwPrefix  + wi)  = 0xFFFF;
  1137. *(lpbySuffix + wi) = (BYTE)wi;
  1138. }
  1139. for(wi = wNowTableNdx; wi < MAX_TABLE_SIZE; wi++)
  1140. {
  1141. *(lpwPrefix+wi)  = 0xFFFF;
  1142. *(lpbySuffix+wi) = 0x00;
  1143. }
  1144. byCurrentBits = byLZW_MinCodeLen + (BYTE)0x01;
  1145. wNowTableNdx  = wLZW_CLEAR + 2;
  1146. wTopTableNdx  = 1 << byCurrentBits;
  1147. wOldCode      = 0xFFFF;
  1148. // 获取下一个编码
  1149. while(byLeftBits < byCurrentBits)
  1150. {
  1151. // 读取下一个字符
  1152. // 判断是否读完一个数据块
  1153. if (++byBlockNdx == byBlockSize)
  1154. {
  1155. // 读取下一个数据块
  1156. byBlockSize = *lpGIFDataParam->lpBgnBuff++;
  1157. byBlockNdx  = 0x00;
  1158. // 判断是否读完
  1159. if ((lpGIFDataParam->lpBgnBuff == lpGIFDataParam->lpEndBuff) &&
  1160. !lpGIFDataParam->bEOF)
  1161. {
  1162. // 读取下一个数据块
  1163. ReadSrcDataGIF(file, &lpGIFDataParam->wMemLen,
  1164. &lpGIFDataParam->dwDataLen,
  1165. lpGIFDataParam->lpDataBuff,
  1166. &lpGIFDataParam->bEOF);
  1167. // 指针重新赋值
  1168. lpGIFDataParam->lpBgnBuff = lpGIFDataParam->lpDataBuff;
  1169. lpGIFDataParam->lpEndBuff = lpGIFDataParam->lpBgnBuff +
  1170.    lpGIFDataParam->wMemLen;
  1171. }
  1172. }
  1173. byCode      = *lpGIFDataParam->lpBgnBuff++;
  1174. dwData     |= ((DWORD)byCode << byLeftBits);
  1175. byLeftBits += 0x08;
  1176. // 判断是否读完
  1177. if ((lpGIFDataParam->lpBgnBuff == lpGIFDataParam->lpEndBuff) &&
  1178.  !lpGIFDataParam->bEOF)
  1179. {
  1180. // 读取下一个数据块
  1181. ReadSrcDataGIF(file,&lpGIFDataParam->wMemLen,
  1182. &lpGIFDataParam->dwDataLen,
  1183. lpGIFDataParam->lpDataBuff,&lpGIFDataParam->bEOF);
  1184. // 指针重新赋值
  1185. lpGIFDataParam->lpBgnBuff = lpGIFDataParam->lpDataBuff;
  1186. lpGIFDataParam->lpEndBuff = lpGIFDataParam->lpBgnBuff + lpGIFDataParam->wMemLen;
  1187. }
  1188. }
  1189. wCode       = (WORD)dwData & wCodeMask[byCurrentBits];
  1190. dwData    >>= byCurrentBits;
  1191. byLeftBits -= byCurrentBits;
  1192. // 判断编码是否为LZW_EOI
  1193. if (wCode!=wLZW_EOI)
  1194. {
  1195. // 这里没有用到lpbyStack[0]
  1196. lpbyStack  ++;
  1197. // 将数据压入堆栈
  1198. while((*(lpwPrefix+wCode)) != 0xFFFF)
  1199. {
  1200. *lpbyStack++ = *(lpbySuffix+wCode);
  1201. wCode        = *(lpwPrefix+wCode);
  1202. }
  1203. *lpbyStack  = *(lpbySuffix+wCode);
  1204. byFirstChar = *lpbyStack;
  1205. // 输出数据
  1206. while(lpbyStack>lpbyStackBgn)
  1207. {
  1208. byTempChar |= (*lpbyStack-- << (8-wBitCnt));
  1209. if (wBitCnt==8)
  1210. {
  1211. *lpImage++ = byTempChar;
  1212. byTempChar = 0x00;
  1213. wBitCnt    = lpGIFDataParam->wBits;
  1214. }
  1215. else
  1216. {
  1217. wBitCnt   += lpGIFDataParam->wBits;
  1218. }
  1219. wWidthCnt  ++;
  1220. if (wWidthCnt==lpGIFDataParam->wWidth)
  1221. {
  1222. if (wBitCnt!=lpGIFDataParam->wBits)
  1223. {
  1224. *lpImage   = byTempChar;
  1225. byTempChar = 0x00;
  1226. wBitCnt    = lpGIFDataParam->wBits;
  1227. }
  1228. // 图像当前行偏移量
  1229. dwDataNdx = (DWORD)(lpGIFDataParam->wDepth - 1 - wRowNum) * (DWORD)wWidthBytes;
  1230. // 图像当前行起始位置
  1231. lpDst = (BYTE *)lpDIBBits + dwDataNdx;
  1232. // 赋值
  1233. memcpy(lpDst, lpImageBgn, wWidthBytes);
  1234. lpImage   = lpImageBgn;
  1235. // 判断是否按照交错方式保存
  1236. if (lpGIFDataParam->bInterlace)
  1237. {
  1238. // 交错方式
  1239. // 计算下一行的行号
  1240. wRowNum += wIncTable[byPass];
  1241. if (wRowNum >= lpGIFDataParam->wDepth)
  1242. {
  1243. byPass ++;
  1244. wRowNum = wBgnTable[byPass];
  1245. }
  1246. }
  1247. else
  1248. {
  1249. // 非交错方式,行号直接加1
  1250. wRowNum ++;
  1251. }
  1252. wWidthCnt = 0;
  1253. }
  1254. }
  1255. }
  1256. }
  1257. else
  1258. {
  1259. // 这里没有用到lpbyStack[0]
  1260. lpbyStack  ++;
  1261. // 判断字符串是否在字串表中
  1262. if (wCode < wNowTableNdx)
  1263. {
  1264. // 不在字串表中
  1265. wTempNdx   = wCode;
  1266. }
  1267. else
  1268. {
  1269. // 在字串表中
  1270. wTempNdx     = wOldCode;
  1271. *lpbyStack++ = byFirstChar;
  1272. }
  1273. // 将数据压入堆栈
  1274. while((*(lpwPrefix+wTempNdx)) != 0xFFFF)
  1275. {
  1276. *lpbyStack++ = *(lpbySuffix+wTempNdx);
  1277. wTempNdx     = *(lpwPrefix+wTempNdx);
  1278. }
  1279. *lpbyStack  = *(lpbySuffix+wTempNdx);
  1280. byFirstChar = *lpbyStack;
  1281. // 将字符串添加到字串表中
  1282. *(lpwPrefix+wNowTableNdx)  = wOldCode;
  1283. *(lpbySuffix+wNowTableNdx) = byFirstChar;
  1284. if (++wNowTableNdx==wTopTableNdx && byCurrentBits<12)
  1285. {
  1286. byCurrentBits ++;
  1287. wTopTableNdx   = 1 << byCurrentBits;
  1288. }
  1289. // 输出数据
  1290. while(lpbyStack>lpbyStackBgn)
  1291. {
  1292. byTempChar |= (*lpbyStack-- << (8-wBitCnt));
  1293. if (wBitCnt==8)
  1294. {
  1295. *lpImage++ = byTempChar;
  1296. byTempChar = 0x00;
  1297. wBitCnt    = lpGIFDataParam->wBits;
  1298. }
  1299. else
  1300. {
  1301. wBitCnt   += lpGIFDataParam->wBits;
  1302. }
  1303. wWidthCnt  ++;
  1304. if (wWidthCnt==lpGIFDataParam->wWidth)
  1305. {
  1306. if (wBitCnt!=lpGIFDataParam->wBits)
  1307. {
  1308. *lpImage   = byTempChar;
  1309. byTempChar = 0x00;
  1310. wBitCnt    = lpGIFDataParam->wBits;
  1311. }
  1312. // 图像当前行偏移量
  1313. dwDataNdx = (DWORD)(lpGIFDataParam->wDepth - 1 - wRowNum) * (DWORD)wWidthBytes;
  1314. // 图像当前行起始位置
  1315. lpDst = (BYTE *)lpDIBBits + dwDataNdx;
  1316. // 赋值
  1317. memcpy(lpDst, lpImageBgn, wWidthBytes);
  1318. lpImage   = lpImageBgn;
  1319. // 判断是否按照交错方式保存
  1320. if (lpGIFDataParam->bInterlace)
  1321. {
  1322. // 交错方式
  1323. // 计算下一行的行号
  1324. wRowNum += wIncTable[byPass];
  1325. if (wRowNum >= lpGIFDataParam->wDepth)
  1326. {
  1327. byPass ++;
  1328. wRowNum = wBgnTable[byPass];
  1329. }
  1330. }
  1331. else
  1332. {
  1333. // 非交错方式,行号直接加1
  1334. wRowNum ++;
  1335. }
  1336. wWidthCnt = 0;
  1337. }
  1338. }
  1339. }
  1340. wOldCode = wCode;
  1341. // 读取下一个编码
  1342. while(byLeftBits < byCurrentBits)
  1343. {
  1344. // 读取下一个字符
  1345. // 判断是否读完一个数据块
  1346. if (++byBlockNdx == byBlockSize)
  1347. {
  1348. // 读取下一个数据块
  1349. byBlockSize = *lpGIFDataParam->lpBgnBuff++;
  1350. byBlockNdx  = 0x00;
  1351. // 判断是否读完
  1352. if ((lpGIFDataParam->lpBgnBuff == lpGIFDataParam->lpEndBuff) &&
  1353.  !lpGIFDataParam->bEOF)
  1354. {
  1355. // 读取下一个数据块
  1356. ReadSrcDataGIF(file,&lpGIFDataParam->wMemLen,
  1357. &lpGIFDataParam->dwDataLen,
  1358. lpGIFDataParam->lpDataBuff,&lpGIFDataParam->bEOF);
  1359. // 指针重新赋值
  1360. lpGIFDataParam->lpBgnBuff = lpGIFDataParam->lpDataBuff;
  1361. lpGIFDataParam->lpEndBuff = lpGIFDataParam->lpBgnBuff + lpGIFDataParam->wMemLen;
  1362. }
  1363. }
  1364. byCode      = *lpGIFDataParam->lpBgnBuff++;
  1365. dwData     |= ((DWORD)byCode << byLeftBits);
  1366. byLeftBits += 0x08;
  1367. // 判断是否读完
  1368. if ((lpGIFDataParam->lpBgnBuff == lpGIFDataParam->lpEndBuff) &&
  1369.   !lpGIFDataParam->bEOF)
  1370. {
  1371. // 读取下一个数据块
  1372. ReadSrcDataGIF(file,&lpGIFDataParam->wMemLen,
  1373. &lpGIFDataParam->dwDataLen,
  1374. lpGIFDataParam->lpDataBuff,&lpGIFDataParam->bEOF);
  1375. // 指针重新赋值
  1376. lpGIFDataParam->lpBgnBuff = lpGIFDataParam->lpDataBuff;
  1377. lpGIFDataParam->lpEndBuff = lpGIFDataParam->lpBgnBuff + lpGIFDataParam->wMemLen;
  1378. }
  1379. }
  1380. wCode       = (WORD)dwData & wCodeMask[byCurrentBits];
  1381. dwData    >>= byCurrentBits;
  1382. byLeftBits -= byCurrentBits;
  1383. }
  1384. // 释放内存
  1385. GlobalUnlock(hPrefix);
  1386. GlobalUnlock(hSuffix);
  1387. GlobalUnlock(hStack);
  1388. GlobalFree(hPrefix);
  1389. GlobalFree(hSuffix);
  1390. GlobalFree(hStack);
  1391. // 返回
  1392. return;
  1393. }