GifModule.cpp
上传用户:yatsl7111
上传日期:2007-01-08
资源大小:1433k
文件大小:47k
- /********************************************************************
- GifModule.cpp - ISee图像浏览器—GIF图像读写模块实现文件
-
- 版权所有(C) 2000 VCHelp-coPathway-ISee workgroup member - Sam, YZ
- 这一程序是自由软件,你可以遵照自由软件基金会出版的GNU 通用公共许
- 可证条款来修改和重新发布这一程序。或者用许可证的第二版,或者(根
- 据你的选择)用任何更新的版本。
- 发布这一程序的目的是希望它有用,但没有任何担保。甚至没有适合特定
- 目地的隐含的担保。更详细的情况请参阅GNU通用公共许可证。
- 你应该已经和程序一起收到一份GNU通用公共许可证的副本(本目录
- GPL.TXT文件)。如果还没有,写信给:
- The Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- MA02139, USA
- 如果你在使用本软件时有什么问题或建议,用以下地址可以与我们取得联
- 系:
- http://isee.126.com
- http://www.vchelp.net
- 或:
- iseesoft@china.com
- 原创人 :Sam (http://go.163.com/~program2000/)
- 第二编写人:YZ (http://isee.126.com/ or yzfree@sina.com)
- 文件版本:
- Build 00901
- Date 2000-9-1
- GIF图像文件格式版权声明:
- ---------------------------------------------------------------
- The Graphics Interchange Format(c) is the Copyright property of
- CompuServe Incorporated. GIF(sm) is a Service Mark property of
- CompuServe Incorporated.
- ---------------------------------------------------------------
- ********************************************************************/
- #include "stdafx.h"
- #include "GifModule.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- // 全局变量定义
- GIFINFO m_GifInfo;
- LZWTABLE LZWTable[LZWTABLESIZE];
- CPtrList m_ImageList;
- RGBQUAD m_GlobalPal[256]; // 全局调色板
- RGBQUAD m_CurRgbQuad[256]; // 当前的局部调色板
- int m_CurPalSize; // 当前调色板项数(针对于局部调色板)
- int m_CurDM; // 当前的处置方法
- int m_CurUserInput; // 当前的用户输入标志
- short m_CurTColorIndex; // 当前的透明色索引号(-1表示无效)
- WORD m_CurDelayTime; // 当前的延迟时间(0表示没有延时)
- BOOL m_CurSaveMode; // 当前的图像存储模式
- WORD m_CurX,m_CurY; // 当前图像在虚拟屏幕中的位置
- WORD m_CurWidth,m_CurHeight; // 当前图像的宽度、高度
- int m_CurImgIndex; // 当前图像的序号(0基)
- LPSUBIMGBLOCK m_pSubimgHead; // 子图像链表的头
- LPSUBIMGBLOCK m_pSubimgTail; // 子图像链表的尾
- static char ModuleProcessImgType[]="GIF"; // 本模块能处理的图像类型
- static char WriterList[]="Sam, YZ"; // 本模块的作者列表
- static char WriterMess[]="我喜欢自由软件,它大大的减少了重复代码的开发^_^";
- // 作者留言
- static char GIF87a[]="GIF87a";
- static char GIF89a[]="GIF89a";
- //
- // Note!
- //
- // If this DLL is dynamically linked against the MFC
- // DLLs, any functions exported from this DLL which
- // call into MFC must have the AFX_MANAGE_STATE macro
- // added at the very beginning of the function.
- //
- // For example:
- //
- // extern "C" BOOL PASCAL EXPORT ExportedFunction()
- // {
- // AFX_MANAGE_STATE(AfxGetStaticModuleState());
- // // normal function body here
- // }
- //
- // It is very important that this macro appear in each
- // function, prior to any calls into MFC. This means that
- // it must appear as the first statement within the
- // function, even before any object variable declarations
- // as their constructors may generate calls into the MFC
- // DLL.
- //
- // Please see MFC Technical Notes 33 and 58 for additional
- // details.
- //
- // 在图像读写模块中,如果想分配内存,请使用API函数GlobalAlloc()
- // ,如果想释放内存请使用GlobalFree()函数。不要使用诸如:new
- // 、malloc()等函数。这是为了使各模块之间可以异地释放内存。
- //
- //
- /////////////////////////////////////////////////////////////////////////////
- // CGifModuleApp
- BEGIN_MESSAGE_MAP(CGifModuleApp, CWinApp)
- //{{AFX_MSG_MAP(CGifModuleApp)
- // NOTE - the ClassWizard will add and remove mapping macros here.
- // DO NOT EDIT what you see in these blocks of generated code!
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
- /////////////////////////////////////////////////////////////////////////////
- // CGifModuleApp construction
- CGifModuleApp::CGifModuleApp()
- {
- ::ZeroMemory((PVOID)&m_GifInfo, sizeof(GIFINFO));
- ::ZeroMemory((PVOID)LZWTable, sizeof(LZWTABLE)*LZWTABLESIZE);
- PALETTEENTRY syspal[256];
- // 提取当前系统的调色板数据
- HWND hWnd = ::GetDesktopWindow();
- HDC hDC = ::GetDC(hWnd);
- ::GetSystemPaletteEntries(hDC, 0, 256, (LPPALETTEENTRY)syspal);
- ::ReleaseDC(hWnd, hDC);
- // 初始化全局调色板
- for (int i=0;i<256;i++)
- {
- m_GlobalPal[i].rgbRed = syspal[i].peRed;
- m_GlobalPal[i].rgbGreen = syspal[i].peGreen;
- m_GlobalPal[i].rgbBlue = syspal[i].peBlue;
- m_GlobalPal[i].rgbReserved = 0;
- }
- m_CurPalSize = 0; // 当前调色板项数(针对于局部调色板)
- m_CurDM = 0; // 当前的处置方法
- m_CurUserInput = 0; // 当前的用户输入标志
- m_CurTColorIndex = -1; // 当前的透明色索引号(-1表示无效)
- m_CurDelayTime = 0; // 当前的延迟时间(0表示没有延时)
- m_CurSaveMode = 0; // 当前的图像存储模式
- m_CurX = m_CurY = 0; // 当前图像在虚拟屏幕中的位置
- m_CurWidth = m_CurHeight = 0; // 当前图像的宽度、高度
- m_CurImgIndex = 0; // 当前图像的序号(0基)
- m_pSubimgHead = NULL; // 子图像链表的头
- m_pSubimgTail = NULL; // 子图像链表的尾
- }
- /////////////////////////////////////////////////////////////////////////////
- // The one and only CGifModuleApp object
- CGifModuleApp theApp;
- // 接口函数声明 — 第一层,唯一与外界联系的接口
- int WINAPI AccessGIFModule(INFOSTR *pInfo)
- {
- // 这个函数可以不作修改的使用,除非你的返回值多于两种。
- switch(pInfo->comm)
- {
- case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
- _fnCMD_GETPROCTYPE(pInfo);
- break;
- case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
- _fnCMD_GETWRITERS(pInfo);
- break;
- case CMD_GETWRITERMESS: // 获取作者们的留言
- _fnCMD_GETWRITERMESS(pInfo);
- break;
- case CMD_GETBUILDID: // 获取图像模块内部版本号
- _fnCMD_GETBUILDID(pInfo);
- break;
- case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的GIF文件
- _fnCMD_IS_VALID_FILE(pInfo);
- break;
- case CMD_GET_FILE_INFO: // 获取指定文件的信息
- _fnCMD_GET_FILE_INFO(pInfo);
- break;
- case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
- _fnCMD_LOAD_FROM_FILE(pInfo);
- break;
- case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
- _fnCMD_SAVE_TO_FILE(pInfo);
- break;
- case CMD_IS_SUPPORT: // 查询某个命令是否被支持
- _fnCMD_IS_SUPPORT(pInfo);
- break;
- case CMD_RESIZE: // 从新获取指定尺寸的图像位数据(只适用于矢量图像)
- _fnCMD_RESIZE(pInfo);
- break;
- default:
- pInfo->result = ER_ILLCOMM; // 非法命令
- ASSERT(FALSE); // 调用者的程序设计有问题 :-)
- break;
- }
- // 执行命令成功返回1, 失败返回0
- return (pInfo->result==ER_SUCCESS)? 1:0;
- }
- // 命令解释函数 — 第二层解释函数
- //********************************************************************//
- // 操作命令解释函数---解释:CMD_IS_SUPPORT命令
- // 查询某个命令是否被支持
- void _fnCMD_IS_SUPPORT(INFOSTR *pInfo)
- {
- ASSERT(pInfo->result == ER_EMPTY);
- switch(pInfo->annexdata.cmAnnData)
- {
- case CMD_GETPROCTYPE: // 获取本模块能处理的图像类型
- pInfo->result = ER_SUCCESS;
- break;
- case CMD_GETWRITERS: // 获取本模块的作者列表,多人时用逗号分隔
- pInfo->result = ER_SUCCESS;
- break;
- case CMD_GETWRITERMESS: // 获取作者们的留言
- pInfo->result = ER_SUCCESS;
- break;
- case CMD_GETBUILDID: // 获取图像模块内部版本号
- pInfo->result = ER_SUCCESS;
- break;
- case CMD_IS_VALID_FILE: // 判断指定文件是否是有效的WMF文件
- pInfo->result = ER_SUCCESS;
- break;
- case CMD_GET_FILE_INFO: // 获取指定文件的信息
- pInfo->result = ER_SUCCESS;
- break;
- case CMD_LOAD_FROM_FILE: // 从指定图像文件中读取数据
- pInfo->result = ER_SUCCESS;
- break;
- case CMD_SAVE_TO_FILE: // 将数据保存到指定文件中
- pInfo->result = ER_NOTSUPPORT;
- break;
- case CMD_IS_SUPPORT: // 查询某个命令是否被支持
- pInfo->result = ER_SUCCESS;
- break;
- case CMD_RESIZE: // 获取指定尺寸的图像(只适用于矢量图像)
- pInfo->result = ER_NOTSUPPORT;
- break;
- default:
- pInfo->result = ER_NOTSUPPORT;
- break;
- }
- }
- // 操作命令解释函数---解释:CMD_GETPROCTYPE命令
- // 获取本模块能处理的图像类型,如:BMP,PCX等等
- void _fnCMD_GETPROCTYPE(INFOSTR *pInfo)
- {
- // 这是预定义的函数代码,你可以不必修改的使用。
- // 根据接口定义,此时附加数据应被清空为0,所以下此断言
- ASSERT(pInfo->annexdata.scAnnData[0] == 0);
- ASSERT(pInfo->result == ER_EMPTY);
- // 复制能处理的类型字符串
- ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)ModuleProcessImgType,
- sizeof(ModuleProcessImgType));
- pInfo->result = ER_SUCCESS;
- }
- // 操作命令解释函数---解释:CMD_GETWRITER命令
- // 获取本模块的作者列表,多人时用逗号分隔
- void _fnCMD_GETWRITERS(INFOSTR *pInfo)
- {
- // 这是预定义的函数代码,你可以不必修改的使用。
- // 根据接口定义,此时附加数据应被清空为0,所以下此断言
- ASSERT(pInfo->annexdata.scAnnData[0] == 0);
- ASSERT(pInfo->result == ER_EMPTY);
- // 复制开发者名单串
- ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterList,
- sizeof(WriterList));
- pInfo->result = ER_SUCCESS;
- }
- // 操作命令解释函数---解释:CMD_GETWRITERMESS命令
- // 获取作者们的留言
- void _fnCMD_GETWRITERMESS(INFOSTR *pInfo)
- {
- // 这是预定义的函数代码,你可以不必修改的使用。
- // 根据接口定义,此时附加数据应被清空为0,所以下此断言
- ASSERT(pInfo->annexdata.scAnnData[0] == 0);
- ASSERT(pInfo->result == ER_EMPTY);
- // 复制开发者们的留言字符串
- ::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterMess,
- sizeof(WriterMess));
- pInfo->result = ER_SUCCESS;
- }
- // 操作命令解释函数---解释:CMD_GETBUILDID命令
- // 获取图像模块内部版本号
- void _fnCMD_GETBUILDID(INFOSTR *pInfo)
- {
- // 这是预定义的函数代码,你可以不必修改的使用。
- // 根据接口定义,此时annexdata.dwAnnData应被设为0,所以下此断言
- ASSERT(pInfo->annexdata.dwAnnData == 0);
- ASSERT(pInfo->result == ER_EMPTY);
- // 填写内部版本号码
- pInfo->annexdata.dwAnnData = MODULE_BUILDID;
- pInfo->result = ER_SUCCESS;
- }
- // 操作命令解释函数---解释:CMD_IS_VALID_FILE命令
- // 判断指定文件是否是有效的WMF文件
- void _fnCMD_IS_VALID_FILE(INFOSTR *pInfo)
- {
- CFile file;
- GIFHEADER gifheader;
- DWORD dwSize;
- UINT uRet;
- // 检验入口参数是否符合接口定义
- ASSERT(pInfo->result == ER_EMPTY);
- ASSERT(pInfo->annexdata.iAnnData == 0);
- ASSERT(::strlen(pInfo->filename));
- ASSERT(pInfo->state == PKST_NOTVER);
- ASSERT(pInfo);
- // 设初值
- pInfo->result = ER_SUCCESS;
- pInfo->annexdata.iAnnData = 0;
- // 先判断指定的文件是否存在
- if (!IsFileExist(pInfo->filename))
- pInfo->result = ER_COMMINFOERR;
- else
- {
- // 打开指定文件
- if (!file.Open(pInfo->filename, CFile::modeRead))
- {
- pInfo->result = ER_FILERWERR; // 打开文件时出错
- return;
- }
- // 获取文件的长度(以字节为单位)
- dwSize = file.GetLength();
- // 用长度判断
- if (dwSize < sizeof(GIFHEADER))
- {
- // 这不是一个GIF文件,因为GIF文件的长度起码大于GIF文件头
- // 结构的长度
- file.Close();
- return;
- }
- // 读取GIF文件信息头结构,并检查它的有效性
- file.SeekToBegin();
- uRet = file.Read((LPSTR)&gifheader, sizeof(GIFHEADER));
- if (uRet != sizeof(GIFHEADER))
- {
- // 读文件时出错
- pInfo->result = ER_FILERWERR;
- file.Close();
- return;
- }
- // 判断文件标志
- if ((::memcmp((const void*)(gifheader.Signature), (const void*)GIF87a, sizeof(GIFVERSIZE)) != 0)&&
- (::memcmp((const void*)(gifheader.Signature), (const void*)GIF89a, sizeof(GIFVERSIZE)) != 0))
- {
- file.Close();
- return;
- }
- // 到此,大致可以表明该文件是一个GIF文件,iAnnData变量设为1
- pInfo->annexdata.iAnnData = 1;
- // 表示通过校验
- pInfo->state = PKST_PASSVER;
- file.Close();
- }
- }
- // 操作命令解释函数---解释:CMD_GET_FILE_INFO命令
- // 获取指定文件的信息
- // 注:此时数据包中的imginfo结构并没有真正填写完,图像的类型
- // 图像的个数、及图像是否可被编辑等值都是暂设的。
- void _fnCMD_GET_FILE_INFO(INFOSTR *pInfo)
- {
- CFile file;
- CFileStatus status;
- PBYTE pFileContent;
- DWORD dwFileLen, uRet;
- GIFHEADER *gifheader;
- // 检验入口参数是否符合接口定义
- ASSERT(pInfo->result == ER_EMPTY);
- ASSERT(::strlen(pInfo->filename));
- // 此时,该文件必需是一个已存在的、并且是有效的GIF文件
- ASSERT(pInfo->state == PKST_PASSVER);
- // 客户模块必需要先将imginfo清空为0
- ASSERT(pInfo->imginfo.imgtype == IMT_NULL);
- // 打开指定文件
- if (!file.Open(pInfo->filename, CFile::modeRead))
- {
- pInfo->result = ER_FILERWERR;
- return;
- }
- // 获取文件长度
- dwFileLen = file.GetLength();
- // 分配内存,用于存放所有的GIF数据
- pFileContent = (PBYTE)::GlobalAlloc(GPTR, dwFileLen+1);
- if (!pFileContent)
- {
- file.Close();
- pInfo->result = ER_MEMORYERR;
- return;
- }
- file.SeekToBegin();
- // 读取整个的GIF文件到内存中
- uRet = file.ReadHuge((void*)pFileContent, dwFileLen);
- if (uRet != dwFileLen)
- {
- ::GlobalFree(pFileContent);
- file.Close();
- pInfo->result = ER_FILERWERR;
- return;
- }
-
- gifheader = (GIFHEADER*)pFileContent;
- // 这个文件应该已经被校验过的,也就是说应该是有效的GIF文件
- ASSERT(gifheader->Signature[0] == 'G');
- // 获取GIF文件中的图像个数
- int imgcount = _get_imgcount(pFileContent, dwFileLen);
- if (imgcount == 0) // 受损的GIF图像文件
- {
- ::GlobalFree(pFileContent);
- file.Close();
- pInfo->result = ER_BADIMAGE;
- return;
- }
- LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo;
- // 获取文件的长度、图像的宽度、高度等信息
- lpImgInfoStr->imgtype = (imgcount == 1) ? IMT_RESSTATIC:IMT_RESDYN;
- lpImgInfoStr->imgformat = IMF_GIF;
- lpImgInfoStr->filesize = dwFileLen;
- // 以下的宽度、高度是指GIF虚拟屏幕的宽、高
- lpImgInfoStr->width = gifheader->ScreenWidth;
- lpImgInfoStr->height = gifheader->ScreenHeight;
- // 获取位深度值
- lpImgInfoStr->bitcount = ((gifheader->GlobalFlagByte&0x70)>>4)+1;
- lpImgInfoStr->compression = ICS_GIFLZW;
- // 每一图像行所占的字节数(GIF中,此值没有意义,所以设为0)
- lpImgInfoStr->linesize = 0;
- // 图像的个数(如果是动态GIF,图像个数中将包括背景图像,所以要再加一)
- lpImgInfoStr->imgnumbers = (imgcount == 1) ? 1:imgcount+1;
- // 表示是否可被编辑(动画GIF将不能被编辑,所以设为1)
- lpImgInfoStr->imgchang = (imgcount == 1) ? 0:1;
- // 获取文件最后的修改日期(月在高字节,日在低字节)
- file.GetStatus(status);
- lpImgInfoStr->year = (WORD)status.m_mtime.GetYear();
- lpImgInfoStr->monday = (WORD)status.m_mtime.GetMonth();
- lpImgInfoStr->monday <<= 8;
- lpImgInfoStr->monday |= (WORD)status.m_mtime.GetDay();
- // 获取文件最后的修改时间(字序:最高—0, 2—时,1—分,0—秒)
- lpImgInfoStr->time = status.m_mtime.GetHour();
- lpImgInfoStr->time <<= 8;
- lpImgInfoStr->time |= status.m_mtime.GetMinute();
- lpImgInfoStr->time <<= 8;
- lpImgInfoStr->time |= status.m_mtime.GetSecond();
- lpImgInfoStr->time &= 0xffffff;
- ::GlobalFree(pFileContent);
- file.Close();
- // 设置出口数据
- pInfo->state = PKST_PASSINFO;
- pInfo->result = ER_SUCCESS;
- // 恢复初始值
- ::ZeroMemory((PVOID)&m_GifInfo, sizeof(GIFINFO));
- m_CurPalSize = 0; // 当前调色板项数(针对于局部调色板)
- m_CurDM = 0; // 当前的处置方法
- m_CurUserInput = 0; // 当前的用户输入标志
- m_CurTColorIndex = -1; // 当前的透明色索引号(-1表示无效)
- m_CurDelayTime = 0; // 当前的延迟时间(0表示没有延时)
- m_CurSaveMode = 0; // 当前的图像存储模式
- m_CurX = m_CurY = 0; // 当前图像在虚拟屏幕中的位置
- m_CurWidth = m_CurHeight = 0; // 当前图像的宽度、高度
- m_CurImgIndex = 0; // 当前图像的序号(0基)
- return;
- }
- // 操作命令解释函数---解释:CMD_LOAD_FROM_FILE命令
- // 从指定图像文件中读取数据
- void _fnCMD_LOAD_FROM_FILE(INFOSTR *pInfo)
- {
- // 检验入口参数是否符合接口定义
- ASSERT(pInfo->result == ER_EMPTY);
- ASSERT(::strlen(pInfo->filename));
- // 此时,该文件必需是一个已存在的、有效的GIF文件,并且数据包中
- // 含有该文件的信息(imginfo结构中)
- ASSERT(pInfo->state == PKST_PASSINFO);
- ASSERT(pInfo->imginfo.imgformat == IMF_GIF);
- ASSERT(pInfo->pImgInfo == NULL);
- // 必需设置标准图像格式信息
- ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
- ASSERT(pInfo->pLineAddr != NULL);
- ASSERT(pInfo->_pbdata != NULL);
- // 必需没有子图像链表
- ASSERT(pInfo->psubimg == NULL);
- CFile file;
- DWORD dwFileLen, uRet;
- PBYTE pFileContent;
- if (pInfo->fpProgress)
- {
- if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 6))
- { // 如果进度函数返回1,则说明用户想中断操作,返回。
- pInfo->result = ER_USERBREAK;
- return;
- }
- }
- // 打开指定文件
- if (!file.Open(pInfo->filename, CFile::modeRead))
- {
- pInfo->result = ER_FILERWERR;
- return;
- }
- // 获取文件长度
- dwFileLen = file.GetLength();
- // 分配内存,用于存放所有的GIF数据
- pFileContent = (PBYTE)::GlobalAlloc(GPTR, dwFileLen+1);
- if (!pFileContent)
- {
- file.Close();
- pInfo->result = ER_MEMORYERR;
- return;
- }
- file.SeekToBegin();
- // 读取整个的GIF文件到内存中
- uRet = file.ReadHuge((void*)pFileContent, dwFileLen);
- if (uRet != dwFileLen)
- {
- ::GlobalFree(pFileContent);
- file.Close();
- pInfo->result = ER_FILERWERR;
- return;
- }
- // 关闭GIF文件
- file.Close();
- // 读取并转换图像到数据包中
- if (LoadGIF(pFileContent, dwFileLen, pInfo) == TRUE)
- {
- // 成功
- pInfo->state = PKST_INFOANDBITS;
- pInfo->modify = 0;
- pInfo->result = ER_SUCCESS;
- }
-
- // 释放内存
- ::GlobalFree(pFileContent);
- // 恢复初始值
- ::ZeroMemory((PVOID)&m_GifInfo, sizeof(GIFINFO));
- m_CurPalSize = 0; // 当前调色板项数(针对于局部调色板)
- m_CurDM = 0; // 当前的处置方法
- m_CurUserInput = 0; // 当前的用户输入标志
- m_CurTColorIndex = -1; // 当前的透明色索引号(-1表示无效)
- m_CurDelayTime = 0; // 当前的延迟时间(0表示没有延时)
- m_CurSaveMode = 0; // 当前的图像存储模式
- m_CurX = m_CurY = 0; // 当前图像在虚拟屏幕中的位置
- m_CurWidth = m_CurHeight = 0; // 当前图像的宽度、高度
- m_CurImgIndex = 0; // 当前图像的序号(0基)
- m_pSubimgHead = NULL; // 子图像链表的头
- m_pSubimgTail = NULL; // 子图像链表的尾
- if (pInfo->fpProgress) // 结束进度条,此调用不再支持用户中断
- (*pInfo->fpProgress)(RWPROGRESSSIZE, RWPROGRESSSIZE);
- }
- // 操作命令解释函数---解释:CMD_SAVE_TO_FILE命令
- // 将数据保存到指定文件中
- void _fnCMD_SAVE_TO_FILE(INFOSTR *pInfo)
- {
- // 这个命令不一定要解释,你可以参考本图像格式的具体境况来决定
- // 是否解释该命令。
- // 如果你想解释该命令,请在下面加入代码,并修改pInfo->result的返回值:
- // ----------------------------------------------------------------->
- pInfo->result = ER_NOTSUPPORT;
- }
- // 操作命令解释函数---解释:CMD_RESIZE命令
- // 重新获取指定尺寸的图像位数据(只适用于矢量图像)
- void _fnCMD_RESIZE(INFOSTR *pInfo)
- {
- // 这个命令一般的图像读写模块不需要支持,它只适用于矢量图像,
- // 比如WMF、EMF之类。
- // 如果你想解释该命令,请在下面加入代码,并修改pInfo->result的返回值:
- // ----------------------------------------------------------------->
- pInfo->result = ER_NOTSUPPORT;
- }
- /*************************************************************************
- *
- * IsFileExist()
- *
- * 参数说明:
- *
- * char *lpFileName - 待判断的文件路径和名称(文件名)
- *
- * 返回值:
- *
- * BOOL - 如果指定的文件存在返回TRUE,否则返回FALSE。
- *
- * 描述:
- *
- * 判断指定的文件是否存在
- *
- * 该文件必需可以被读和写
- *
- ************************************************************************/
- BOOL IsFileExist(char *lpFileName)
- {
- CFile file;
- BOOL bExist = FALSE; // 文件存在是TRUE,不存在是FALSE
- CFileException e;
- // 确定指定的文件是否存在
- if (file.Open(lpFileName, CFile::modeReadWrite|CFile::shareDenyNone, &e))
- {
- bExist = TRUE;
- file.Close();
- }
- else
- {
- // 可能有其他程序正在处理此文件
- switch(e.m_cause)
- {
- case CFileException::tooManyOpenFiles:
- case CFileException::accessDenied:
- case CFileException::sharingViolation:
- case CFileException::lockViolation:
- return TRUE;
- case CFileException::fileNotFound:
- case CFileException::badPath:
- case CFileException::invalidFile:
- case CFileException::hardIO:
- default:
- return FALSE;
- }
- }
- return bExist;
- }
- // 返回TRUE表示读取成功,FALSE表示失败,同时数据包置错误信息
- BOOL LoadGIF(PBYTE pFileContent, DWORD filesize, LPINFOSTR pInfo)
- {
- //获取GIF文件的相关信息
- UINT HeaderSize = AnalizeFileHeader(pFileContent, filesize);
- if (HeaderSize == 0)
- {
- // 表明该文件是一个受损的文件
- pInfo->result = ER_BADIMAGE;
- return FALSE;
- }
- // 设置背景图像
- RGBQUAD * pBKColor = (RGBQUAD*)&(m_GlobalPal[m_GifInfo.bkindex]);
- int i,j;
- switch(_get_desformat(pInfo))
- {
- case DF_16_555: // 16位555格式(也就是15位图像)
- {
- WORD bkc555 = _cnv_rgb_to_555(pBKColor->rgbRed, pBKColor->rgbGreen,
- pBKColor->rgbBlue);
- WORD *pPix555;
- for (i=0;i<(int)pInfo->imginfo.height;i++)
- {
- pPix555 = (WORD*)(pInfo->pLineAddr[i]);
- for(j=0;j<(int)pInfo->imginfo.width;j++)
- *pPix555++ = bkc555;
- }
- }
- break;
- case DF_16_565: // 16位565格式
- {
- WORD bkc565 = _cnv_rgb_to_565(pBKColor->rgbRed, pBKColor->rgbGreen,
- pBKColor->rgbBlue);
- WORD *pPix565;
- for (i=0;i<(int)pInfo->imginfo.height;i++)
- {
- pPix565 = (WORD*)(pInfo->pLineAddr[i]);
- for(j=0;j<(int)pInfo->imginfo.width;j++)
- *pPix565++ = bkc565;
- }
- }
- break;
- case DF_24: // 24位格式
- {
- PBYTE pPix24;
- for (i=0;i<(int)pInfo->imginfo.height;i++)
- {
- pPix24 = (PBYTE)(pInfo->pLineAddr[i]);
- for(j=0;j<(int)pInfo->imginfo.width;j++)
- {
- *pPix24++ = pBKColor->rgbBlue;
- *pPix24++ = pBKColor->rgbGreen;
- *pPix24++ = pBKColor->rgbRed;
- }
- }
- }
- break;
- case DF_32: // 32位格式
- {
- DWORD bkc32 = _cnv_rgb_to_888(pBKColor->rgbRed, pBKColor->rgbGreen,
- pBKColor->rgbBlue);
- DWORD *pPix32;
- for (i=0;i<(int)pInfo->imginfo.height;i++)
- {
- pPix32 = (DWORD*)(pInfo->pLineAddr[i]);
- for(j=0;j<(int)pInfo->imginfo.width;j++)
- *pPix32++ = bkc32;
- }
- }
- break;
- }
- m_CurTColorIndex = -1;
- m_CurDelayTime = 0;
-
- // 跨过头结构
- PBYTE p = pFileContent+HeaderSize;
- UINT Offset;
- while (1)
- {
- if (p[0] == 0x21 && p[1] == 0xf9 && p[2] == 0x04)
- {// 图形扩展块
- Offset = GetGrphContent(p);
- p += Offset;
- }
- else if (p[0] == 0x21 && p[1] == 0x01 && p[2] == 0x0c)
- {// 文本扩展块
- Offset = ShowText(p);
- p += Offset;
- }
- else if (p[0] == 0x21 && p[1] == 0xff && p[2] == 0x0b)
- {// 应用程序扩展块
- Offset = GetAppContent(p);
- p += Offset;
- }
- else if (p[0] == 0x21 && p[1] == 0xfe)
- {// 注释扩展块
- Offset = GetNoteContent(p);
- p += Offset;
- }
- else if (p[0] == 0x2c)
- {// 图像描述符+[局部调色板]+图像数据块
- Offset = GetImage(p, pInfo);
- p += Offset;
- }
- else break;
- if (Offset == 0)
- {
- // 内存不足,失败
- _clear_list();
- pInfo->result = ER_MEMORYERR;
- return FALSE;
- }
- if (((DWORD)p-(DWORD)pFileContent) > filesize)
- {
- // 表明该文件是一个受损的文件
- _clear_list();
- pInfo->result = ER_BADIMAGE;
- return FALSE;
- }
- }
- // 子图像链表指针
- pInfo->psubimg = m_pSubimgHead;
- return TRUE;
- }
- /***************************************************************************
- * AnalizeFileHeader - 获得GIF文件信息
- *
- * Parameter: PBYTE - 完整的GIF文件数据首指针
- * DWORD - GIF文件的长度
- *
- * Result : UINT - GIF文件头结构尺寸(包括虚拟屏幕结构及全局调色板)
- * 如果返回0,则说明GIF文件是一个受损的文件
- ***************************************************************************/
- UINT AnalizeFileHeader(PBYTE pFileContent, DWORD filesize)
- {
- ASSERT(filesize > sizeof(GIFHEADER));
- GIFHEADER gifHeader; //文件头
- UINT uRet = sizeof(GIFHEADER);
- memcpy(&gifHeader,pFileContent,sizeof(GIFHEADER));
- // 取得图像(逻辑屏幕)的宽度、高度
- m_GifInfo.Width = gifHeader.ScreenWidth ;
- m_GifInfo.Height = gifHeader.ScreenHeight ;
- // 获取图像位深度
- m_GifInfo.BitCount = ((gifHeader.GlobalFlagByte&0x70)>>4)+1;
- // 获取GIF背景色索引
- m_GifInfo.bkindex = gifHeader.BackGroundColor;
- // 单个压缩数据初始位数
- m_GifInfo.InitPixelBits = (gifHeader.GlobalFlagByte&0x7)+2;
- // 获得图像的颜色个数
- m_GifInfo.ColorNum = 1<<((gifHeader.GlobalFlagByte&0x7)+1);
- if (gifHeader.GlobalFlagByte&0x80)
- {
- // 有全局调色板
- LPGIFRGB pRGB = (LPGIFRGB)(pFileContent+sizeof(GIFHEADER));
- for (int j=0;j<m_GifInfo.ColorNum;j++)
- {
- m_GlobalPal[j].rgbRed = pRGB[j].bRed;
- m_GlobalPal[j].rgbGreen = pRGB[j].bGreen;
- m_GlobalPal[j].rgbBlue = pRGB[j].bBlue;
- m_GlobalPal[j].rgbReserved = 0;
- }
- // 跨过全局调色板
- uRet += m_GifInfo.ColorNum*sizeof(GIFRGB);
- if (uRet >= filesize)
- uRet = 0; // 说明文件太小,可能是一个受损的GIF文件
- }
- return uRet;
- }
- // 处理图形扩展块
- UINT GetGrphContent(PBYTE pGrCtrl)
- {
- ASSERT(pGrCtrl);
- GRAPHCTRL GraphCtrl;
- memcpy(&GraphCtrl,pGrCtrl,sizeof(GRAPHCTRL));
- BYTE Flag = GraphCtrl.PackedField; // 包装域
- m_CurDM = (int)((BYTE)(Flag&0x1c)>>2); // 处置方式
- m_CurUserInput = (int)((BYTE)(Flag&0x2)>>1); // 用户输入标志
- m_CurDelayTime = GraphCtrl.DelayTime; // 延迟时间
-
- if (Flag&1) // 判断是否有透明色
- m_CurTColorIndex = GraphCtrl.TranColorIndex;
- else
- m_CurTColorIndex = -1;
- return sizeof(GRAPHCTRL);
- }
- // 处理文本扩展块
- UINT ShowText(PBYTE pText)
- {
- ASSERT(pText);
- TEXTCTRL TextCtrl;
- memcpy(&TextCtrl,pText,sizeof(TEXTCTRL));
- return sizeof(TEXTCTRL)+TextCtrl.Data[0]-256+1;
- }
- // 处理应用程序扩展块
- UINT GetAppContent(PBYTE pApp)
- {
- ASSERT(pApp);
- APPCTRL AppCtrl;
- memcpy(&AppCtrl,pApp,sizeof(APPCTRL));
- return sizeof(APPCTRL)+AppCtrl.Data[0]-256+1;
- }
- // 处理注释扩展块
- UINT GetNoteContent(PBYTE pNote)
- {
- ASSERT(pNote);
- NOTEHCTRL NoteCtrl;
- memcpy(&NoteCtrl,pNote,sizeof(NOTEHCTRL));
- return sizeof(NOTEHCTRL)+NoteCtrl.Data[0]-256+1;
- }
- // 处理图像数据区
- UINT GetImage(PBYTE pData, LPINFOSTR pInfo)
- {
- ASSERT(pData);
- IMAGEDATAINFO ImageData;
- // 提取图像描述
- memcpy(&ImageData,pData,sizeof(IMAGEDATAINFO));
- PBYTE p = pData+sizeof(IMAGEDATAINFO);
- UINT PalSize;
- m_CurX = ImageData.ImageLeft;
- m_CurY = ImageData.ImageTop ;
- m_CurWidth = ImageData.ImageWidth ;
- m_CurHeight = ImageData.ImageHeight;
- // 判断是否有局部调色板
- if (ImageData.LocalFlagByte&0x80)
- {
- LPGIFRGB pRGB = (LPGIFRGB)p;
- // 计算局部调色版的项数
- m_CurPalSize = 1<<((ImageData.LocalFlagByte&0x7)+1);
- // 有关文档对这个值描述的不是很清楚,为保险起见作了
- // 如下判断。
- if ((m_CurPalSize <= 0)||(m_CurPalSize > 256))
- m_CurPalSize = m_GifInfo.ColorNum;
- for (int j=0;j<m_CurPalSize;j++)
- {
- m_CurRgbQuad[j].rgbRed = pRGB[j].bRed;
- m_CurRgbQuad[j].rgbGreen = pRGB[j].bGreen;
- m_CurRgbQuad[j].rgbBlue = pRGB[j].bBlue;
- m_CurRgbQuad[j].rgbReserved = 0;
- }
- // 计算调色板尺寸(字节数)
- PalSize = m_CurPalSize*sizeof(GIFRGB);
- // 跨过局部调色板
- p += PalSize;
- }
- else
- {
- // 如果没有局部调色板,用全局调色板数据替代
- m_CurPalSize = m_GifInfo.ColorNum;
- memcpy((void*)m_CurRgbQuad, (void*)m_GlobalPal, m_CurPalSize*sizeof(RGBQUAD));
- PalSize = 0;
- }
- // 设置图像存储模式标志
- if (ImageData.LocalFlagByte&0x40)
- m_CurSaveMode = 1; // 交叉存储
- else
- m_CurSaveMode = 0; // 顺序存储
- UINT InitBits = *p++;//跳过第一字节,进入真正的段落
-
- UINT offset; // 数据区在文件中的尺寸(将包括GIF附加的描述符)
- // 获取当前数据区的尺寸(纯数据尺寸)
- UINT dataCount = GetCodeCountOnChar(p, offset);
- // 获取当前数据区内容
- PBYTE pCodeData = GetCodeDataOnChar(p, dataCount);
- if (!pCodeData)
- return 0;
- // 提取真实数据,所有数据存为字符大小
- PBYTE pTrueCodeData = GetCodeDataOnBits(pCodeData,
- m_GifInfo.InitPixelBits, dataCount);
- if (!pTrueCodeData)
- {
- ::GlobalFree(pCodeData);
- return 0;
- }
- ::GlobalFree(pCodeData);
- // 将GIF图像数据保存(并转化)到子图像链表中
- BOOL bRet;
- if (pInfo->imginfo.imgnumbers > 1) // 多帧GIF图像
- bRet = ConvertToBmpImage(pTrueCodeData, pInfo);
- else // 单帧GIF图像
- bRet = ConvertToBackgroup(pTrueCodeData, pInfo);
- ::GlobalFree(pTrueCodeData);
- if (bRet == FALSE)
- return 0;
- else
- return sizeof(IMAGEDATAINFO) + offset + PalSize;
- }
- // 计算图像位数据的尺寸
- UINT GetCodeCountOnChar (PBYTE CodeDataStr,UINT &AllDataLen)
- {
- UINT dataCount = 0;
- BYTE dataLen;
- PBYTE p1 = CodeDataStr;
- AllDataLen = 0;
- while(1)
- {
- dataLen = *p1++; // 提取长度描述字节值,并后移指针
- p1 += dataLen;
- dataCount += dataLen;
- AllDataLen += (dataLen+1); // 数据子块长度加长度描述字节
- if (dataLen == 0x00) break;
- }
- AllDataLen ++; // 跨过LZW初始位值的一个字节
- return dataCount;
- }
- // 将GIF中的纯LZW图像数据提取到新的内存块中
- PBYTE GetCodeDataOnChar(PBYTE CodeDataStr, UINT dataCount)
- {
- ASSERT(CodeDataStr);
- PBYTE pData = (PBYTE)::GlobalAlloc(GPTR, dataCount+1);
- if (!pData)
- return NULL;
- PBYTE p2 = pData;
- PBYTE p1 = CodeDataStr;
- BYTE dataLen;
- while (1)
- {
- dataLen = *p1++;
- if (dataLen == 0x00)
- break;
- memcpy(p2,p1,dataLen);
- p1 += dataLen;
- p2 += dataLen;
- }
- return pData;
- }
- // 将指定的LZW数据解压为位图数据
- PBYTE GetCodeDataOnBits (PBYTE CodeDataStr ,UINT InitLen ,UINT &CodeDataLen)
- {
- ASSERT(CodeDataStr);
- PBYTE pData = (PBYTE)::GlobalAlloc(GPTR ,m_CurWidth*m_CurHeight*2);
- if (!pData)
- return NULL;
- PBYTE p = CodeDataStr;
- PBYTE pTrueData = pData;
-
- int i = 0;
- UINT BitsCount = 0;
- WORD TCode,s = m_GifInfo.ColorNum+2;//起始的代码值
- UINT TableLen,iLen = InitLen;
- UINT Pos,index,j = 0;
- UINT SrcCodeLEN = CodeDataLen;
- while (1)
- {
- TCode = GetOneCode(p, CodeDataLen,BitsCount/8, BitsCount%8, iLen);
- BitsCount += iLen;
- if (TCode < m_GifInfo.ColorNum)
- {
- LZWTable[j].Header = TCode;
- LZWTable[j].Code = s ++;
- if (j != 0)
- {
- LZWTable[j - 1].Tail = TCode;
- }
- j++;
- }
- else if (TCode > m_GifInfo.ColorNum + 1) // 代码
- {
- if (j == 0) continue;
- LZWTable[j].Header = TCode;
- LZWTable[j].Code = s ++;
- ASSERT( LZWTable[j].Header < LZWTable[j].Code);
- index = j - 1;
- Pos = j;
- while (1)
- {
- Pos = LZWTable[Pos].Header - (m_GifInfo.ColorNum + 2) ;
- if (LZWTable[Pos].Header < m_GifInfo.ColorNum)
- break;
- }
- LZWTable[index].Tail = LZWTable[Pos].Header;
- j++;
- }
- else if (TCode == m_GifInfo.ColorNum) // 清除码
- {
- iLen = InitLen;
- TableLen = j;
- j = 0;
- if (GetPartImageDataFromTable(pData,LZWTable,TableLen) == FALSE)
- {
- ::GlobalFree(pTrueData);
- return NULL;
- }
- //pData+=TableLen;
- s = m_GifInfo.ColorNum + 2 ;
- }
- else if (TCode == m_GifInfo.ColorNum + 1) // 结束码
- {
- //end build table
- iLen = InitLen;
- TableLen = j;
- if (GetPartImageDataFromTable(pData,LZWTable,TableLen) == FALSE)
- {
- ::GlobalFree(pTrueData);
- return NULL;
- }
- //pData+=TableLen;
- s = m_GifInfo.ColorNum + 2;
- break;
- }
- if (s == 3)
- iLen = 2;
- else if (s == 5)
- iLen = 3;
- else if (s == 9)
- iLen = 4;
- else if (s == 17)
- iLen = 5;
- else if (s == 33)
- iLen = 6;
- else if (s == 65)
- iLen = 7;
- else if (s == 129)
- iLen = 8;
- else if (s == 257)
- iLen = 9;
- else if ( s == 513 )
- iLen = 10;
- else if (s == 1025 )
- iLen = 11;
- else if (s == 2049 )
- iLen = 12;
-
- if (BitsCount/8 > SrcCodeLEN)
- {
- iLen = InitLen;
- TableLen = j;
- if (GetPartImageDataFromTable(pData,LZWTable,TableLen) == FALSE)
- {
- ::GlobalFree(pTrueData);
- return NULL;
- }
- //pData+=TableLen;
- s = m_GifInfo.ColorNum + 2;
- break;
- }
-
- }
- CodeDataLen = BitsCount/8;
-
- return pTrueData;
- }
- WORD GetOneCode(PBYTE CodeStr ,UINT CodeStrLen, UINT OffsetChar,
- UINT OffsetBits, UINT Length)
- {
- ASSERT (Length <= 12);
-
- PBYTE pValue;
- PBYTE lp = CodeStr;
-
- DWORD value = 0;
- pValue = (PBYTE)&value;
- pValue[0] = lp[OffsetChar+0];
- if (OffsetChar + 1 < CodeStrLen)
- pValue[1] = lp[OffsetChar+1];
- if (OffsetChar + 2 < CodeStrLen)
- pValue[2] = lp[OffsetChar+2];
- if (OffsetChar + 3 < CodeStrLen)
- pValue[3] = lp[OffsetChar+3];
- value = value >> OffsetBits;
- value = value << (32 - Length);
- value = value >> (32 - Length);
- return (WORD)value;
- }
- //
- BOOL GetPartImageDataFromTable(PBYTE &pImage, LZWTABLE *Table, UINT TableLen)
- {
- UINT i;
- PBYTE p = pImage;
- WORD *TailStack = (WORD*)::GlobalAlloc(GPTR, LZWTABLESIZE*sizeof(WORD));
- if (!TailStack)
- return FALSE;
- int j;
- int sp;
- for (i = 0 ; i < TableLen; i++)
- {
- if (Table[i].Header < m_GifInfo.ColorNum)
- {
- *p++ = (BYTE)Table[i].Header ;
- }
- else
- {
- sp = 0;
- j = Table[i].Header - (m_GifInfo.ColorNum + 2);
- while (Table[j].Header > m_GifInfo.ColorNum + 1)
- {
- TailStack[sp++] = Table[j].Tail ;
- j = Table[j].Header;
- j -= (m_GifInfo.ColorNum + 2);
- ASSERT(sp < LZWTABLESIZE);
- }
- *p++ = (BYTE)Table[j].Header;
- *p++ = (BYTE)Table[j].Tail;
- sp --;
- while (sp >= 0)
- {
- *p++ = (BYTE)TailStack[sp--];
- }
- }
- }
- int len = p - pImage;
- pImage = p;
-
- ::GlobalFree(TailStack);
- return TRUE;
- }
- // 将GIF图像保存到数据包背景图像中(只针对单帧GIF图像)
- BOOL ConvertToBackgroup(PBYTE SrcData,LPINFOSTR lpInfo)
- {
- ASSERT(SrcData);
- ASSERT(lpInfo->imginfo.imgnumbers == 1);
- PBYTE p2,pTmp;
- PBYTE pSrcData = SrcData;
-
- int i,j,k,Step,index;
- if (m_CurSaveMode )//交叉存储
- {
- pTmp = p2 = (PBYTE)::GlobalAlloc(GPTR, m_CurWidth*m_CurHeight);
- if (!pTmp)
- return FALSE;
-
- k = 0; Step = 8;
- for (j = 0; j < m_CurHeight ; j ++)
- {
- memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
- k += Step;
- if (k >= m_CurHeight) break;
- }
- j++;//每行中存了一个越界值
- k = 4; Step = 8;
- for (; j < m_CurHeight ; j ++)
- {
- memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
- k += Step;
- if (k >= m_CurHeight) break;
- }
- j++;
- k = 2; Step = 4;
- for (; j < m_CurHeight ; j ++)
- {
- memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
- k += Step;
- if (k >= m_CurHeight) break;
- }
- j++;
- k = 1; Step = 2;
- for (; j < m_CurHeight ; j ++)
- {
- memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_GifInfo.Width);
- k += Step;
- if (k >= m_CurHeight) break;
- }
- pSrcData = p2;
- p2 = NULL;
- }
- // 转换图像到数据包指定格式
- switch(_get_desformat(lpInfo))
- {
- case DF_16_555: // 16位555格式(也就是15位图像)
- {
- for (j=0;j<m_CurHeight;j++)
- {
- WORD *pImg555 = (WORD*)(lpInfo->pLineAddr[j]);
- for (i=0;i<m_CurWidth;i++)
- {
- index = pSrcData[j*m_CurWidth+i];
- WORD bkc555 = _cnv_rgb_to_555(m_CurRgbQuad[index].rgbRed,
- m_CurRgbQuad[index].rgbGreen,
- m_CurRgbQuad[index].rgbBlue);
- *pImg555++ = bkc555;
- }
- }
- }
- break;
- case DF_16_565: // 16位565格式
- {
- for (j=0;j<m_CurHeight;j++)
- {
- WORD *pImg565 = (WORD*)(lpInfo->pLineAddr[j]);
- for (i=0;i<m_CurWidth;i++)
- {
- index = pSrcData[j*m_CurWidth+i];
- WORD bkc565 = _cnv_rgb_to_565(m_CurRgbQuad[index].rgbRed,
- m_CurRgbQuad[index].rgbGreen,
- m_CurRgbQuad[index].rgbBlue);
- *pImg565++ = bkc565;
- }
- }
- }
- break;
- case DF_24: // 24位格式
- {
- for (j=0;j<m_CurHeight;j++)
- {
- PBYTE pImg24 = (PBYTE)(lpInfo->pLineAddr[j]);
- for (i=0;i<m_CurWidth;i++)
- {
- index = pSrcData[j*m_CurWidth+i];
- *pImg24++ = m_CurRgbQuad[index].rgbBlue;
- *pImg24++ = m_CurRgbQuad[index].rgbGreen;
- *pImg24++ = m_CurRgbQuad[index].rgbRed;
- }
- }
- }
- break;
- case DF_32: // 32位格式
- {
- for (j=0;j<m_CurHeight;j++)
- {
- DWORD *pImg32 = (DWORD*)(lpInfo->pLineAddr[j]);
- for (i=0;i<m_CurWidth;i++)
- {
- index = pSrcData[j*m_CurWidth+i];
- DWORD bkc32 = _cnv_rgb_to_888( m_CurRgbQuad[index].rgbRed,
- m_CurRgbQuad[index].rgbGreen,
- m_CurRgbQuad[index].rgbBlue);
- *pImg32++ = bkc32;
- }
- }
- }
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- if (m_CurSaveMode) //交叉存储
- GlobalFree(pSrcData);
- return TRUE;
- }
- // 将某一子图像保存到子图像链表中
- BOOL ConvertToBmpImage(PBYTE SrcData, LPINFOSTR lpInfo)
- {
- ASSERT(SrcData);
- PBYTE p2,pTmp;
- PBYTE pSrcData = SrcData;
-
- int i,j,k,Step,index;
- if (m_CurSaveMode )//交叉存储
- {
- pTmp = p2 = (PBYTE)::GlobalAlloc(GPTR, m_CurWidth*m_CurHeight);
- if (!pTmp)
- return FALSE;
-
- k = 0; Step = 8;
- for (j = 0; j < m_CurHeight ; j ++)
- {
- memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
- k += Step;
- if (k >= m_CurHeight) break;
- }
- j++;//每行中存了一个越界值
- k = 4; Step = 8;
- for (; j < m_CurHeight ; j ++)
- {
- memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
- k += Step;
- if (k >= m_CurHeight) break;
- }
- j++;
- k = 2; Step = 4;
- for (; j < m_CurHeight ; j ++)
- {
- memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_CurWidth);
- k += Step;
- if (k >= m_CurHeight) break;
- }
- j++;
- k = 1; Step = 2;
- for (; j < m_CurHeight ; j ++)
- {
- memcpy(pTmp+k*m_CurWidth,pSrcData+j*m_CurWidth,m_GifInfo.Width);
- k += Step;
- if (k >= m_CurHeight) break;
- }
- pSrcData = p2;
- p2 = NULL;
- }
- LPSUBIMGBLOCK pSubImage = (LPSUBIMGBLOCK)::GlobalAlloc(GPTR, sizeof(SUBIMGBLOCK));
- if (!pSubImage)
- {
- if (m_CurSaveMode )//交叉存储
- ::GlobalFree(pSrcData);
- return FALSE;
- }
- pSubImage->parents = lpInfo;// 第一桢图像数据的结构地址(所属数据包结构的地址)
- pSubImage->prev = NULL; // 前一桢图像数据的结构地址
- pSubImage->next = NULL; // 后一桢图像数据的结构地址(NULL表示这是最后一副图像)
- DWORD desize = 0; // 子图像BMP格式的尺寸
- DWORD scanlinesize = 0; // 子图像扫描行尺寸
- // 获取数据包标准图像格式之子图像尺寸
- switch(_get_desformat(lpInfo))
- {
- case DF_16_555: // 16位555格式(也就是15位图像)
- case DF_16_565: // 16位565格式
- scanlinesize = WIDTHBYTES(m_CurWidth*16);
- break;
- case DF_24: // 24位格式
- scanlinesize = WIDTHBYTES(m_CurWidth*24);
- case DF_32: // 32位格式
- scanlinesize = m_CurWidth*4;
- break;
- default:
- ASSERT(FALSE);
- if (m_CurSaveMode )//交叉存储
- ::GlobalFree(pSrcData);
- return FALSE;
- }
- desize = scanlinesize*m_CurHeight;
-
- ASSERT(desize); // 宽度或高度不能是0
- // 分配子图像位数据缓冲区
- pSubImage->pLineAddr = (DWORD**)::GlobalAlloc(GPTR, m_CurHeight*sizeof(DWORD*));
- pSubImage->_pbdata = (PBYTE)::GlobalAlloc(GPTR, desize);
- if ((pSubImage->pLineAddr == NULL)||(pSubImage->_pbdata == NULL))
- {
- if (m_CurSaveMode) ::GlobalFree(pSrcData);
- if (pSubImage->_pbdata) ::GlobalFree(pSubImage->_pbdata);
- if (pSubImage->pLineAddr) ::GlobalFree(pSubImage->pLineAddr);
- return FALSE;
- }
- // 初始化行首地址数组(倒向DIB格式)
- for (int y=0;y<m_CurHeight;y++)
- {
- pSubImage->pLineAddr[y] =
- (DWORD*)(pSubImage->_pbdata+((m_CurHeight-y-1)*scanlinesize));
- }
- pSubImage->number = m_CurImgIndex++; // 子图像块的序列号
- pSubImage->left = m_CurX; // 子图像块的显示位置(左上角)
- pSubImage->top = m_CurY;
- pSubImage->width = m_CurWidth; // 子图像块的图像宽度及高度
- pSubImage->height = m_CurHeight;
- pSubImage->dowith = m_CurDM; // 处置方法(针对于动画GIF)
- pSubImage->userinput = m_CurUserInput; // 用户输入(针对于动画GIF)
-
- if (m_CurTColorIndex != -1) // 透明色分量值(-1表示无效)
- {
- pSubImage->colorkey = RGB(m_CurRgbQuad[m_CurTColorIndex].rgbRed,
- m_CurRgbQuad[m_CurTColorIndex].rgbGreen,
- m_CurRgbQuad[m_CurTColorIndex].rgbBlue);
- }
- else
- pSubImage->colorkey = (COLORREF)((int)(-1));
- pSubImage->time = (int)m_CurDelayTime; // 显示的延迟时间
-
- // 将子图像块插入链表
- if (m_pSubimgTail == NULL) // 当前是空链表
- {
- m_pSubimgHead = pSubImage;
- m_pSubimgTail = pSubImage;
- }
- else
- {
- ASSERT(m_pSubimgHead->prev == NULL); // 检察链表的有效性
- ASSERT(m_pSubimgTail->next == NULL);
- m_pSubimgTail->next = pSubImage;
- pSubImage->prev = m_pSubimgTail;
- m_pSubimgTail = pSubImage;
- }
- // 转换图像到数据包指定格式
- switch(_get_desformat(lpInfo))
- {
- case DF_16_555: // 16位555格式(也就是15位图像)
- {
- for (j=0;j<m_CurHeight;j++)
- {
- WORD *pImg555 = (WORD*)(pSubImage->pLineAddr[j]);
- for (i=0;i<m_CurWidth;i++)
- {
- index = pSrcData[j*m_CurWidth+i];
- WORD bkc555 = _cnv_rgb_to_555(m_CurRgbQuad[index].rgbRed,
- m_CurRgbQuad[index].rgbGreen,
- m_CurRgbQuad[index].rgbBlue);
- *pImg555++ = bkc555;
- }
- }
- }
- break;
- case DF_16_565: // 16位565格式
- {
- for (j=0;j<m_CurHeight;j++)
- {
- WORD *pImg565 = (WORD*)(pSubImage->pLineAddr[j]);
- for (i=0;i<m_CurWidth;i++)
- {
- index = pSrcData[j*m_CurWidth+i];
- WORD bkc565 = _cnv_rgb_to_565(m_CurRgbQuad[index].rgbRed,
- m_CurRgbQuad[index].rgbGreen,
- m_CurRgbQuad[index].rgbBlue);
- *pImg565++ = bkc565;
- }
- }
- }
- break;
- case DF_24: // 24位格式
- {
- for (j=0;j<m_CurHeight;j++)
- {
- PBYTE pImg24 = (PBYTE)(pSubImage->pLineAddr[j]);
- for (i=0;i<m_CurWidth;i++)
- {
- index = pSrcData[j*m_CurWidth+i];
- *pImg24++ = m_CurRgbQuad[index].rgbBlue;
- *pImg24++ = m_CurRgbQuad[index].rgbGreen;
- *pImg24++ = m_CurRgbQuad[index].rgbRed;
- }
- }
- }
- break;
- case DF_32: // 32位格式
- {
- for (j=0;j<m_CurHeight;j++)
- {
- DWORD *pImg32 = (DWORD*)(pSubImage->pLineAddr[j]);
- for (i=0;i<m_CurWidth;i++)
- {
- index = pSrcData[j*m_CurWidth+i];
- DWORD bkc32 = _cnv_rgb_to_888( m_CurRgbQuad[index].rgbRed,
- m_CurRgbQuad[index].rgbGreen,
- m_CurRgbQuad[index].rgbBlue);
- *pImg32++ = bkc32;
- }
- }
- }
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- if (m_CurSaveMode) //交叉存储
- GlobalFree(pSrcData);
- return TRUE;
- }
- // 获取GIF文件中图像的个数
- // 参数pFileContent指向的缓冲区必须包括完整的GIF文件内容
- // 参数filesize是指明pFileContent所指向的缓冲区的尺寸(即GIF文件的尺寸)
- // 函数返回图像的个数,如果文件内容非法(比如是个受损的GIF文件),则返回0
- int _get_imgcount(PBYTE pFileContent, DWORD filesize)
- {
- ASSERT(pFileContent);
- ASSERT(pFileContent[0] == 'G');
- PBYTE p = pFileContent;
- GIFHEADER gifHeader; // 文件头
- memcpy(&gifHeader,p,sizeof(GIFHEADER));
- // 跨过GIF文件头及逻辑屏幕描述块
- p += sizeof(GIFHEADER);
- // 判断是否存在全局调色板,如果存在则跨过该调色板
- if (gifHeader.GlobalFlagByte&0x80)
- p += (1<<((gifHeader.GlobalFlagByte&0x7)+1))*sizeof(GIFRGB);
- int imgcount = 0;
- // 分解数据区
- while (1)
- {
- if (p[0] == 0x21 && p[1] == 0xf9 && p[2] == 0x4) // 图形扩展块
- p += sizeof(GRAPHCTRL);
- else if (p[0] == 0x21 && p[1] == 0x1 && p[2] == 0xc)// 文本扩展块
- p += sizeof(TEXTCTRL)-(255-((LPTEXTCTRL)p)->Data[0]);
- else if (p[0] == 0x21 && p[1] == 0xff && p[2] == 0xb)// 应用程序扩展块
- p += sizeof(APPCTRL)-(255-((LPAPPCTRL)p)->Data[0]);
- else if (p[0] == 0x21 && p[1] == 0xfe) // 注释扩展块
- p += sizeof(NOTEHCTRL)-(255-((LPNOTEHCTRL)p)->Data[0]);
- else if (p[0] == 0x2c) // 图像描述符+[局部调色板]+图像数据块
- {
- IMAGEDATAINFO ImageData; // 图像数据块
- // 跨过图像描述符结构
- memcpy(&ImageData,p,sizeof(IMAGEDATAINFO));
- p += sizeof(IMAGEDATAINFO);
- // 如果拥有局部调色板数据,则跨过
- if (ImageData.LocalFlagByte&0x80)
- p += (1<<(ImageData.LocalFlagByte&0x7+1))*sizeof(GIFRGB);
- p++; // 越过LZW初始位值
- BYTE dataLen;
- // 跨过经压缩的图像数据
- while (1)
- {
- if ((((DWORD)p)-((DWORD)pFileContent)) > filesize)
- return 0; // 受损的文件
- dataLen = *p++;
- p += dataLen;
- if (dataLen == 0x0)
- break;
- }
- // 图像个数加1
- imgcount++;
- }
- else
- break;
- if ((((DWORD)p)-((DWORD)pFileContent)) > filesize)
- return 0; // 受损的文件
- }
- // 返回GIF文件中的图像个数
- return imgcount;
- }
- // 判断标准图像的位格式
- DESFORMAT _get_desformat(LPINFOSTR pInfo)
- {
- ASSERT(pInfo);
- // ASSERT(pInfo->state >= PKST_PASSVER);
- ASSERT(pInfo->sDIBInfo.bmi.biPlanes == 1);
- DESFORMAT result;
- switch(pInfo->sDIBInfo.bmi.biBitCount)
- {
- case 32:
- /******************************************************
- 32位掩码示意图
- 高 -> 低
- 0000 0000 0000 0000 0000 0000 0000 0000 888格式
- 1111 1111 ------------------------R
- 1111 1111 -------------G
- 1111 1111--B
- * Win95 系统只支持这一种格式
- ******************************************************/
- if (pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
- {
- result = DF_32;
- break;
- }
- if ((pInfo->sDIBInfo.rmask == 0xff0000)&&
- (pInfo->sDIBInfo.gmask == 0xff00)&&
- (pInfo->sDIBInfo.bmask == 0xff))
- result = DF_32;
- else
- {
- ASSERT(FALSE); // 只支持888格式
- result = DF_NULL;
- }
- break;
- case 24:
- result = DF_24;
- break;
- case 16:
- /*******************************************
- 16位掩码示意图
- 高字节 低字节
- 0000 0000 0000 0000
- 1 1111--B // 555格式
- 11 111 -------G
- 111 11 --------------R
- 0
- 1 1111--B // 565格式
- 111 111 -------G
- 1111 1 --------------R
- * Win95 系统只支持以上两种格式
- *******************************************/
- if (pInfo->sDIBInfo.bmi.biCompression == BI_RGB)
- {
- result = DF_16_555;
- break;
- }
- if ((pInfo->sDIBInfo.rmask == 0x7c00)&&
- (pInfo->sDIBInfo.gmask == 0x3e0)&&
- (pInfo->sDIBInfo.bmask == 0x1f))
- result = DF_16_555;
- else if ((pInfo->sDIBInfo.rmask == 0xf800)&&
- (pInfo->sDIBInfo.gmask == 0x7e0)&&
- (pInfo->sDIBInfo.bmask == 0x1f))
- result = DF_16_565;
- else
- result = DF_NULL;
- break;
- default:
- ASSERT(FALSE); // 不接受其它格式
- result = DF_NULL;
- break;
- }
- return result;
- }
- // 将指定的RGB颜色分量转换成555格式(WORD型值返回)
- WORD _cnv_rgb_to_555(BYTE red, BYTE green, BYTE blue)
- {
- WORD result = 0;
- result = (((WORD)red>>3)<<10)|(((WORD)green>>3)<<5)|((WORD)blue>>3);
- return result;
- }
- // 将指定的555格式的颜色转换成RGB颜色分量
- void _cnv_555_to_rgb(WORD col, PBYTE red, PBYTE green, PBYTE blue)
- {
- // 在555转换到RGB时,将像素的亮度调到最大
- *red = (BYTE)((col>>7)&0xf8);
- *green = (BYTE)((col>>2)&0xf8);
- *blue = (BYTE)(col<<3);
- }
- // 将指定的RGB颜色分量转换成565格式(WORD型值返回)
- WORD _cnv_rgb_to_565(BYTE red, BYTE green, BYTE blue)
- {
- WORD result = 0;
- result = (((WORD)red>>3)<<11)|(((WORD)green>>2)<<5)|((WORD)blue>>3);
- return result;
- }
- // 将指定的565格式的颜色转换成RGB颜色分量
- void _cnv_565_to_rgb(WORD col, PBYTE red, PBYTE green, PBYTE blue)
- {
- // 在565转换到RGB时,将像素的亮度调到最大
- *red = (BYTE)((col>>8)&0xf8);
- *green = (BYTE)((col>>3)&0xfc);
- *blue = (BYTE)(col<<3);
- }
- // 将指定的RGB颜色分量转换成888格式(DWORD型值返回)
- DWORD _cnv_rgb_to_888(BYTE red, BYTE green, BYTE blue)
- {
- DWORD result = 0;
- result = ((DWORD)red<<16)|((DWORD)green<<8)|(DWORD)blue;
- return result;
- }
- // 清除子图像链表
- void _clear_list(void)
- {
- if (m_pSubimgTail == NULL)
- return;
- ASSERT(m_CurImgIndex);
- LPSUBIMGBLOCK lpSubImg;
- while((lpSubImg=m_pSubimgTail) != NULL)
- {
- m_pSubimgTail = lpSubImg->prev;
- lpSubImg->number = 0; // 子图像块的序列号
- lpSubImg->left = lpSubImg->top = 0; // 子图像块的显示位置(左上角)
- lpSubImg->width = lpSubImg->height = 0; // 子图像块的图像宽度及高度
- lpSubImg->dowith = 0; // 处置方法(针对于动画GIF)
- lpSubImg->userinput = 0; // 用户输入(针对于动画GIF)
- lpSubImg->colorkey = 0; // 透明色分量值
- lpSubImg->time = 0; // 显示的延迟时间
- if (lpSubImg->pLineAddr)
- ::GlobalFree(lpSubImg->pLineAddr);
- if (lpSubImg->_pbdata)
- ::GlobalFree(lpSubImg->_pbdata);
-
- lpSubImg->parents = NULL; // 第一桢图像数据的结构地址(所属数据包结构的地址)
- lpSubImg->prev = NULL; // 前一桢图像数据的结构地址
- lpSubImg->next = NULL; // 后一桢图像数据的结构地址(NULL表示这是最后一副图像)
- ::GlobalFree(lpSubImg);
- };
- m_pSubimgHead = NULL;
- m_CurImgIndex = 0;
-
- return;
- }