?? 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 + -