VC调用giflib(2):EGifOpen、DGifOpen用法
作者:马健
邮箱:stronghorse_mj@hotmail.com
主页:http://www.comicer.com/stronghorse
发布:2020.03.14
早期版本的giflib对GIF编码、解码均只提供针对文件的接口,如解码的DGifOpenFileName、DGifOpenFileHandle函数。从v5开始增加了EGifOpen、DGifOpen函数,可以更灵活地操作GIF文件,如解码内存中的GIF文件、在内存中编码GIF文件,或打开Unicode文件名的文件。
giflib官方文档对这两个新增接口说得含含糊糊,网上也有人在问究竟应该怎么用,我也是绕了一下才搞清楚,所以在这里记录一下。
这两个接口的核心思想是,把读、写操作变成函数指针,具体是在内存还是在文件中读、写,完全看函数指针所指的函数是怎么实现的。dgif_lib.c中的InternalRead函数、egif_lib.c中的InternalWrite函数就提供了读、写函数的例子,看懂了其中针对FILE*的操作,即可在此基础上写出自己的读、写函数。
例如,如果想解码内存缓冲区中的GIF文件,则可以这样写代码:
struct GifData { const unsigned char* m_lpBuffer; size_t m_nBufferSize; size_t m_nPosition; }; // copied from CMemFile::Read int InternalRead_Mem(GifFileType *gif, GifByteType *buf, int len) { if (len == 0) return 0; GifData* pData = (GifData*)gif->UserData; if (pData->m_nPosition > pData->m_nBufferSize) return 0; UINT nRead; if (pData->m_nPosition + len > pData->m_nBufferSize || pData->m_nPosition + len < pData->m_nPosition) nRead = (UINT)(pData->m_nBufferSize - pData->m_nPosition); else nRead = len; memcpy((BYTE*)buf, (BYTE*)pData->m_lpBuffer + pData->m_nPosition, nRead); pData->m_nPosition += nRead; return nRead; } // 解码内存缓冲区中的GIF文件,文件首地址pBuffer,文件长度dwLen,结果存入pImage BOOL LoadGifFromBuffer(BYTE* pBuffer, CxImage* pImage, DWORD dwLen) { // DGifOpen要的数据结构 GifData data; memset(&data, 0, sizeof(data)); data.m_lpBuffer = pBuffer; data.m_nBufferSize = dwLen; // 打开GIF文件 GifFileType* gif = DGifOpen(&data, InternalRead_Mem, NULL); …… }
如果基于MFC的CFile类,则可以一次性解决Unicode文件名和在内存中对GIF文件进行操作的问题,如下面的代码:
// 写GIF文件内容到CFile int InternalWrite_CFile(GifFileType *gif, const GifByteType *buf, int len) { CFile* pData = (CFile*)gif->UserData; pData->Write(buf, len); return len; } // 生成GIF文件,pszTgtPath是目标路径 BOOL MakeGif(LPCTSTR pszTgtPath, ……) { // 打开输出的 GIF 文件
CFile fileOut;
GifFileType* GifFile; if (!fileOut.Open(pszTgtPath, CFile::modeCreate|CFile::modeWrite)) return FALSE; if ((GifFile = EGifOpen(&fileOut, InternalWrite_CFile, NULL)) == NULL) return FALSE; …… }
如果在上面的MakeGif函数里,把CFile换成CMemFile,使用同样的InternalWrite_CFile函数,则可以实现在内存里生成GIF文件。