📄 gifapi.cpp
字号:
*
* 参数:
* CFile& file - 源GIF文件
* LPWORD lpwMemLen - 缓冲区长度(指针)
* LPDWORD lpdwDataLen - 剩余数据长度(指针)
* LPSTR lpSrcBuff - 缓冲区指针
* LPBOOL lpbEOF - 结束标志
*
* 返回值:
* 无
*
* 说明:
* 该函数用来读取指定GIF文件中的图像编码,每次最多读取MAX_BUFF_SIZE
* 字节,是否读完由标志lpbEOF指定。
*
*************************************************************************/
void WINAPI ReadSrcData(CFile& file, LPWORD lpwMemLen, LPDWORD lpdwDataLen,
LPSTR lpSrcBuff, LPBOOL lpbEOF)
{
// 判断数据长度是否仍然大于内存大小
if ((*lpdwDataLen) > (DWORD)(*lpwMemLen))
{
// 数据长度大于内存大小,表示没有解码完
// 数据长度减内存大小
(*lpdwDataLen) -= (DWORD)(*lpwMemLen);
}
else
{
// 数据长度不大于内存大小,表示解码将要完成
// 内存大小就是剩余数据长度
(*lpwMemLen) = (WORD)(*lpdwDataLen);
// EOF标志设置为TRUE
(*lpbEOF) = TRUE;
}
// 读取编码数据
file.Read(lpSrcBuff, (*lpwMemLen));
// 返回
return;
}
/*************************************************************************
*
* 函数名称:
* DecodeGIF_LZW()
*
* 参数:
* CFile& file - 源GIF文件
* LPSTR lpDIBBits - 指向要保存的DIB图像指针
* LPGIFD_VAR lpGIFDVar - 指向GIFC_VAR结构的指针
* WORD wWidthBytes - 每行图像字节数
*
* 返回值:
* 无
*
* 说明:
* 该函数对指定GIF_LZW编码数据进行解码。
*
*************************************************************************/
void WINAPI DecodeGIF_LZW(CFile& file, LPSTR lpDIBBits,
LPGIFD_VAR lpGIFDVar,WORD wWidthBytes)
{
// 指向编码后图像数据的指针
BYTE * lpDst;
// 内存分配句柄
HANDLE hPrefix;
HANDLE hSuffix;
HANDLE hStack;
HANDLE hImage;
// 用于字串表搜索的索引
LPWORD lpwPrefix;
LPBYTE lpbySuffix;
LPBYTE lpbyStack;
LPBYTE lpbyStackBgn;
// 指向图像当前行解码结果的指针
LPSTR lpImageBgn;
// 指向当前编码像素的指针
LPSTR lpImage;
// 计算当前数据图像的偏移量
DWORD dwDataNdx;
// LZW_CLEAR
WORD wLZW_CLEAR;
// LZW_EOI
WORD wLZW_EOI;
// LZW_MinCodeLen
BYTE byLZW_MinCodeLen;
// 字串表索引
WORD wNowTableNdx;
WORD wTopTableNdx;
// 当前图像的行数
WORD wRowNum;
// 计数
WORD wWidthCnt;
WORD wBitCnt;
WORD wRowCnt;
// 循环变量
WORD wi;
// 交错方式存储时每次增加的行数
WORD wIncTable[5] = { 8,8,4,2,0 };
// 交错方式存储时起始行数
WORD wBgnTable[5] = { 0,4,2,1,0 };
// 块大小
BYTE byBlockSize;
// 块索引
BYTE byBlockNdx;
DWORD dwData;
// 当前编码
WORD wCode;
// 上一个编码
WORD wOldCode;
// 临时索引
WORD wTempNdx;
WORD wCodeMask[13] = {0x0000,
0x0001,0x0003,0x0007,0x000F,
0x001F,0x003F,0x007F,0x00FF,
0x01FF,0x03FF,0x07FF,0x0FFF
};
BYTE byLeftBits;
BYTE byFirstChar;
BYTE byCode;
BYTE byCurrentBits;
BYTE byPass;
// 临时字节变量
BYTE byTempChar;
// 给字串表分配内存
hPrefix = GlobalAlloc(GHND,(DWORD)(MAX_TABLE_SIZE<<1));
hSuffix = GlobalAlloc(GHND,(DWORD)MAX_TABLE_SIZE);
hStack = GlobalAlloc(GHND,(DWORD)MAX_TABLE_SIZE);
hImage = GlobalAlloc(GHND,(DWORD)wWidthBytes);
// 锁定内存
lpwPrefix = (LPWORD)GlobalLock(hPrefix);
lpbySuffix = (LPBYTE)GlobalLock(hSuffix);
lpbyStack = (LPBYTE)GlobalLock(hStack);
lpbyStackBgn = lpbyStack;
lpImage = (LPSTR)GlobalLock(hImage);
lpImageBgn = lpImage;
// 读取GIF LZW最小编码大小
byLZW_MinCodeLen = *lpGIFDVar->lpBgnBuff++;
byCurrentBits = byLZW_MinCodeLen + (BYTE)0x01;
// 计算LZW_CLEAR
wLZW_CLEAR = 1 << byLZW_MinCodeLen;
// 计算LZW_EOI
wLZW_EOI = wLZW_CLEAR + 1;
// 计算字串表索引
wNowTableNdx = wLZW_CLEAR + 2;
wTopTableNdx = 1 << byCurrentBits;
// 赋初值
dwData = 0UL;
wBitCnt = lpGIFDVar->wBits;
wRowNum = 0;
wRowCnt = 1;
wWidthCnt = 0;
wCode = 0;
wOldCode = 0xFFFF;
byBlockSize = 0x01;
byBlockNdx = 0x00;
byLeftBits = 0x00;
byTempChar = 0x00;
byPass = 0x00;
// 读取下一个编码
while(byLeftBits < byCurrentBits)
{
// 读取下一个字符
// 判断是否读完一个数据块
if (++byBlockNdx == byBlockSize)
{
// 读取下一个数据块
byBlockSize = *lpGIFDVar->lpBgnBuff++;
byBlockNdx = 0x00;
// 判断是否读完
if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
!lpGIFDVar->bEOF)
{
// 读取下一个数据块
ReadSrcData(file,&lpGIFDVar->wMemLen,
&lpGIFDVar->dwDataLen,
lpGIFDVar->lpDataBuff,&lpGIFDVar->bEOF);
// 指针重新赋值
lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff + lpGIFDVar->wMemLen;
}
}
// 下一个字符
byCode = *lpGIFDVar->lpBgnBuff++;
// 移位
dwData |= ((DWORD)byCode << byLeftBits);
byLeftBits += 0x08;
// 判断是否读完
if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
!lpGIFDVar->bEOF)
{
// 读取下一个数据块
ReadSrcData(file,&lpGIFDVar->wMemLen,
&lpGIFDVar->dwDataLen,
lpGIFDVar->lpDataBuff,&lpGIFDVar->bEOF);
// 指针重新赋值
lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff + lpGIFDVar->wMemLen;
}
}
wCode = (WORD)dwData & wCodeMask[byCurrentBits];
dwData >>= byCurrentBits;
byLeftBits -= byCurrentBits;
// 解码
while(wCode != wLZW_EOI)
{
// 当前编码不是LZW_EOI码
// 判断是否是LZW_CLEAR码
if (wCode == wLZW_CLEAR)
{
// 是LZW_CLEAR,清除字串表
// 重新初始化字串表
for(wi = 0; wi < wLZW_CLEAR; wi++)
{
*(lpwPrefix + wi) = 0xFFFF;
*(lpbySuffix + wi) = (BYTE)wi;
}
for(wi = wNowTableNdx; wi < MAX_TABLE_SIZE; wi++)
{
*(lpwPrefix+wi) = 0xFFFF;
*(lpbySuffix+wi) = 0x00;
}
byCurrentBits = byLZW_MinCodeLen + (BYTE)0x01;
wNowTableNdx = wLZW_CLEAR + 2;
wTopTableNdx = 1 << byCurrentBits;
wOldCode = 0xFFFF;
// 获取下一个编码
while(byLeftBits < byCurrentBits)
{
// 读取下一个字符
// 判断是否读完一个数据块
if (++byBlockNdx == byBlockSize)
{
// 读取下一个数据块
byBlockSize = *lpGIFDVar->lpBgnBuff++;
byBlockNdx = 0x00;
// 判断是否读完
if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
!lpGIFDVar->bEOF)
{
// 读取下一个数据块
ReadSrcData(file, &lpGIFDVar->wMemLen,
&lpGIFDVar->dwDataLen,
lpGIFDVar->lpDataBuff,
&lpGIFDVar->bEOF);
// 指针重新赋值
lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff +
lpGIFDVar->wMemLen;
}
}
byCode = *lpGIFDVar->lpBgnBuff++;
dwData |= ((DWORD)byCode << byLeftBits);
byLeftBits += 0x08;
// 判断是否读完
if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
!lpGIFDVar->bEOF)
{
// 读取下一个数据块
ReadSrcData(file,&lpGIFDVar->wMemLen,
&lpGIFDVar->dwDataLen,
lpGIFDVar->lpDataBuff,&lpGIFDVar->bEOF);
// 指针重新赋值
lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff + lpGIFDVar->wMemLen;
}
}
wCode = (WORD)dwData & wCodeMask[byCurrentBits];
dwData >>= byCurrentBits;
byLeftBits -= byCurrentBits;
// 判断编码是否为LZW_EOI
if (wCode!=wLZW_EOI)
{
// 这里没有用到lpbyStack[0]
lpbyStack ++;
// 将数据压入堆栈
while((*(lpwPrefix+wCode)) != 0xFFFF)
{
*lpbyStack++ = *(lpbySuffix+wCode);
wCode = *(lpwPrefix+wCode);
}
*lpbyStack = *(lpbySuffix+wCode);
byFirstChar = *lpbyStack;
// 输出数据
while(lpbyStack>lpbyStackBgn)
{
byTempChar |= (*lpbyStack-- << (8-wBitCnt));
if (wBitCnt==8)
{
*lpImage++ = byTempChar;
byTempChar = 0x00;
wBitCnt = lpGIFDVar->wBits;
}
else
{
wBitCnt += lpGIFDVar->wBits;
}
wWidthCnt ++;
if (wWidthCnt==lpGIFDVar->wWidth)
{
if (wBitCnt!=lpGIFDVar->wBits)
{
*lpImage = byTempChar;
byTempChar = 0x00;
wBitCnt = lpGIFDVar->wBits;
}
// 图像当前行偏移量
dwDataNdx = (DWORD)(lpGIFDVar->wDepth - 1 - wRowNum) * (DWORD)wWidthBytes;
// 图像当前行起始位置
lpDst = (BYTE *)lpDIBBits + dwDataNdx;
// 赋值
memcpy(lpDst, lpImageBgn, wWidthBytes);
lpImage = lpImageBgn;
// 判断是否按照交错方式保存
if (lpGIFDVar->bInterlace)
{
// 交错方式
// 计算下一行的行号
wRowNum += wIncTable[byPass];
if (wRowNum >= lpGIFDVar->wDepth)
{
byPass ++;
wRowNum = wBgnTable[byPass];
}
}
else
{
// 非交错方式,行号直接加1
wRowNum ++;
}
wWidthCnt = 0;
}
}
}
}
else
{
// 这里没有用到lpbyStack[0]
lpbyStack ++;
// 判断字符串是否在字串表中
if (wCode < wNowTableNdx)
{
// 不在字串表中
wTempNdx = wCode;
}
else
{
// 在字串表中
wTempNdx = wOldCode;
*lpbyStack++ = byFirstChar;
}
// 将数据压入堆栈
while((*(lpwPrefix+wTempNdx)) != 0xFFFF)
{
*lpbyStack++ = *(lpbySuffix+wTempNdx);
wTempNdx = *(lpwPrefix+wTempNdx);
}
*lpbyStack = *(lpbySuffix+wTempNdx);
byFirstChar = *lpbyStack;
// 将字符串添加到字串表中
*(lpwPrefix+wNowTableNdx) = wOldCode;
*(lpbySuffix+wNowTableNdx) = byFirstChar;
if (++wNowTableNdx==wTopTableNdx && byCurrentBits<12)
{
byCurrentBits ++;
wTopTableNdx = 1 << byCurrentBits;
}
// 输出数据
while(lpbyStack>lpbyStackBgn)
{
byTempChar |= (*lpbyStack-- << (8-wBitCnt));
if (wBitCnt==8)
{
*lpImage++ = byTempChar;
byTempChar = 0x00;
wBitCnt = lpGIFDVar->wBits;
}
else
{
wBitCnt += lpGIFDVar->wBits;
}
wWidthCnt ++;
if (wWidthCnt==lpGIFDVar->wWidth)
{
if (wBitCnt!=lpGIFDVar->wBits)
{
*lpImage = byTempChar;
byTempChar = 0x00;
wBitCnt = lpGIFDVar->wBits;
}
// 图像当前行偏移量
dwDataNdx = (DWORD)(lpGIFDVar->wDepth - 1 - wRowNum) * (DWORD)wWidthBytes;
// 图像当前行起始位置
lpDst = (BYTE *)lpDIBBits + dwDataNdx;
// 赋值
memcpy(lpDst, lpImageBgn, wWidthBytes);
lpImage = lpImageBgn;
// 判断是否按照交错方式保存
if (lpGIFDVar->bInterlace)
{
// 交错方式
// 计算下一行的行号
wRowNum += wIncTable[byPass];
if (wRowNum >= lpGIFDVar->wDepth)
{
byPass ++;
wRowNum = wBgnTable[byPass];
}
}
else
{
// 非交错方式,行号直接加1
wRowNum ++;
}
wWidthCnt = 0;
}
}
}
wOldCode = wCode;
// 读取下一个编码
while(byLeftBits < byCurrentBits)
{
// 读取下一个字符
// 判断是否读完一个数据块
if (++byBlockNdx == byBlockSize)
{
// 读取下一个数据块
byBlockSize = *lpGIFDVar->lpBgnBuff++;
byBlockNdx = 0x00;
// 判断是否读完
if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
!lpGIFDVar->bEOF)
{
// 读取下一个数据块
ReadSrcData(file,&lpGIFDVar->wMemLen,
&lpGIFDVar->dwDataLen,
lpGIFDVar->lpDataBuff,&lpGIFDVar->bEOF);
// 指针重新赋值
lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff + lpGIFDVar->wMemLen;
}
}
byCode = *lpGIFDVar->lpBgnBuff++;
dwData |= ((DWORD)byCode << byLeftBits);
byLeftBits += 0x08;
// 判断是否读完
if ((lpGIFDVar->lpBgnBuff == lpGIFDVar->lpEndBuff) &&
!lpGIFDVar->bEOF)
{
// 读取下一个数据块
ReadSrcData(file,&lpGIFDVar->wMemLen,
&lpGIFDVar->dwDataLen,
lpGIFDVar->lpDataBuff,&lpGIFDVar->bEOF);
// 指针重新赋值
lpGIFDVar->lpBgnBuff = lpGIFDVar->lpDataBuff;
lpGIFDVar->lpEndBuff = lpGIFDVar->lpBgnBuff + lpGIFDVar->wMemLen;
}
}
wCode = (WORD)dwData & wCodeMask[byCurrentBits];
dwData >>= byCurrentBits;
byLeftBits -= byCurrentBits;
}
// 释放内存
GlobalUnlock(hPrefix);
GlobalUnlock(hSuffix);
GlobalUnlock(hStack);
GlobalFree(hPrefix);
GlobalFree(hSuffix);
GlobalFree(hStack);
// 返回
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -