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文件。

posted @ 2022-03-14 09:41  strnghrs  阅读(424)  评论(0编辑  收藏  举报