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