GifModule.cpp
上传用户:yatsl7111
上传日期:2007-01-08
资源大小:1433k
文件大小:47k
源码类别:

图形图象

开发平台:

Visual C++

  1. /********************************************************************
  2. GifModule.cpp - ISee图像浏览器—GIF图像读写模块实现文件
  3.           
  4.     版权所有(C) 2000 VCHelp-coPathway-ISee workgroup member - Sam, YZ
  5.     这一程序是自由软件,你可以遵照自由软件基金会出版的GNU 通用公共许
  6. 可证条款来修改和重新发布这一程序。或者用许可证的第二版,或者(根
  7. 据你的选择)用任何更新的版本。
  8.     发布这一程序的目的是希望它有用,但没有任何担保。甚至没有适合特定
  9. 目地的隐含的担保。更详细的情况请参阅GNU通用公共许可证。
  10.     你应该已经和程序一起收到一份GNU通用公共许可证的副本(本目录
  11. GPL.TXT文件)。如果还没有,写信给:
  12.     The Free Software Foundation, Inc.,  675  Mass Ave,  Cambridge,
  13.     MA02139,  USA
  14. 如果你在使用本软件时有什么问题或建议,用以下地址可以与我们取得联
  15. 系:
  16. http://isee.126.com
  17. http://www.vchelp.net
  18. 或:
  19. iseesoft@china.com
  20. 原创人    :Sam (http://go.163.com/~program2000/)
  21. 第二编写人:YZ (http://isee.126.com/  or  yzfree@sina.com)
  22. 文件版本:
  23. Build 00901
  24. Date  2000-9-1
  25. GIF图像文件格式版权声明:
  26. ---------------------------------------------------------------
  27. The Graphics Interchange Format(c) is the Copyright property of
  28. CompuServe Incorporated. GIF(sm) is a Service Mark property of
  29. CompuServe Incorporated.
  30. ---------------------------------------------------------------
  31. ********************************************************************/
  32. #include "stdafx.h"
  33. #include "GifModule.h"
  34. #ifdef _DEBUG
  35. #define new DEBUG_NEW
  36. #undef THIS_FILE
  37. static char THIS_FILE[] = __FILE__;
  38. #endif
  39. // 全局变量定义
  40. GIFINFO m_GifInfo;
  41. LZWTABLE LZWTable[LZWTABLESIZE];
  42. CPtrList m_ImageList;
  43. RGBQUAD m_GlobalPal[256]; // 全局调色板
  44. RGBQUAD m_CurRgbQuad[256]; // 当前的局部调色板
  45. int m_CurPalSize; // 当前调色板项数(针对于局部调色板)
  46. int m_CurDM; // 当前的处置方法
  47. int m_CurUserInput; // 当前的用户输入标志
  48. short m_CurTColorIndex; // 当前的透明色索引号(-1表示无效)
  49. WORD m_CurDelayTime; // 当前的延迟时间(0表示没有延时)
  50. BOOL m_CurSaveMode; // 当前的图像存储模式
  51. WORD m_CurX,m_CurY; // 当前图像在虚拟屏幕中的位置
  52. WORD m_CurWidth,m_CurHeight; // 当前图像的宽度、高度
  53. int m_CurImgIndex; // 当前图像的序号(0基)
  54. LPSUBIMGBLOCK   m_pSubimgHead; // 子图像链表的头
  55. LPSUBIMGBLOCK   m_pSubimgTail; // 子图像链表的尾
  56. static char ModuleProcessImgType[]="GIF"; // 本模块能处理的图像类型
  57. static char WriterList[]="Sam, YZ"; // 本模块的作者列表
  58. static char WriterMess[]="我喜欢自由软件,它大大的减少了重复代码的开发^_^";
  59. // 作者留言
  60. static char GIF87a[]="GIF87a";
  61. static char GIF89a[]="GIF89a";
  62. //
  63. // Note!
  64. //
  65. // If this DLL is dynamically linked against the MFC
  66. // DLLs, any functions exported from this DLL which
  67. // call into MFC must have the AFX_MANAGE_STATE macro
  68. // added at the very beginning of the function.
  69. //
  70. // For example:
  71. //
  72. // extern "C" BOOL PASCAL EXPORT ExportedFunction()
  73. // {
  74. // AFX_MANAGE_STATE(AfxGetStaticModuleState());
  75. // // normal function body here
  76. // }
  77. //
  78. // It is very important that this macro appear in each
  79. // function, prior to any calls into MFC.  This means that
  80. // it must appear as the first statement within the 
  81. // function, even before any object variable declarations
  82. // as their constructors may generate calls into the MFC
  83. // DLL.
  84. //
  85. // Please see MFC Technical Notes 33 and 58 for additional
  86. // details.
  87. //
  88. // 在图像读写模块中,如果想分配内存,请使用API函数GlobalAlloc()
  89. // ,如果想释放内存请使用GlobalFree()函数。不要使用诸如:new
  90. // 、malloc()等函数。这是为了使各模块之间可以异地释放内存。
  91. //
  92. //
  93. /////////////////////////////////////////////////////////////////////////////
  94. // CGifModuleApp
  95. BEGIN_MESSAGE_MAP(CGifModuleApp, CWinApp)
  96. //{{AFX_MSG_MAP(CGifModuleApp)
  97. // NOTE - the ClassWizard will add and remove mapping macros here.
  98. //    DO NOT EDIT what you see in these blocks of generated code!
  99. //}}AFX_MSG_MAP
  100. END_MESSAGE_MAP()
  101. /////////////////////////////////////////////////////////////////////////////
  102. // CGifModuleApp construction
  103. CGifModuleApp::CGifModuleApp()
  104. {
  105. ::ZeroMemory((PVOID)&m_GifInfo, sizeof(GIFINFO));
  106. ::ZeroMemory((PVOID)LZWTable, sizeof(LZWTABLE)*LZWTABLESIZE);
  107. PALETTEENTRY syspal[256];
  108. // 提取当前系统的调色板数据
  109. HWND hWnd = ::GetDesktopWindow();
  110. HDC  hDC  = ::GetDC(hWnd);
  111. ::GetSystemPaletteEntries(hDC, 0, 256, (LPPALETTEENTRY)syspal);
  112. ::ReleaseDC(hWnd, hDC);
  113. // 初始化全局调色板
  114. for (int i=0;i<256;i++)
  115. {
  116. m_GlobalPal[i].rgbRed = syspal[i].peRed;
  117. m_GlobalPal[i].rgbGreen = syspal[i].peGreen;
  118. m_GlobalPal[i].rgbBlue = syspal[i].peBlue;
  119. m_GlobalPal[i].rgbReserved = 0;
  120. }
  121. m_CurPalSize = 0; // 当前调色板项数(针对于局部调色板)
  122. m_CurDM = 0; // 当前的处置方法
  123. m_CurUserInput = 0; // 当前的用户输入标志
  124. m_CurTColorIndex = -1; // 当前的透明色索引号(-1表示无效)
  125. m_CurDelayTime = 0; // 当前的延迟时间(0表示没有延时)
  126. m_CurSaveMode = 0; // 当前的图像存储模式
  127. m_CurX = m_CurY = 0; // 当前图像在虚拟屏幕中的位置
  128. m_CurWidth = m_CurHeight = 0; // 当前图像的宽度、高度
  129. m_CurImgIndex = 0; // 当前图像的序号(0基)
  130. m_pSubimgHead = NULL; // 子图像链表的头
  131. m_pSubimgTail = NULL; // 子图像链表的尾
  132. }
  133. /////////////////////////////////////////////////////////////////////////////
  134. // The one and only CGifModuleApp object
  135. CGifModuleApp theApp;
  136. // 接口函数声明 — 第一层,唯一与外界联系的接口
  137. int WINAPI AccessGIFModule(INFOSTR *pInfo)
  138. {
  139. // 这个函数可以不作修改的使用,除非你的返回值多于两种。
  140. switch(pInfo->comm)
  141. {
  142. case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
  143. _fnCMD_GETPROCTYPE(pInfo);
  144. break;
  145. case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
  146. _fnCMD_GETWRITERS(pInfo);
  147. break;
  148. case CMD_GETWRITERMESS: // 获取作者们的留言
  149. _fnCMD_GETWRITERMESS(pInfo);
  150. break;
  151. case CMD_GETBUILDID: // 获取图像模块内部版本号
  152. _fnCMD_GETBUILDID(pInfo);
  153. break;
  154. case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的GIF文件
  155. _fnCMD_IS_VALID_FILE(pInfo);
  156. break;
  157. case CMD_GET_FILE_INFO: // 获取指定文件的信息
  158. _fnCMD_GET_FILE_INFO(pInfo);
  159. break;
  160. case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
  161. _fnCMD_LOAD_FROM_FILE(pInfo);
  162. break;
  163. case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
  164. _fnCMD_SAVE_TO_FILE(pInfo);
  165. break;
  166. case CMD_IS_SUPPORT: // 查询某个命令是否被支持
  167. _fnCMD_IS_SUPPORT(pInfo);
  168. break;
  169. case CMD_RESIZE: // 从新获取指定尺寸的图像位数据(只适用于矢量图像)
  170. _fnCMD_RESIZE(pInfo);
  171. break;
  172. default:
  173. pInfo->result = ER_ILLCOMM; // 非法命令
  174. ASSERT(FALSE); // 调用者的程序设计有问题 :-)
  175. break;
  176. }
  177. // 执行命令成功返回1, 失败返回0
  178. return (pInfo->result==ER_SUCCESS)? 1:0;
  179. }
  180. // 命令解释函数 — 第二层解释函数
  181. //********************************************************************//
  182. // 操作命令解释函数---解释:CMD_IS_SUPPORT命令
  183. // 查询某个命令是否被支持
  184. void _fnCMD_IS_SUPPORT(INFOSTR *pInfo)
  185. {
  186. ASSERT(pInfo->result == ER_EMPTY);
  187. switch(pInfo->annexdata.cmAnnData)  
  188. {
  189. case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
  190. pInfo->result = ER_SUCCESS;
  191. break;
  192. case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
  193. pInfo->result = ER_SUCCESS;
  194. break;
  195. case CMD_GETWRITERMESS: // 获取作者们的留言
  196. pInfo->result = ER_SUCCESS;
  197. break;
  198. case CMD_GETBUILDID: // 获取图像模块内部版本号
  199. pInfo->result = ER_SUCCESS;
  200. break;
  201. case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的WMF文件
  202. pInfo->result = ER_SUCCESS;
  203. break;
  204. case CMD_GET_FILE_INFO: // 获取指定文件的信息
  205. pInfo->result = ER_SUCCESS;
  206. break;
  207. case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
  208. pInfo->result = ER_SUCCESS;
  209. break;
  210. case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
  211. pInfo->result = ER_NOTSUPPORT;
  212. break;
  213. case CMD_IS_SUPPORT: // 查询某个命令是否被支持
  214. pInfo->result = ER_SUCCESS;
  215. break;
  216. case CMD_RESIZE: // 获取指定尺寸的图像(只适用于矢量图像)
  217. pInfo->result = ER_NOTSUPPORT;
  218. break;
  219. default:
  220. pInfo->result = ER_NOTSUPPORT;
  221. break;
  222. }
  223. }
  224. // 操作命令解释函数---解释:CMD_GETPROCTYPE命令
  225. // 获取本模块能处理的图像类型,如:BMP,PCX等等
  226. void _fnCMD_GETPROCTYPE(INFOSTR *pInfo)
  227. {
  228. // 这是预定义的函数代码,你可以不必修改的使用。
  229. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  230. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  231. ASSERT(pInfo->result == ER_EMPTY);
  232. // 复制能处理的类型字符串
  233. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)ModuleProcessImgType, 
  234. sizeof(ModuleProcessImgType));
  235. pInfo->result = ER_SUCCESS;
  236. }
  237. // 操作命令解释函数---解释:CMD_GETWRITER命令
  238. // 获取本模块的作者列表,多人时用逗号分隔
  239. void _fnCMD_GETWRITERS(INFOSTR *pInfo)
  240. {
  241. // 这是预定义的函数代码,你可以不必修改的使用。
  242. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  243. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  244. ASSERT(pInfo->result == ER_EMPTY);
  245. // 复制开发者名单串
  246. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterList, 
  247. sizeof(WriterList));
  248. pInfo->result = ER_SUCCESS;
  249. }
  250. // 操作命令解释函数---解释:CMD_GETWRITERMESS命令
  251. // 获取作者们的留言
  252. void _fnCMD_GETWRITERMESS(INFOSTR *pInfo)
  253. {
  254. // 这是预定义的函数代码,你可以不必修改的使用。
  255. // 根据接口定义,此时附加数据应被清空为0,所以下此断言
  256. ASSERT(pInfo->annexdata.scAnnData[0] == 0);
  257. ASSERT(pInfo->result == ER_EMPTY);
  258. // 复制开发者们的留言字符串
  259. ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterMess, 
  260. sizeof(WriterMess));
  261. pInfo->result = ER_SUCCESS;
  262. }
  263. // 操作命令解释函数---解释:CMD_GETBUILDID命令
  264. // 获取图像模块内部版本号
  265. void _fnCMD_GETBUILDID(INFOSTR *pInfo)
  266. {
  267. // 这是预定义的函数代码,你可以不必修改的使用。
  268. // 根据接口定义,此时annexdata.dwAnnData应被设为0,所以下此断言
  269. ASSERT(pInfo->annexdata.dwAnnData == 0);
  270. ASSERT(pInfo->result == ER_EMPTY);
  271. // 填写内部版本号码
  272. pInfo->annexdata.dwAnnData = MODULE_BUILDID;
  273. pInfo->result = ER_SUCCESS;
  274. }
  275. // 操作命令解释函数---解释:CMD_IS_VALID_FILE命令
  276. // 判断指定文件是否是有效的WMF文件
  277. void _fnCMD_IS_VALID_FILE(INFOSTR *pInfo)
  278. {
  279. CFile file;
  280. GIFHEADER gifheader;
  281. DWORD dwSize;
  282. UINT uRet;
  283. // 检验入口参数是否符合接口定义
  284. ASSERT(pInfo->result == ER_EMPTY);
  285. ASSERT(pInfo->annexdata.iAnnData == 0);
  286. ASSERT(::strlen(pInfo->filename));
  287. ASSERT(pInfo->state == PKST_NOTVER);
  288. ASSERT(pInfo);
  289. // 设初值
  290. pInfo->result = ER_SUCCESS;
  291. pInfo->annexdata.iAnnData = 0;
  292. // 先判断指定的文件是否存在
  293. if (!IsFileExist(pInfo->filename))
  294. pInfo->result = ER_COMMINFOERR;
  295. else
  296. {
  297. // 打开指定文件
  298. if (!file.Open(pInfo->filename, CFile::modeRead))
  299. {
  300. pInfo->result = ER_FILERWERR; // 打开文件时出错
  301. return;
  302. }
  303. // 获取文件的长度(以字节为单位)
  304. dwSize = file.GetLength();
  305. // 用长度判断
  306. if (dwSize < sizeof(GIFHEADER))
  307. {
  308. // 这不是一个GIF文件,因为GIF文件的长度起码大于GIF文件头
  309. // 结构的长度
  310. file.Close();
  311. return;
  312. }
  313. // 读取GIF文件信息头结构,并检查它的有效性
  314. file.SeekToBegin();
  315. uRet  = file.Read((LPSTR)&gifheader, sizeof(GIFHEADER));
  316. if (uRet != sizeof(GIFHEADER))
  317. {
  318. // 读文件时出错
  319. pInfo->result = ER_FILERWERR;
  320. file.Close();
  321. return;
  322. }
  323. // 判断文件标志
  324. if ((::memcmp((const void*)(gifheader.Signature), (const void*)GIF87a, sizeof(GIFVERSIZE)) != 0)&&
  325. (::memcmp((const void*)(gifheader.Signature), (const void*)GIF89a, sizeof(GIFVERSIZE)) != 0))
  326. {
  327. file.Close();
  328. return;
  329. }
  330. // 到此,大致可以表明该文件是一个GIF文件,iAnnData变量设为1
  331. pInfo->annexdata.iAnnData = 1;
  332. // 表示通过校验
  333. pInfo->state = PKST_PASSVER;
  334. file.Close();
  335. }
  336. }
  337. // 操作命令解释函数---解释:CMD_GET_FILE_INFO命令
  338. // 获取指定文件的信息
  339. // 注:此时数据包中的imginfo结构并没有真正填写完,图像的类型
  340. //     图像的个数、及图像是否可被编辑等值都是暂设的。
  341. void _fnCMD_GET_FILE_INFO(INFOSTR *pInfo)
  342. {
  343. CFile file;
  344. CFileStatus status;
  345. PBYTE pFileContent;
  346. DWORD dwFileLen, uRet;
  347. GIFHEADER *gifheader;
  348. // 检验入口参数是否符合接口定义
  349. ASSERT(pInfo->result == ER_EMPTY);
  350. ASSERT(::strlen(pInfo->filename));
  351. // 此时,该文件必需是一个已存在的、并且是有效的GIF文件
  352. ASSERT(pInfo->state == PKST_PASSVER);
  353. // 客户模块必需要先将imginfo清空为0
  354. ASSERT(pInfo->imginfo.imgtype == IMT_NULL);
  355. // 打开指定文件
  356. if (!file.Open(pInfo->filename, CFile::modeRead))
  357. {
  358. pInfo->result = ER_FILERWERR;
  359. return;
  360. }
  361. // 获取文件长度
  362. dwFileLen = file.GetLength();
  363. // 分配内存,用于存放所有的GIF数据
  364. pFileContent = (PBYTE)::GlobalAlloc(GPTR, dwFileLen+1);
  365. if (!pFileContent)
  366. {
  367. file.Close();
  368. pInfo->result = ER_MEMORYERR;
  369. return;
  370. }
  371. file.SeekToBegin();
  372. // 读取整个的GIF文件到内存中
  373. uRet = file.ReadHuge((void*)pFileContent, dwFileLen);
  374. if (uRet != dwFileLen)
  375. {
  376. ::GlobalFree(pFileContent);
  377. file.Close();
  378. pInfo->result = ER_FILERWERR;
  379. return;
  380. }
  381. gifheader = (GIFHEADER*)pFileContent;
  382. // 这个文件应该已经被校验过的,也就是说应该是有效的GIF文件
  383. ASSERT(gifheader->Signature[0] == 'G');
  384. // 获取GIF文件中的图像个数
  385. int imgcount = _get_imgcount(pFileContent, dwFileLen);
  386. if (imgcount == 0) // 受损的GIF图像文件
  387. {
  388. ::GlobalFree(pFileContent);
  389. file.Close();
  390. pInfo->result = ER_BADIMAGE;
  391. return;
  392. }
  393. LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo;
  394. // 获取文件的长度、图像的宽度、高度等信息
  395. lpImgInfoStr->imgtype = (imgcount == 1) ? IMT_RESSTATIC:IMT_RESDYN;
  396. lpImgInfoStr->imgformat = IMF_GIF;
  397. lpImgInfoStr->filesize = dwFileLen;
  398. // 以下的宽度、高度是指GIF虚拟屏幕的宽、高
  399. lpImgInfoStr->width = gifheader->ScreenWidth;
  400. lpImgInfoStr->height = gifheader->ScreenHeight;
  401. // 获取位深度值
  402. lpImgInfoStr->bitcount = ((gifheader->GlobalFlagByte&0x70)>>4)+1;
  403. lpImgInfoStr->compression = ICS_GIFLZW;
  404. // 每一图像行所占的字节数(GIF中,此值没有意义,所以设为0)
  405. lpImgInfoStr->linesize = 0;
  406. // 图像的个数(如果是动态GIF,图像个数中将包括背景图像,所以要再加一)
  407. lpImgInfoStr->imgnumbers = (imgcount == 1) ? 1:imgcount+1;
  408. // 表示是否可被编辑(动画GIF将不能被编辑,所以设为1)
  409. lpImgInfoStr->imgchang = (imgcount == 1) ? 0:1;
  410. // 获取文件最后的修改日期(月在高字节,日在低字节)
  411. file.GetStatus(status);
  412. lpImgInfoStr->year = (WORD)status.m_mtime.GetYear();
  413. lpImgInfoStr->monday = (WORD)status.m_mtime.GetMonth();
  414. lpImgInfoStr->monday <<= 8;
  415. lpImgInfoStr->monday |= (WORD)status.m_mtime.GetDay();
  416. // 获取文件最后的修改时间(字序:最高—0, 2—时,1—分,0—秒)
  417. lpImgInfoStr->time = status.m_mtime.GetHour();
  418. lpImgInfoStr->time <<= 8;
  419. lpImgInfoStr->time |= status.m_mtime.GetMinute();
  420. lpImgInfoStr->time <<= 8;
  421. lpImgInfoStr->time |= status.m_mtime.GetSecond();
  422. lpImgInfoStr->time &= 0xffffff;
  423. ::GlobalFree(pFileContent);
  424. file.Close();
  425. // 设置出口数据
  426. pInfo->state = PKST_PASSINFO;
  427. pInfo->result = ER_SUCCESS;
  428. // 恢复初始值
  429. ::ZeroMemory((PVOID)&m_GifInfo, sizeof(GIFINFO));
  430. m_CurPalSize = 0; // 当前调色板项数(针对于局部调色板)
  431. m_CurDM = 0; // 当前的处置方法
  432. m_CurUserInput = 0; // 当前的用户输入标志
  433. m_CurTColorIndex = -1; // 当前的透明色索引号(-1表示无效)
  434. m_CurDelayTime = 0; // 当前的延迟时间(0表示没有延时)
  435. m_CurSaveMode = 0; // 当前的图像存储模式
  436. m_CurX = m_CurY = 0; // 当前图像在虚拟屏幕中的位置
  437. m_CurWidth = m_CurHeight = 0; // 当前图像的宽度、高度
  438. m_CurImgIndex = 0; // 当前图像的序号(0基)
  439. return;
  440. }
  441. // 操作命令解释函数---解释:CMD_LOAD_FROM_FILE命令
  442. // 从指定图像文件中读取数据
  443. void _fnCMD_LOAD_FROM_FILE(INFOSTR *pInfo)
  444. {
  445. // 检验入口参数是否符合接口定义
  446. ASSERT(pInfo->result == ER_EMPTY);
  447. ASSERT(::strlen(pInfo->filename));
  448. // 此时,该文件必需是一个已存在的、有效的GIF文件,并且数据包中
  449. // 含有该文件的信息(imginfo结构中)
  450. ASSERT(pInfo->state == PKST_PASSINFO);
  451. ASSERT(pInfo->imginfo.imgformat == IMF_GIF);
  452. ASSERT(pInfo->pImgInfo == NULL);
  453. // 必需设置标准图像格式信息
  454. ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
  455. ASSERT(pInfo->pLineAddr != NULL);
  456. ASSERT(pInfo->_pbdata != NULL);
  457. // 必需没有子图像链表
  458. ASSERT(pInfo->psubimg == NULL);
  459. CFile file;
  460. DWORD dwFileLen, uRet;
  461. PBYTE pFileContent;
  462. if (pInfo->fpProgress)
  463. {
  464. if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 6))
  465. { // 如果进度函数返回1,则说明用户想中断操作,返回。
  466. pInfo->result = ER_USERBREAK;
  467. return;
  468. }
  469. }
  470. // 打开指定文件
  471. if (!file.Open(pInfo->filename, CFile::modeRead))
  472. {
  473. pInfo->result = ER_FILERWERR;
  474. return;
  475. }
  476. // 获取文件长度
  477. dwFileLen = file.GetLength();
  478. // 分配内存,用于存放所有的GIF数据
  479. pFileContent = (PBYTE)::GlobalAlloc(GPTR, dwFileLen+1);
  480. if (!pFileContent)
  481. {
  482. file.Close();
  483. pInfo->result = ER_MEMORYERR;
  484. return;
  485. }
  486. file.SeekToBegin();
  487. // 读取整个的GIF文件到内存中
  488. uRet = file.ReadHuge((void*)pFileContent, dwFileLen);
  489. if (uRet != dwFileLen)
  490. {
  491. ::GlobalFree(pFileContent);
  492. file.Close();
  493. pInfo->result = ER_FILERWERR;
  494. return;
  495. }
  496. // 关闭GIF文件
  497. file.Close();
  498. // 读取并转换图像到数据包中
  499. if (LoadGIF(pFileContent, dwFileLen, pInfo) == TRUE)
  500. {
  501. // 成功
  502. pInfo->state = PKST_INFOANDBITS;
  503. pInfo->modify = 0;
  504. pInfo->result = ER_SUCCESS;
  505. }
  506. // 释放内存
  507. ::GlobalFree(pFileContent);
  508. // 恢复初始值
  509. ::ZeroMemory((PVOID)&m_GifInfo, sizeof(GIFINFO));
  510. m_CurPalSize = 0; // 当前调色板项数(针对于局部调色板)
  511. m_CurDM = 0; // 当前的处置方法
  512. m_CurUserInput = 0; // 当前的用户输入标志
  513. m_CurTColorIndex = -1; // 当前的透明色索引号(-1表示无效)
  514. m_CurDelayTime = 0; // 当前的延迟时间(0表示没有延时)
  515. m_CurSaveMode = 0; // 当前的图像存储模式
  516. m_CurX = m_CurY = 0; // 当前图像在虚拟屏幕中的位置
  517. m_CurWidth = m_CurHeight = 0; // 当前图像的宽度、高度
  518. m_CurImgIndex = 0; // 当前图像的序号(0基)
  519. m_pSubimgHead = NULL; // 子图像链表的头
  520. m_pSubimgTail = NULL; // 子图像链表的尾
  521. if (pInfo->fpProgress) // 结束进度条,此调用不再支持用户中断
  522. (*pInfo->fpProgress)(RWPROGRESSSIZE, RWPROGRESSSIZE);
  523. }
  524. // 操作命令解释函数---解释:CMD_SAVE_TO_FILE命令
  525. // 将数据保存到指定文件中
  526. void _fnCMD_SAVE_TO_FILE(INFOSTR *pInfo)
  527. {
  528. // 这个命令不一定要解释,你可以参考本图像格式的具体境况来决定
  529. // 是否解释该命令。
  530. // 如果你想解释该命令,请在下面加入代码,并修改pInfo->result的返回值:
  531. // ----------------------------------------------------------------->
  532. pInfo->result = ER_NOTSUPPORT;
  533. }
  534. // 操作命令解释函数---解释:CMD_RESIZE命令
  535. // 重新获取指定尺寸的图像位数据(只适用于矢量图像)
  536. void _fnCMD_RESIZE(INFOSTR *pInfo)
  537. {
  538. // 这个命令一般的图像读写模块不需要支持,它只适用于矢量图像,
  539. // 比如WMF、EMF之类。
  540. // 如果你想解释该命令,请在下面加入代码,并修改pInfo->result的返回值:
  541. // ----------------------------------------------------------------->
  542. pInfo->result = ER_NOTSUPPORT;
  543. }
  544. /*************************************************************************
  545.  *
  546.  * IsFileExist()
  547.  * 
  548.  * 参数说明:
  549.  *
  550.  * char *lpFileName - 待判断的文件路径和名称(文件名)
  551.  *
  552.  * 返回值:
  553.  *
  554.  * BOOL - 如果指定的文件存在返回TRUE,否则返回FALSE。
  555.  * 
  556.  * 描述:
  557.  *
  558.  * 判断指定的文件是否存在
  559.  * 
  560.  * 该文件必需可以被读和写
  561.  *
  562.  ************************************************************************/
  563. BOOL IsFileExist(char *lpFileName)
  564. {
  565. CFile file;
  566. BOOL bExist = FALSE; // 文件存在是TRUE,不存在是FALSE
  567. CFileException e;
  568. // 确定指定的文件是否存在
  569. if (file.Open(lpFileName, CFile::modeReadWrite|CFile::shareDenyNone, &e))
  570. {
  571. bExist = TRUE;
  572. file.Close();
  573. }
  574. else
  575. {
  576. // 可能有其他程序正在处理此文件
  577. switch(e.m_cause)
  578. {
  579. case CFileException::tooManyOpenFiles:
  580. case CFileException::accessDenied:
  581. case CFileException::sharingViolation:
  582. case CFileException::lockViolation:
  583. return TRUE;
  584. case CFileException::fileNotFound:
  585. case CFileException::badPath:
  586. case CFileException::invalidFile:
  587. case CFileException::hardIO:
  588. default:
  589. return FALSE;
  590. }
  591. }
  592. return bExist;
  593. }
  594. // 返回TRUE表示读取成功,FALSE表示失败,同时数据包置错误信息
  595. BOOL LoadGIF(PBYTE pFileContent, DWORD filesize, LPINFOSTR pInfo)
  596. {
  597. //获取GIF文件的相关信息
  598. UINT HeaderSize = AnalizeFileHeader(pFileContent, filesize);
  599. if (HeaderSize == 0)
  600. {
  601. // 表明该文件是一个受损的文件
  602. pInfo->result = ER_BADIMAGE;
  603. return FALSE;
  604. }
  605. // 设置背景图像
  606. RGBQUAD * pBKColor = (RGBQUAD*)&(m_GlobalPal[m_GifInfo.bkindex]);
  607. int i,j;
  608. switch(_get_desformat(pInfo))
  609. {
  610. case DF_16_555: // 16位555格式(也就是15位图像)
  611. {
  612. WORD bkc555 = _cnv_rgb_to_555(pBKColor->rgbRed, pBKColor->rgbGreen, 
  613. pBKColor->rgbBlue);
  614. WORD *pPix555;
  615. for (i=0;i<(int)pInfo->imginfo.height;i++)
  616. {
  617. pPix555 = (WORD*)(pInfo->pLineAddr[i]);
  618. for(j=0;j<(int)pInfo->imginfo.width;j++)
  619. *pPix555++ = bkc555;
  620. }
  621. }
  622. break;
  623. case DF_16_565: // 16位565格式
  624. {
  625. WORD bkc565 = _cnv_rgb_to_565(pBKColor->rgbRed, pBKColor->rgbGreen, 
  626. pBKColor->rgbBlue);
  627. WORD *pPix565;
  628. for (i=0;i<(int)pInfo->imginfo.height;i++)
  629. {
  630. pPix565 = (WORD*)(pInfo->pLineAddr[i]);
  631. for(j=0;j<(int)pInfo->imginfo.width;j++)
  632. *pPix565++ = bkc565;
  633. }
  634. }
  635. break;
  636. case DF_24: // 24位格式
  637. {
  638. PBYTE pPix24;
  639. for (i=0;i<(int)pInfo->imginfo.height;i++)
  640. {
  641. pPix24 = (PBYTE)(pInfo->pLineAddr[i]);
  642. for(j=0;j<(int)pInfo->imginfo.width;j++)
  643. {
  644. *pPix24++ = pBKColor->rgbBlue;
  645. *pPix24++ = pBKColor->rgbGreen;
  646. *pPix24++ = pBKColor->rgbRed;
  647. }
  648. }
  649. }
  650. break;
  651. case DF_32: // 32位格式
  652. {
  653. DWORD bkc32 = _cnv_rgb_to_888(pBKColor->rgbRed, pBKColor->rgbGreen, 
  654. pBKColor->rgbBlue);
  655. DWORD *pPix32;
  656. for (i=0;i<(int)pInfo->imginfo.height;i++)
  657. {
  658. pPix32 = (DWORD*)(pInfo->pLineAddr[i]);
  659. for(j=0;j<(int)pInfo->imginfo.width;j++)
  660. *pPix32++ = bkc32;
  661. }
  662. }
  663. break;
  664. }
  665. m_CurTColorIndex = -1;
  666. m_CurDelayTime = 0;
  667. // 跨过头结构
  668. PBYTE p = pFileContent+HeaderSize;
  669. UINT  Offset;
  670. while (1)
  671. {
  672. if (p[0] == 0x21 && p[1] == 0xf9 && p[2] == 0x04)
  673. {// 图形扩展块
  674. Offset = GetGrphContent(p);
  675. p += Offset;
  676. }
  677. else if (p[0] == 0x21 && p[1] == 0x01 && p[2] == 0x0c)
  678. {// 文本扩展块
  679. Offset = ShowText(p);
  680. p += Offset;
  681. }
  682. else if (p[0] == 0x21 && p[1] == 0xff && p[2] == 0x0b)
  683. {// 应用程序扩展块
  684. Offset = GetAppContent(p);
  685. p += Offset;
  686. }
  687. else if (p[0] == 0x21 && p[1] == 0xfe)
  688. {// 注释扩展块
  689.    Offset = GetNoteContent(p);
  690.    p += Offset;
  691. }
  692. else if (p[0] == 0x2c)
  693. {// 图像描述符+[局部调色板]+图像数据块
  694.    Offset = GetImage(p, pInfo);
  695.    p += Offset;
  696. }
  697. else break;
  698. if (Offset == 0)
  699. {
  700. // 内存不足,失败
  701. _clear_list();
  702. pInfo->result = ER_MEMORYERR;
  703. return FALSE;
  704. }
  705. if (((DWORD)p-(DWORD)pFileContent) > filesize)
  706. {
  707. // 表明该文件是一个受损的文件
  708. _clear_list();
  709. pInfo->result = ER_BADIMAGE;
  710. return FALSE;
  711. }
  712. }
  713. // 子图像链表指针
  714. pInfo->psubimg = m_pSubimgHead;
  715. return TRUE;
  716. }
  717. /***************************************************************************
  718. * AnalizeFileHeader - 获得GIF文件信息
  719. *
  720. * Parameter: PBYTE - 完整的GIF文件数据首指针
  721. *              DWORD - GIF文件的长度
  722. *
  723. * Result   : UINT  - GIF文件头结构尺寸(包括虚拟屏幕结构及全局调色板)
  724. *    如果返回0,则说明GIF文件是一个受损的文件
  725. ***************************************************************************/
  726. UINT AnalizeFileHeader(PBYTE pFileContent, DWORD filesize)
  727. {
  728. ASSERT(filesize > sizeof(GIFHEADER));
  729. GIFHEADER gifHeader; //文件头
  730. UINT uRet = sizeof(GIFHEADER);
  731. memcpy(&gifHeader,pFileContent,sizeof(GIFHEADER));
  732. // 取得图像(逻辑屏幕)的宽度、高度
  733. m_GifInfo.Width  = gifHeader.ScreenWidth ;
  734. m_GifInfo.Height = gifHeader.ScreenHeight ;
  735. // 获取图像位深度
  736. m_GifInfo.BitCount  = ((gifHeader.GlobalFlagByte&0x70)>>4)+1;
  737. // 获取GIF背景色索引
  738. m_GifInfo.bkindex = gifHeader.BackGroundColor;
  739. // 单个压缩数据初始位数
  740. m_GifInfo.InitPixelBits = (gifHeader.GlobalFlagByte&0x7)+2;
  741. // 获得图像的颜色个数
  742. m_GifInfo.ColorNum = 1<<((gifHeader.GlobalFlagByte&0x7)+1);
  743. if (gifHeader.GlobalFlagByte&0x80)
  744. // 有全局调色板
  745. LPGIFRGB pRGB = (LPGIFRGB)(pFileContent+sizeof(GIFHEADER));
  746. for (int j=0;j<m_GifInfo.ColorNum;j++)
  747. {
  748. m_GlobalPal[j].rgbRed       = pRGB[j].bRed;
  749. m_GlobalPal[j].rgbGreen     = pRGB[j].bGreen;
  750. m_GlobalPal[j].rgbBlue      = pRGB[j].bBlue;
  751. m_GlobalPal[j].rgbReserved  = 0;
  752. }
  753. // 跨过全局调色板
  754. uRet += m_GifInfo.ColorNum*sizeof(GIFRGB);
  755. if (uRet >= filesize)
  756. uRet = 0; // 说明文件太小,可能是一个受损的GIF文件
  757. }
  758. return uRet;
  759. }
  760. // 处理图形扩展块
  761. UINT GetGrphContent(PBYTE pGrCtrl)
  762. {
  763. ASSERT(pGrCtrl);
  764. GRAPHCTRL GraphCtrl;
  765. memcpy(&GraphCtrl,pGrCtrl,sizeof(GRAPHCTRL));
  766. BYTE Flag = GraphCtrl.PackedField; // 包装域
  767. m_CurDM = (int)((BYTE)(Flag&0x1c)>>2); // 处置方式
  768. m_CurUserInput = (int)((BYTE)(Flag&0x2)>>1); // 用户输入标志
  769. m_CurDelayTime = GraphCtrl.DelayTime; // 延迟时间
  770. if (Flag&1) // 判断是否有透明色
  771.    m_CurTColorIndex = GraphCtrl.TranColorIndex;
  772. else
  773. m_CurTColorIndex = -1;
  774. return sizeof(GRAPHCTRL);
  775. }
  776. // 处理文本扩展块
  777. UINT ShowText(PBYTE pText)
  778. {
  779. ASSERT(pText);
  780. TEXTCTRL TextCtrl;
  781. memcpy(&TextCtrl,pText,sizeof(TEXTCTRL));
  782. return sizeof(TEXTCTRL)+TextCtrl.Data[0]-256+1;
  783. }
  784. // 处理应用程序扩展块
  785. UINT GetAppContent(PBYTE pApp)
  786. {
  787. ASSERT(pApp);
  788. APPCTRL AppCtrl;
  789. memcpy(&AppCtrl,pApp,sizeof(APPCTRL));
  790. return sizeof(APPCTRL)+AppCtrl.Data[0]-256+1;
  791. }
  792. // 处理注释扩展块
  793. UINT GetNoteContent(PBYTE pNote)
  794. {
  795. ASSERT(pNote);
  796. NOTEHCTRL NoteCtrl;
  797. memcpy(&NoteCtrl,pNote,sizeof(NOTEHCTRL));
  798. return sizeof(NOTEHCTRL)+NoteCtrl.Data[0]-256+1;
  799. }
  800. // 处理图像数据区
  801. UINT GetImage(PBYTE pData, LPINFOSTR pInfo)
  802. {
  803. ASSERT(pData);
  804. IMAGEDATAINFO ImageData;
  805. // 提取图像描述
  806. memcpy(&ImageData,pData,sizeof(IMAGEDATAINFO));
  807. PBYTE p = pData+sizeof(IMAGEDATAINFO);
  808. UINT PalSize;
  809. m_CurX = ImageData.ImageLeft;
  810. m_CurY = ImageData.ImageTop ;
  811. m_CurWidth  = ImageData.ImageWidth ;
  812. m_CurHeight = ImageData.ImageHeight;
  813. // 判断是否有局部调色板
  814. if (ImageData.LocalFlagByte&0x80)
  815. LPGIFRGB pRGB = (LPGIFRGB)p;
  816. // 计算局部调色版的项数
  817. m_CurPalSize  = 1<<((ImageData.LocalFlagByte&0x7)+1);
  818. // 有关文档对这个值描述的不是很清楚,为保险起见作了
  819. // 如下判断。
  820. if ((m_CurPalSize <= 0)||(m_CurPalSize > 256))
  821. m_CurPalSize = m_GifInfo.ColorNum;
  822. for (int j=0;j<m_CurPalSize;j++)
  823. {
  824. m_CurRgbQuad[j].rgbRed       = pRGB[j].bRed;
  825. m_CurRgbQuad[j].rgbGreen     = pRGB[j].bGreen;
  826. m_CurRgbQuad[j].rgbBlue      = pRGB[j].bBlue;
  827. m_CurRgbQuad[j].rgbReserved  = 0;
  828. }
  829. // 计算调色板尺寸(字节数)
  830. PalSize = m_CurPalSize*sizeof(GIFRGB);
  831. // 跨过局部调色板
  832. p += PalSize;
  833. }
  834. else
  835. {
  836. // 如果没有局部调色板,用全局调色板数据替代
  837. m_CurPalSize = m_GifInfo.ColorNum;
  838. memcpy((void*)m_CurRgbQuad, (void*)m_GlobalPal, m_CurPalSize*sizeof(RGBQUAD));
  839. PalSize = 0;
  840. }
  841. // 设置图像存储模式标志
  842. if (ImageData.LocalFlagByte&0x40)
  843. m_CurSaveMode = 1; // 交叉存储
  844. else
  845. m_CurSaveMode = 0; // 顺序存储
  846. UINT InitBits = *p++;//跳过第一字节,进入真正的段落
  847. UINT offset; // 数据区在文件中的尺寸(将包括GIF附加的描述符)
  848. // 获取当前数据区的尺寸(纯数据尺寸)
  849. UINT dataCount = GetCodeCountOnChar(p, offset);
  850. // 获取当前数据区内容
  851. PBYTE pCodeData = GetCodeDataOnChar(p, dataCount);
  852. if (!pCodeData)
  853. return 0;
  854. // 提取真实数据,所有数据存为字符大小
  855. PBYTE pTrueCodeData = GetCodeDataOnBits(pCodeData, 
  856. m_GifInfo.InitPixelBits, dataCount);
  857. if (!pTrueCodeData)
  858. {
  859. ::GlobalFree(pCodeData);
  860. return 0;
  861. }
  862. ::GlobalFree(pCodeData);
  863. // 将GIF图像数据保存(并转化)到子图像链表中
  864. BOOL bRet;
  865. if (pInfo->imginfo.imgnumbers > 1) // 多帧GIF图像
  866. bRet = ConvertToBmpImage(pTrueCodeData, pInfo);
  867. else // 单帧GIF图像
  868. bRet = ConvertToBackgroup(pTrueCodeData, pInfo);
  869. ::GlobalFree(pTrueCodeData);
  870. if (bRet == FALSE)
  871. return 0;
  872. else
  873. return sizeof(IMAGEDATAINFO) + offset + PalSize;
  874. }
  875. // 计算图像位数据的尺寸
  876. UINT GetCodeCountOnChar (PBYTE CodeDataStr,UINT &AllDataLen)
  877. {
  878. UINT dataCount = 0;
  879. BYTE dataLen;
  880. PBYTE p1 = CodeDataStr;
  881. AllDataLen = 0;
  882. while(1)
  883. {
  884. dataLen = *p1++; // 提取长度描述字节值,并后移指针
  885. p1 += dataLen;
  886. dataCount += dataLen;
  887. AllDataLen += (dataLen+1); // 数据子块长度加长度描述字节
  888. if (dataLen == 0x00) break;
  889. }
  890. AllDataLen ++; // 跨过LZW初始位值的一个字节
  891. return dataCount;
  892. }
  893. // 将GIF中的纯LZW图像数据提取到新的内存块中
  894. PBYTE GetCodeDataOnChar(PBYTE CodeDataStr, UINT dataCount)
  895. {
  896. ASSERT(CodeDataStr);
  897. PBYTE pData = (PBYTE)::GlobalAlloc(GPTR, dataCount+1);
  898. if (!pData)
  899. return NULL;
  900. PBYTE p2 = pData;
  901. PBYTE p1 = CodeDataStr;
  902. BYTE  dataLen;
  903. while (1)
  904. {
  905. dataLen = *p1++;
  906. if (dataLen == 0x00) 
  907. break;
  908. memcpy(p2,p1,dataLen);
  909. p1 += dataLen;
  910. p2 += dataLen;
  911. }
  912. return pData;
  913. }
  914. // 将指定的LZW数据解压为位图数据
  915. PBYTE  GetCodeDataOnBits (PBYTE CodeDataStr ,UINT InitLen ,UINT &CodeDataLen)
  916. {
  917. ASSERT(CodeDataStr);
  918. PBYTE pData = (PBYTE)::GlobalAlloc(GPTR ,m_CurWidth*m_CurHeight*2);
  919. if (!pData)
  920. return NULL;
  921. PBYTE p = CodeDataStr;
  922. PBYTE pTrueData = pData;
  923. int i = 0;
  924. UINT BitsCount = 0;
  925. WORD TCode,s = m_GifInfo.ColorNum+2;//起始的代码值
  926. UINT TableLen,iLen = InitLen;
  927. UINT Pos,index,j = 0;
  928. UINT SrcCodeLEN = CodeDataLen;
  929. while (1)
  930. {
  931. TCode = GetOneCode(p, CodeDataLen,BitsCount/8, BitsCount%8, iLen);
  932. BitsCount += iLen;
  933. if (TCode < m_GifInfo.ColorNum)
  934. {
  935. LZWTable[j].Header = TCode;
  936. LZWTable[j].Code   = s ++;
  937. if (j != 0)
  938. {
  939. LZWTable[j - 1].Tail = TCode;
  940. }
  941. j++;
  942. }
  943. else if (TCode > m_GifInfo.ColorNum + 1) // 代码
  944. {
  945. if (j == 0) continue;
  946. LZWTable[j].Header = TCode;
  947. LZWTable[j].Code   = s ++;
  948. ASSERT( LZWTable[j].Header < LZWTable[j].Code);
  949. index = j - 1;
  950. Pos = j;
  951. while (1)
  952. {
  953. Pos = LZWTable[Pos].Header - (m_GifInfo.ColorNum + 2) ;
  954. if (LZWTable[Pos].Header < m_GifInfo.ColorNum) 
  955. break;
  956. }
  957. LZWTable[index].Tail  = LZWTable[Pos].Header;
  958. j++;
  959. }
  960. else if (TCode == m_GifInfo.ColorNum) // 清除码
  961. {
  962. iLen = InitLen;
  963. TableLen = j;
  964. j = 0;
  965. if (GetPartImageDataFromTable(pData,LZWTable,TableLen) == FALSE)
  966. {
  967. ::GlobalFree(pTrueData);
  968. return NULL;
  969. }
  970. //pData+=TableLen;
  971. s = m_GifInfo.ColorNum + 2 ;
  972. }
  973. else if (TCode == m_GifInfo.ColorNum + 1) // 结束码
  974. {
  975. //end build table
  976. iLen = InitLen;
  977. TableLen = j;
  978. if (GetPartImageDataFromTable(pData,LZWTable,TableLen) == FALSE)
  979. {
  980. ::GlobalFree(pTrueData);
  981. return NULL;
  982. }
  983. //pData+=TableLen;
  984. s = m_GifInfo.ColorNum + 2;
  985. break;
  986. }
  987. if (s == 3)
  988. iLen = 2;
  989. else if (s == 5)
  990. iLen = 3;
  991. else if (s == 9)
  992. iLen = 4;
  993. else if (s == 17)
  994. iLen = 5;
  995. else if (s == 33)
  996. iLen = 6;
  997. else if (s == 65)
  998. iLen = 7;
  999. else if (s == 129)
  1000. iLen  = 8;
  1001. else if (s == 257)
  1002. iLen  = 9;
  1003. else if ( s == 513 ) 
  1004. iLen = 10;
  1005. else if (s == 1025 ) 
  1006. iLen = 11;
  1007. else if (s == 2049 ) 
  1008. iLen = 12;
  1009. if (BitsCount/8 > SrcCodeLEN)
  1010. {
  1011. iLen = InitLen;
  1012. TableLen = j;
  1013. if (GetPartImageDataFromTable(pData,LZWTable,TableLen) == FALSE)
  1014. {
  1015. ::GlobalFree(pTrueData);
  1016. return NULL;
  1017. }
  1018. //pData+=TableLen;
  1019. s = m_GifInfo.ColorNum + 2;
  1020. break;
  1021. }
  1022. }
  1023. CodeDataLen = BitsCount/8;
  1024. return pTrueData;
  1025. }
  1026. WORD GetOneCode(PBYTE CodeStr ,UINT CodeStrLen, UINT OffsetChar, 
  1027. UINT OffsetBits, UINT Length)
  1028. {
  1029. ASSERT (Length <= 12);
  1030. PBYTE pValue;
  1031. PBYTE lp = CodeStr;
  1032. DWORD value = 0;
  1033. pValue = (PBYTE)&value;
  1034. pValue[0] = lp[OffsetChar+0];
  1035. if (OffsetChar + 1 < CodeStrLen)
  1036. pValue[1] = lp[OffsetChar+1];
  1037. if (OffsetChar + 2 < CodeStrLen)
  1038. pValue[2] = lp[OffsetChar+2];
  1039. if (OffsetChar + 3 < CodeStrLen)
  1040. pValue[3] = lp[OffsetChar+3];
  1041. value = value >> OffsetBits;
  1042. value = value << (32 - Length);
  1043. value = value >> (32 - Length);
  1044. return (WORD)value;
  1045. }
  1046. //
  1047. BOOL GetPartImageDataFromTable(PBYTE &pImage, LZWTABLE *Table, UINT TableLen)
  1048. {
  1049. UINT i;
  1050. PBYTE p = pImage;
  1051. WORD *TailStack = (WORD*)::GlobalAlloc(GPTR, LZWTABLESIZE*sizeof(WORD));
  1052. if (!TailStack)
  1053. return FALSE;
  1054. int j;
  1055. int sp;
  1056. for (i = 0 ; i < TableLen; i++)
  1057. {
  1058. if (Table[i].Header < m_GifInfo.ColorNum)
  1059. {
  1060. *p++ = (BYTE)Table[i].Header ;
  1061. }
  1062. else
  1063. {
  1064. sp = 0;
  1065. j = Table[i].Header - (m_GifInfo.ColorNum + 2);
  1066. while (Table[j].Header > m_GifInfo.ColorNum + 1)
  1067. {
  1068. TailStack[sp++] = Table[j].Tail ;
  1069. j = Table[j].Header;
  1070. j -= (m_GifInfo.ColorNum + 2);
  1071. ASSERT(sp < LZWTABLESIZE);
  1072. }
  1073. *p++ = (BYTE)Table[j].Header;
  1074. *p++ = (BYTE)Table[j].Tail;
  1075. sp --;
  1076. while (sp >= 0)
  1077. {
  1078. *p++ = (BYTE)TailStack[sp--];
  1079. }
  1080. }
  1081. }
  1082. int len = p - pImage;
  1083. pImage = p;
  1084. ::GlobalFree(TailStack);
  1085. return TRUE;
  1086. }
  1087. // 将GIF图像保存到数据包背景图像中(只针对单帧GIF图像)
  1088. BOOL ConvertToBackgroup(PBYTE SrcData,LPINFOSTR lpInfo)
  1089. {
  1090. ASSERT(SrcData);
  1091. ASSERT(lpInfo->imginfo.imgnumbers == 1);
  1092. PBYTE p2,pTmp;
  1093. PBYTE pSrcData = SrcData;
  1094. int i,j,k,Step,index;
  1095. if (m_CurSaveMode )//交叉存储
  1096. {
  1097. pTmp = p2 = (PBYTE)::GlobalAlloc(GPTR, m_CurWidth*m_CurHeight);
  1098. if (!pTmp)
  1099. return FALSE;
  1100. k = 0; Step = 8;
  1101. for (j = 0; j < m_CurHeight  ; j ++)
  1102. {
  1103. memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
  1104. k += Step;
  1105. if (k >= m_CurHeight) break;
  1106. }
  1107. j++;//每行中存了一个越界值
  1108. k = 4; Step = 8;
  1109. for (; j < m_CurHeight  ; j ++)
  1110. {
  1111. memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
  1112. k += Step;
  1113. if (k >= m_CurHeight) break;
  1114. }
  1115. j++;
  1116. k = 2; Step = 4;
  1117. for (; j < m_CurHeight  ; j ++)
  1118. {
  1119. memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
  1120. k += Step;
  1121. if (k >= m_CurHeight) break;
  1122. }
  1123. j++;
  1124. k = 1; Step = 2;
  1125. for (; j < m_CurHeight  ; j ++)
  1126. {
  1127. memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_GifInfo.Width);
  1128. k += Step;
  1129. if (k >= m_CurHeight) break;
  1130. }
  1131. pSrcData = p2;
  1132. p2 = NULL;
  1133. }
  1134. // 转换图像到数据包指定格式
  1135. switch(_get_desformat(lpInfo))
  1136. {
  1137. case DF_16_555: // 16位555格式(也就是15位图像)
  1138. {
  1139. for (j=0;j<m_CurHeight;j++)
  1140. {
  1141. WORD *pImg555 = (WORD*)(lpInfo->pLineAddr[j]);
  1142. for (i=0;i<m_CurWidth;i++)
  1143. {
  1144. index = pSrcData[j*m_CurWidth+i];
  1145. WORD bkc555 = _cnv_rgb_to_555(m_CurRgbQuad[index].rgbRed, 
  1146.   m_CurRgbQuad[index].rgbGreen, 
  1147.   m_CurRgbQuad[index].rgbBlue);
  1148. *pImg555++ = bkc555;
  1149. }
  1150. }
  1151. }
  1152. break;
  1153. case DF_16_565: // 16位565格式
  1154. {
  1155. for (j=0;j<m_CurHeight;j++)
  1156. {
  1157. WORD *pImg565 = (WORD*)(lpInfo->pLineAddr[j]);
  1158. for (i=0;i<m_CurWidth;i++)
  1159. {
  1160. index = pSrcData[j*m_CurWidth+i];
  1161. WORD bkc565 = _cnv_rgb_to_565(m_CurRgbQuad[index].rgbRed, 
  1162.   m_CurRgbQuad[index].rgbGreen, 
  1163.   m_CurRgbQuad[index].rgbBlue);
  1164. *pImg565++ = bkc565;
  1165. }
  1166. }
  1167. }
  1168. break;
  1169. case DF_24: // 24位格式
  1170. {
  1171. for (j=0;j<m_CurHeight;j++)
  1172. {
  1173. PBYTE pImg24 = (PBYTE)(lpInfo->pLineAddr[j]);
  1174. for (i=0;i<m_CurWidth;i++)
  1175. {
  1176. index = pSrcData[j*m_CurWidth+i];
  1177. *pImg24++ = m_CurRgbQuad[index].rgbBlue;
  1178. *pImg24++ = m_CurRgbQuad[index].rgbGreen;
  1179. *pImg24++ = m_CurRgbQuad[index].rgbRed;
  1180. }
  1181. }
  1182. }
  1183. break;
  1184. case DF_32: // 32位格式
  1185. {
  1186. for (j=0;j<m_CurHeight;j++)
  1187. {
  1188. DWORD *pImg32 = (DWORD*)(lpInfo->pLineAddr[j]);
  1189. for (i=0;i<m_CurWidth;i++)
  1190. {
  1191. index = pSrcData[j*m_CurWidth+i];
  1192. DWORD bkc32 = _cnv_rgb_to_888( m_CurRgbQuad[index].rgbRed, 
  1193.   m_CurRgbQuad[index].rgbGreen, 
  1194.   m_CurRgbQuad[index].rgbBlue);
  1195. *pImg32++ = bkc32;
  1196. }
  1197. }
  1198. }
  1199. break;
  1200. default:
  1201. ASSERT(FALSE);
  1202. break;
  1203. }
  1204. if (m_CurSaveMode) //交叉存储
  1205. GlobalFree(pSrcData);
  1206. return TRUE;
  1207. }
  1208. // 将某一子图像保存到子图像链表中
  1209. BOOL ConvertToBmpImage(PBYTE SrcData, LPINFOSTR lpInfo)
  1210. {
  1211. ASSERT(SrcData);
  1212. PBYTE p2,pTmp;
  1213. PBYTE pSrcData = SrcData;
  1214. int i,j,k,Step,index;
  1215. if (m_CurSaveMode )//交叉存储
  1216. {
  1217. pTmp = p2 = (PBYTE)::GlobalAlloc(GPTR, m_CurWidth*m_CurHeight);
  1218. if (!pTmp)
  1219. return FALSE;
  1220. k = 0; Step = 8;
  1221. for (j = 0; j < m_CurHeight  ; j ++)
  1222. {
  1223. memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
  1224. k += Step;
  1225. if (k >= m_CurHeight) break;
  1226. }
  1227. j++;//每行中存了一个越界值
  1228. k = 4; Step = 8;
  1229. for (; j < m_CurHeight  ; j ++)
  1230. {
  1231. memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
  1232. k += Step;
  1233. if (k >= m_CurHeight) break;
  1234. }
  1235. j++;
  1236. k = 2; Step = 4;
  1237. for (; j < m_CurHeight  ; j ++)
  1238. {
  1239. memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
  1240. k += Step;
  1241. if (k >= m_CurHeight) break;
  1242. }
  1243. j++;
  1244. k = 1; Step = 2;
  1245. for (; j < m_CurHeight  ; j ++)
  1246. {
  1247. memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_GifInfo.Width);
  1248. k += Step;
  1249. if (k >= m_CurHeight) break;
  1250. }
  1251. pSrcData = p2;
  1252. p2 = NULL;
  1253. }
  1254. LPSUBIMGBLOCK pSubImage = (LPSUBIMGBLOCK)::GlobalAlloc(GPTR, sizeof(SUBIMGBLOCK));
  1255. if (!pSubImage)
  1256. {
  1257. if (m_CurSaveMode )//交叉存储
  1258. ::GlobalFree(pSrcData);
  1259. return FALSE;
  1260. }
  1261. pSubImage->parents = lpInfo;// 第一桢图像数据的结构地址(所属数据包结构的地址)
  1262. pSubImage->prev = NULL; // 前一桢图像数据的结构地址
  1263. pSubImage->next = NULL; // 后一桢图像数据的结构地址(NULL表示这是最后一副图像)
  1264. DWORD desize = 0; // 子图像BMP格式的尺寸
  1265. DWORD scanlinesize = 0; // 子图像扫描行尺寸
  1266. // 获取数据包标准图像格式之子图像尺寸
  1267. switch(_get_desformat(lpInfo))
  1268. {
  1269. case DF_16_555: // 16位555格式(也就是15位图像)
  1270. case DF_16_565: // 16位565格式
  1271. scanlinesize = WIDTHBYTES(m_CurWidth*16);
  1272. break;
  1273. case DF_24: // 24位格式
  1274. scanlinesize = WIDTHBYTES(m_CurWidth*24);
  1275. case DF_32: // 32位格式
  1276. scanlinesize = m_CurWidth*4;
  1277. break;
  1278. default:
  1279. ASSERT(FALSE);
  1280. if (m_CurSaveMode )//交叉存储
  1281. ::GlobalFree(pSrcData);
  1282. return FALSE;
  1283. }
  1284. desize = scanlinesize*m_CurHeight;
  1285. ASSERT(desize); // 宽度或高度不能是0
  1286. // 分配子图像位数据缓冲区
  1287. pSubImage->pLineAddr = (DWORD**)::GlobalAlloc(GPTR, m_CurHeight*sizeof(DWORD*));
  1288. pSubImage->_pbdata   = (PBYTE)::GlobalAlloc(GPTR, desize);
  1289. if ((pSubImage->pLineAddr == NULL)||(pSubImage->_pbdata == NULL))
  1290. {
  1291. if (m_CurSaveMode) ::GlobalFree(pSrcData);
  1292. if (pSubImage->_pbdata) ::GlobalFree(pSubImage->_pbdata);
  1293. if (pSubImage->pLineAddr) ::GlobalFree(pSubImage->pLineAddr);
  1294. return FALSE;
  1295. }
  1296. // 初始化行首地址数组(倒向DIB格式)
  1297. for (int y=0;y<m_CurHeight;y++)
  1298. {
  1299. pSubImage->pLineAddr[y] = 
  1300. (DWORD*)(pSubImage->_pbdata+((m_CurHeight-y-1)*scanlinesize));
  1301. }
  1302. pSubImage->number = m_CurImgIndex++; // 子图像块的序列号
  1303. pSubImage->left = m_CurX; // 子图像块的显示位置(左上角)
  1304. pSubImage->top  = m_CurY;
  1305. pSubImage->width = m_CurWidth; // 子图像块的图像宽度及高度
  1306. pSubImage->height = m_CurHeight;
  1307. pSubImage->dowith = m_CurDM; // 处置方法(针对于动画GIF)
  1308. pSubImage->userinput = m_CurUserInput; // 用户输入(针对于动画GIF)
  1309. if (m_CurTColorIndex != -1) // 透明色分量值(-1表示无效)
  1310. {
  1311. pSubImage->colorkey = RGB(m_CurRgbQuad[m_CurTColorIndex].rgbRed, 
  1312. m_CurRgbQuad[m_CurTColorIndex].rgbGreen, 
  1313. m_CurRgbQuad[m_CurTColorIndex].rgbBlue);
  1314. }
  1315. else
  1316. pSubImage->colorkey = (COLORREF)((int)(-1));
  1317. pSubImage->time = (int)m_CurDelayTime; // 显示的延迟时间
  1318. // 将子图像块插入链表
  1319. if (m_pSubimgTail == NULL) // 当前是空链表
  1320. {
  1321. m_pSubimgHead = pSubImage;
  1322. m_pSubimgTail = pSubImage;
  1323. }
  1324. else
  1325. {
  1326. ASSERT(m_pSubimgHead->prev == NULL); // 检察链表的有效性
  1327. ASSERT(m_pSubimgTail->next == NULL);
  1328. m_pSubimgTail->next = pSubImage;
  1329. pSubImage->prev = m_pSubimgTail;
  1330. m_pSubimgTail = pSubImage;
  1331. }
  1332. // 转换图像到数据包指定格式
  1333. switch(_get_desformat(lpInfo))
  1334. {
  1335. case DF_16_555: // 16位555格式(也就是15位图像)
  1336. {
  1337. for (j=0;j<m_CurHeight;j++)
  1338. {
  1339. WORD *pImg555 = (WORD*)(pSubImage->pLineAddr[j]);
  1340. for (i=0;i<m_CurWidth;i++)
  1341. {
  1342. index = pSrcData[j*m_CurWidth+i];
  1343. WORD bkc555 = _cnv_rgb_to_555(m_CurRgbQuad[index].rgbRed, 
  1344.   m_CurRgbQuad[index].rgbGreen, 
  1345.   m_CurRgbQuad[index].rgbBlue);
  1346. *pImg555++ = bkc555;
  1347. }
  1348. }
  1349. }
  1350. break;
  1351. case DF_16_565: // 16位565格式
  1352. {
  1353. for (j=0;j<m_CurHeight;j++)
  1354. {
  1355. WORD *pImg565 = (WORD*)(pSubImage->pLineAddr[j]);
  1356. for (i=0;i<m_CurWidth;i++)
  1357. {
  1358. index = pSrcData[j*m_CurWidth+i];
  1359. WORD bkc565 = _cnv_rgb_to_565(m_CurRgbQuad[index].rgbRed, 
  1360.   m_CurRgbQuad[index].rgbGreen, 
  1361.   m_CurRgbQuad[index].rgbBlue);
  1362. *pImg565++ = bkc565;
  1363. }
  1364. }
  1365. }
  1366. break;
  1367. case DF_24: // 24位格式
  1368. {
  1369. for (j=0;j<m_CurHeight;j++)
  1370. {
  1371. PBYTE pImg24 = (PBYTE)(pSubImage->pLineAddr[j]);
  1372. for (i=0;i<m_CurWidth;i++)
  1373. {
  1374. index = pSrcData[j*m_CurWidth+i];
  1375. *pImg24++ = m_CurRgbQuad[index].rgbBlue;
  1376. *pImg24++ = m_CurRgbQuad[index].rgbGreen;
  1377. *pImg24++ = m_CurRgbQuad[index].rgbRed;
  1378. }
  1379. }
  1380. }
  1381. break;
  1382. case DF_32: // 32位格式
  1383. {
  1384. for (j=0;j<m_CurHeight;j++)
  1385. {
  1386. DWORD *pImg32 = (DWORD*)(pSubImage->pLineAddr[j]);
  1387. for (i=0;i<m_CurWidth;i++)
  1388. {
  1389. index = pSrcData[j*m_CurWidth+i];
  1390. DWORD bkc32 = _cnv_rgb_to_888( m_CurRgbQuad[index].rgbRed, 
  1391.   m_CurRgbQuad[index].rgbGreen, 
  1392.   m_CurRgbQuad[index].rgbBlue);
  1393. *pImg32++ = bkc32;
  1394. }
  1395. }
  1396. }
  1397. break;
  1398. default:
  1399. ASSERT(FALSE);
  1400. break;
  1401. }
  1402. if (m_CurSaveMode) //交叉存储
  1403. GlobalFree(pSrcData);
  1404. return TRUE;
  1405. }
  1406. // 获取GIF文件中图像的个数
  1407. // 参数pFileContent指向的缓冲区必须包括完整的GIF文件内容
  1408. // 参数filesize是指明pFileContent所指向的缓冲区的尺寸(即GIF文件的尺寸)
  1409. // 函数返回图像的个数,如果文件内容非法(比如是个受损的GIF文件),则返回0
  1410. int _get_imgcount(PBYTE pFileContent, DWORD filesize)
  1411. {
  1412. ASSERT(pFileContent);
  1413. ASSERT(pFileContent[0] == 'G');
  1414. PBYTE p = pFileContent;
  1415. GIFHEADER gifHeader; // 文件头
  1416. memcpy(&gifHeader,p,sizeof(GIFHEADER));
  1417. // 跨过GIF文件头及逻辑屏幕描述块
  1418. p += sizeof(GIFHEADER);
  1419. // 判断是否存在全局调色板,如果存在则跨过该调色板
  1420. if (gifHeader.GlobalFlagByte&0x80)
  1421. p += (1<<((gifHeader.GlobalFlagByte&0x7)+1))*sizeof(GIFRGB);
  1422. int imgcount = 0;
  1423. // 分解数据区
  1424. while (1)
  1425. {
  1426. if (p[0] == 0x21 && p[1] == 0xf9 && p[2] == 0x4) // 图形扩展块
  1427. p += sizeof(GRAPHCTRL);
  1428. else if (p[0] == 0x21 && p[1] == 0x1 && p[2] == 0xc)// 文本扩展块
  1429. p += sizeof(TEXTCTRL)-(255-((LPTEXTCTRL)p)->Data[0]);
  1430. else if (p[0] == 0x21 && p[1] == 0xff && p[2] == 0xb)// 应用程序扩展块
  1431. p += sizeof(APPCTRL)-(255-((LPAPPCTRL)p)->Data[0]);
  1432. else if (p[0] == 0x21 && p[1] == 0xfe) // 注释扩展块
  1433. p += sizeof(NOTEHCTRL)-(255-((LPNOTEHCTRL)p)->Data[0]);
  1434. else if (p[0] == 0x2c) // 图像描述符+[局部调色板]+图像数据块
  1435. {
  1436. IMAGEDATAINFO ImageData; // 图像数据块
  1437. // 跨过图像描述符结构
  1438. memcpy(&ImageData,p,sizeof(IMAGEDATAINFO));
  1439. p += sizeof(IMAGEDATAINFO);
  1440. // 如果拥有局部调色板数据,则跨过
  1441. if (ImageData.LocalFlagByte&0x80) 
  1442. p += (1<<(ImageData.LocalFlagByte&0x7+1))*sizeof(GIFRGB);
  1443. p++; // 越过LZW初始位值
  1444. BYTE dataLen;
  1445. // 跨过经压缩的图像数据
  1446. while (1)
  1447. {
  1448. if ((((DWORD)p)-((DWORD)pFileContent)) > filesize)
  1449. return 0; // 受损的文件
  1450. dataLen = *p++;
  1451. p += dataLen;
  1452. if (dataLen == 0x0) 
  1453. break;
  1454. }
  1455. // 图像个数加1
  1456. imgcount++;
  1457. }
  1458. else 
  1459. break;
  1460. if ((((DWORD)p)-((DWORD)pFileContent)) > filesize)
  1461. return 0; // 受损的文件
  1462. }
  1463. // 返回GIF文件中的图像个数
  1464. return imgcount;
  1465. }
  1466. // 判断标准图像的位格式
  1467. DESFORMAT _get_desformat(LPINFOSTR pInfo)
  1468. {
  1469. ASSERT(pInfo);
  1470. // ASSERT(pInfo->state >= PKST_PASSVER);
  1471. ASSERT(pInfo->sDIBInfo.bmi.biPlanes == 1);
  1472. DESFORMAT result;
  1473. switch(pInfo->sDIBInfo.bmi.biBitCount)
  1474. {
  1475. case 32:
  1476. /******************************************************
  1477. 32位掩码示意图
  1478.     高               ->                 低
  1479. 0000 0000   0000 0000   0000 0000   0000 0000  888格式
  1480.             1111 1111  ------------------------R
  1481.                         1111 1111 -------------G
  1482.                                     1111 1111--B
  1483. * Win95 系统只支持这一种格式
  1484. ******************************************************/
  1485. if (pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
  1486. {
  1487. result = DF_32;
  1488. break;
  1489. }
  1490. if ((pInfo->sDIBInfo.rmask == 0xff0000)&&
  1491. (pInfo->sDIBInfo.gmask == 0xff00)&&
  1492. (pInfo->sDIBInfo.bmask == 0xff))
  1493. result = DF_32;
  1494. else
  1495. {
  1496. ASSERT(FALSE); // 只支持888格式
  1497. result = DF_NULL;
  1498. }
  1499. break;
  1500. case 24:
  1501. result = DF_24;
  1502. break;
  1503. case 16:
  1504. /*******************************************
  1505. 16位掩码示意图
  1506.   高字节      低字节
  1507. 0000 0000   0000 0000 
  1508.    1 1111--B // 555格式
  1509.    11 111 -------G
  1510.  111 11  --------------R
  1511. 0
  1512.    1 1111--B // 565格式
  1513.   111   111 -------G
  1514. 1111 1   --------------R
  1515. * Win95 系统只支持以上两种格式
  1516. *******************************************/
  1517. if (pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
  1518. {
  1519. result = DF_16_555;
  1520. break;
  1521. }
  1522. if ((pInfo->sDIBInfo.rmask == 0x7c00)&&
  1523. (pInfo->sDIBInfo.gmask == 0x3e0)&&
  1524. (pInfo->sDIBInfo.bmask == 0x1f))
  1525. result = DF_16_555;
  1526. else if ((pInfo->sDIBInfo.rmask == 0xf800)&&
  1527. (pInfo->sDIBInfo.gmask == 0x7e0)&&
  1528. (pInfo->sDIBInfo.bmask == 0x1f))
  1529. result = DF_16_565;
  1530. else
  1531. result = DF_NULL;
  1532. break;
  1533. default:
  1534. ASSERT(FALSE); // 不接受其它格式
  1535. result = DF_NULL;
  1536. break;
  1537. }
  1538. return result;
  1539. }
  1540. // 将指定的RGB颜色分量转换成555格式(WORD型值返回)
  1541. WORD _cnv_rgb_to_555(BYTE red, BYTE green, BYTE blue)
  1542. {
  1543. WORD result = 0;
  1544. result = (((WORD)red>>3)<<10)|(((WORD)green>>3)<<5)|((WORD)blue>>3);
  1545. return result;
  1546. }
  1547. // 将指定的555格式的颜色转换成RGB颜色分量
  1548. void _cnv_555_to_rgb(WORD col, PBYTE red, PBYTE green, PBYTE blue)
  1549. {
  1550. // 在555转换到RGB时,将像素的亮度调到最大
  1551. *red = (BYTE)((col>>7)&0xf8);
  1552. *green = (BYTE)((col>>2)&0xf8);
  1553. *blue = (BYTE)(col<<3);
  1554. }
  1555. // 将指定的RGB颜色分量转换成565格式(WORD型值返回)
  1556. WORD _cnv_rgb_to_565(BYTE red, BYTE green, BYTE blue)
  1557. {
  1558. WORD result = 0;
  1559. result = (((WORD)red>>3)<<11)|(((WORD)green>>2)<<5)|((WORD)blue>>3);
  1560. return result;
  1561. }
  1562. // 将指定的565格式的颜色转换成RGB颜色分量
  1563. void _cnv_565_to_rgb(WORD col, PBYTE red, PBYTE green, PBYTE blue)
  1564. {
  1565. // 在565转换到RGB时,将像素的亮度调到最大
  1566. *red = (BYTE)((col>>8)&0xf8);
  1567. *green = (BYTE)((col>>3)&0xfc);
  1568. *blue = (BYTE)(col<<3);
  1569. }
  1570. // 将指定的RGB颜色分量转换成888格式(DWORD型值返回)
  1571. DWORD _cnv_rgb_to_888(BYTE red, BYTE green, BYTE blue)
  1572. {
  1573. DWORD result = 0;
  1574. result = ((DWORD)red<<16)|((DWORD)green<<8)|(DWORD)blue;
  1575. return result;
  1576. }
  1577. // 清除子图像链表
  1578. void _clear_list(void)
  1579. {
  1580. if (m_pSubimgTail == NULL)
  1581. return;
  1582. ASSERT(m_CurImgIndex);
  1583. LPSUBIMGBLOCK   lpSubImg;
  1584. while((lpSubImg=m_pSubimgTail) != NULL)
  1585. {
  1586. m_pSubimgTail = lpSubImg->prev;
  1587. lpSubImg->number = 0; // 子图像块的序列号
  1588. lpSubImg->left = lpSubImg->top = 0; // 子图像块的显示位置(左上角)
  1589. lpSubImg->width = lpSubImg->height = 0; // 子图像块的图像宽度及高度
  1590. lpSubImg->dowith = 0; // 处置方法(针对于动画GIF)
  1591. lpSubImg->userinput = 0; // 用户输入(针对于动画GIF)
  1592. lpSubImg->colorkey = 0; // 透明色分量值
  1593. lpSubImg->time = 0; // 显示的延迟时间
  1594. if (lpSubImg->pLineAddr)
  1595. ::GlobalFree(lpSubImg->pLineAddr);
  1596. if (lpSubImg->_pbdata)
  1597. ::GlobalFree(lpSubImg->_pbdata);
  1598. lpSubImg->parents = NULL; // 第一桢图像数据的结构地址(所属数据包结构的地址)
  1599. lpSubImg->prev = NULL; // 前一桢图像数据的结构地址
  1600. lpSubImg->next = NULL; // 后一桢图像数据的结构地址(NULL表示这是最后一副图像)
  1601. ::GlobalFree(lpSubImg);
  1602. };
  1603. m_pSubimgHead = NULL;
  1604. m_CurImgIndex = 0;
  1605. return;
  1606. }