📄 coding.cpp
字号:
{
// 赋初值
memset((LPBYTE)byGIF_Pal,0,768);
// 全局调色板大小
wPalSize = 3 * (1 << GIFDVar.wBits);
// 读取全局调色板
file.Read((LPBYTE)byGIF_Pal,wPalSize);
}
// 读取下一个字节
file.Read((LPBYTE)&byTemp,1);
// 对每一个描述块循环
while(TRUE)
{
// 判断是否是图像描述块
if (byTemp == 0x2C)
{
// 是图像描述块,退出循环
break;
}
// 判断是否是GIF扩展块
if (byTemp==0x21)
{
// 是GIF扩展块
// 分配内存
hTemp = GlobalAlloc(GHND, (DWORD)MAX_BUFF_SIZE);
// 锁定内存
lpTemp = (LPBYTE) GlobalLock(hTemp);
// 读取下一个字节
file.Read((LPBYTE)&byLabel, 1);
// 针对各种扩充块,进行分别处理
switch(byLabel)
{
case 0xF9:
{
// 图像控制扩充块
file.Read((LPBYTE)&GIFC, 6);
// 跳出
break;
}
case 0x01:
{
// 图像说明扩充块
file.Read((LPBYTE)&GIFP, sizeof(GIFP));
// 读取扩充块大小
file.Read((LPBYTE)&byBlockSize, 1);
// 当byBlockSize > 0时循环读取
while(byBlockSize)
{
// 读取图像说明扩充块(这里没有进行任何处理)
file.Read(lpTemp, byBlockSize);
// 读取扩充块大小
file.Read((LPBYTE)&byBlockSize, 1);
}
// 跳出
break;
}
case 0xFE:
{
// 注释说明扩充块
// 读取扩充块大小
file.Read((LPBYTE)&byBlockSize, 1);
// 当byBlockSize > 0时循环读取
while(byBlockSize)
{
// 读取注释说明扩充块(这里没有进行任何处理)
file.Read(lpTemp, byBlockSize);
// 读取扩充块大小
file.Read((LPBYTE)&byBlockSize, 1);
}
// 跳出
break;
}
case 0xFF:
{
// 应用程序扩充块
file.Read((LPBYTE)&GIFA, sizeof(GIFA));
// 读取扩充块大小
file.Read((LPBYTE)&byBlockSize, 1);
// 当byBlockSize > 0时循环读取
while(byBlockSize)
{
// 读取应用程序扩充块(这里没有进行任何处理)
file.Read(lpTemp, byBlockSize);
// 读取扩充块大小
file.Read((LPBYTE)&byBlockSize, 1);
}
// 跳出
break;
}
default:
{
// 忽略未知的扩充块
// 读取扩充块大小
file.Read((LPBYTE)&byBlockSize, 1);
// 当byBlockSize > 0时循环读取
while(byBlockSize)
{
// 读取未知的扩充块(这里没有进行任何处理)
file.Read(lpTemp, byBlockSize);
// 读取扩充块大小
file.Read((LPBYTE)&byBlockSize, 1);
}
// 跳出
break;
}
// 释放内存
GlobalUnlock(hTemp);
GlobalFree(hTemp);
}
}
// 读取下一个字节
file.Read((LPBYTE)&byTemp, 1);
}
// 读取GIF图像描述块
file.Read((LPBYTE)&GIFI, 9);
// 获取图像宽度
GIFDVar.wWidth = GIFI.wWidth;
// 获取图像高度
GIFDVar.wDepth = GIFI.wDepth;
// 判断是否有区域调色板
if (GIFI.LocalFlag.LocalPal)
{
// 赋初值
memset((LPBYTE)byGIF_Pal, 0, 768);
// 读取区域调色板位数
GIFDVar.wBits = (WORD)GIFI.LocalFlag.PalBits + 1;
// 区域调色板大小
wPalSize = 3 * (1 << GIFDVar.wBits);
// 读取区域调色板
file.Read((LPBYTE)byGIF_Pal,wPalSize);
}
// 给GIFDVar成员赋值
GIFDVar.wBits = ((GIFDVar.wBits==1) ? 1 : (GIFDVar.wBits<=4) ? 4 : 8);
GIFDVar.wLineBytes = (WORD)BYTE_WBYTES((DWORD)GIFDVar.wWidth * (DWORD)GIFDVar.wBits);
GIFDVar.bEOF = FALSE;
// 交错方式
GIFDVar.bInterlace = (GIFI.LocalFlag.Interlace ? TRUE : FALSE);
// 每行字节数
wWidthBytes = (WORD)DWORD_WBYTES((DWORD)GIFDVar.wWidth * (DWORD)GIFDVar.wBits);
// 颜色数目
wColors = 1 << GIFDVar.wBits;
// 调色板大小
wPalSize = wColors * sizeof(RGBQUAD);
// 计算DIB长度(字节)
dwDIB_Size = sizeof(BITMAPINFOHEADER) + wPalSize + GIFDVar.wDepth * wWidthBytes;
// 为DIB分配内存
HDIB hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIB_Size);
if (hDIB == 0)
{
// 内存分配失败,返回NULL。
return NULL;
}
// 锁定
LPBYTE pDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);
///////////////////////////////////////////////////////////////////////////
// 设置BITMAPINFOHEADER
// 指向BITMAPINFOHEADER的指针
LPBITMAPINFOHEADER lpBIH = (LPBITMAPINFOHEADER) pDIB;
// 指向BITMAPINFO的指针
LPBITMAPINFO lpBI = (LPBITMAPINFO) pDIB;
// 给lpBIH成员赋值
lpBIH->biSize = (DWORD)sizeof(BITMAPINFOHEADER);
lpBIH->biWidth = (DWORD)GIFDVar.wWidth;
lpBIH->biHeight = (DWORD)GIFDVar.wDepth;
lpBIH->biPlanes = 1;
lpBIH->biBitCount = GIFDVar.wBits;
lpBIH->biCompression = BI_RGB;
lpBIH->biSizeImage = (DWORD)wWidthBytes * GIFDVar.wDepth;
lpBIH->biXPelsPerMeter = 0;
lpBIH->biYPelsPerMeter = 0;
lpBIH->biClrUsed = wColors;
lpBIH->biClrImportant = 0;
///////////////////////////////////////////////////////////////////////////
// 设置调色板
// 判断是否指定全局或区域调色板
if (GIFS.GlobalFlag.GlobalPal || GIFI.LocalFlag.LocalPal)
{
wTemp = 0;
for(wi=0; wi<wColors; wi++)
{
lpBI->bmiColors[wi].rgbRed = byGIF_Pal[wTemp++];
lpBI->bmiColors[wi].rgbGreen = byGIF_Pal[wTemp++];
lpBI->bmiColors[wi].rgbBlue = byGIF_Pal[wTemp++];
lpBI->bmiColors[wi].rgbReserved = 0x00;
}
}
else
{
// 没有指定全局和区域调色板,采用系统调色板
// 按照颜色数目来分别给调色板赋值
switch(wColors)
{
case 2:
{
// 单色位图
lpBI->bmiColors[0].rgbRed = 0x00;
lpBI->bmiColors[0].rgbGreen = 0x00;
lpBI->bmiColors[0].rgbBlue = 0x00;
lpBI->bmiColors[0].rgbReserved = 0x00;
lpBI->bmiColors[1].rgbRed = 0xFF;
lpBI->bmiColors[1].rgbGreen = 0xFF;
lpBI->bmiColors[1].rgbBlue = 0xFF;
lpBI->bmiColors[1].rgbReserved = 0x00;
// 跳出
break;
}
case 16:
{
// 16色位图
wTemp = 0;
for(wi=0;wi<wColors;wi++)
{
lpBI->bmiColors[wi].rgbRed = bySysPal16[wTemp++];
lpBI->bmiColors[wi].rgbGreen = bySysPal16[wTemp++];
lpBI->bmiColors[wi].rgbBlue = bySysPal16[wTemp++];
lpBI->bmiColors[wi].rgbReserved = 0x00;
}
// 跳出
break;
}
case 256:
{
// 256色位图
for(wi=0; wi<wColors; wi++)
{
lpBI->bmiColors[wi].rgbRed = (BYTE)wi;
lpBI->bmiColors[wi].rgbGreen = (BYTE)wi;
lpBI->bmiColors[wi].rgbBlue = (BYTE)wi;
lpBI->bmiColors[wi].rgbReserved = 0x00;
}
// 跳出
break;
}
}
}
///////////////////////////////////////////////////////////////////////////
// 解码
// 获取编码数据长度
GIFDVar.dwDataLen = (DWORD) (file.GetLength() - file.GetPosition());
// 计算内存大小(最大不超过MAX_BUFF_SIZE)
GIFDVar.wMemLen = ((GIFDVar.dwDataLen > (DWORD)MAX_BUFF_SIZE) ?
(WORD)MAX_BUFF_SIZE : (WORD)GIFDVar.dwDataLen);
// 分配内存
hSrcBuff = GlobalAlloc(GHND, (DWORD)GIFDVar.wMemLen);
// 锁定内存
GIFDVar.lpDataBuff = (LPBYTE)GlobalLock(hSrcBuff);
// 读取编码数据
ReadGIF(file, &GIFDVar.wMemLen, &GIFDVar.dwDataLen, GIFDVar.lpDataBuff, &GIFDVar.bEOF);
// 缓冲区起始位置
GIFDVar.lpBgnBuff = GIFDVar.lpDataBuff;
// 缓冲区中止位置
GIFDVar.lpEndBuff = GIFDVar.lpBgnBuff + GIFDVar.wMemLen;
// 计算DIB中像素位置
LPBYTE lpDIBBits = m_clsDIB.FindDIBBits(pDIB);
// 解码
LZW_Decode(file, lpDIBBits, &GIFDVar, wWidthBytes);
// 释放内存
GlobalUnlock(hSrcBuff);
GlobalFree(hSrcBuff);
// 返回DIB句柄
return hDIB;
}
/*************************************************************************
*
* 函数名称:
* ReadGIF()
*
* 参数:
* CFile& file - 源GIF文件
* LPWORD lpwMemLen - 缓冲区长度(指针)
* LPDWORD lpdwDataLen - 剩余数据长度(指针)
* LPBYTE lpSrcBuff - 缓冲区指针
* LPBOOL lpbEOF - 结束标志
*
* 返回值:
* 无
*
* 说明:
* 该函数用来读取指定GIF文件中的图像编码
*
*************************************************************************/
void CCoding::ReadGIF(CFile &file, LPWORD lpwMemLen, LPDWORD lpdwDataLen, LPBYTE lpSrcBuf, LPBOOL lpbEOF)
{
// 根据数据长度是否仍然大于内存大小来判断解码是否将要完成
if ((*lpdwDataLen) > (DWORD)(*lpwMemLen))
(*lpdwDataLen) -= (DWORD)(*lpwMemLen);
else
{
// 内存大小就是剩余数据长度
(*lpwMemLen) = (WORD)(*lpdwDataLen);
// EOF标志设置为TRUE,解码完成
(*lpbEOF) = TRUE;
}
// 读取编码数据
file.Read(lpSrcBuf, (*lpwMemLen));
// 返回
return;
}
/*************************************************************************
*
* 函数名称:
* LZW_Decode()
*
* 参数:
* CFile& file - 源GIF文件
* LPBYTE lpDIBBits - 指向要保存的DIB图像指针
* LPGIFD_VAR lpGIFDVar - 指向GIFC_VAR结构的指针
* WORD wWidthBytes - 每行图像字节数
*
* 返回值:
* 无
*
* 说明:
* 该函数对LZW编码进行解码。
*
*************************************************************************/
void CCoding::LZW_Decode(CFile &file, LPBYTE lpDIBBits, LPGIFD_VAR lpGIFDVar, WORD wWidthBytes)
{
// 指向编码后图像数据的指针
BYTE * lpDst;
// 内存分配句柄
HANDLE hPrefix;
HANDLE hSuffix;
HANDLE hStack;
HANDLE hImage;
// 用于字串表搜索的索引
LPWORD lpwPrefix;
LPBYTE lpbySuffix;
LPBYTE lpbyStack;
LPBYTE lpbyStackBgn;
// 指向图像当前行解码结果的指针
LPBYTE lpImageBgn;
// 指向当前编码像素的指针
LPBYTE 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 = (LPBYTE)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)
{
// 读取下一个数据块
ReadGIF(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)
{
// 读取下一个数据块
ReadGIF(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_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -