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

  • 相关阅读:
    2019长安大学ACM校赛网络同步赛 J Binary Number(组合数学+贪心)
    棋盘问题
    DP待整理
    Monkey and Banana(DP)
    Ignatius and the Princess IV
    【[kuangbin带你飞]专题十二 基础DP1】Max Sum Plus Plus(DP+滚动数组)
    第三届山东ACM Pick apples
    第三届山东省ACM The Best Seat in ACM Contest
    第三届山东ACM省赛 Pixel density
    第三届山东ACM省赛 n a^o7 !
  • 原文地址:https://www.cnblogs.com/stronghorse/p/16002879.html
Copyright © 2020-2023  润新知