?? gifapi.cpp
字號:
if (lpGIFCVar->wBlockNdx > 1) { // 判斷wByteCnt + 256是否超過MAX_BUFF_SIZE if ((lpGIFCVar->wByteCnt + 256) >= MAX_BUFF_SIZE) { // 輸出 file.Write(lpGIFCVar->lpDataBuff, lpGIFCVar->wByteCnt); lpGIFCVar->lpEndBuff = lpGIFCVar->lpDataBuff; lpGIFCVar->wByteCnt = 0; } bySubBlock[0] = (BYTE)(lpGIFCVar->wBlockNdx - 1); memcpy(lpGIFCVar->lpEndBuff,(LPSTR)bySubBlock,lpGIFCVar->wBlockNdx); lpGIFCVar->lpEndBuff += lpGIFCVar->wBlockNdx; lpGIFCVar->wByteCnt += lpGIFCVar->wBlockNdx; lpGIFCVar->wBlockNdx = 1; } // 解除鎖定 GlobalUnlock(hTableNdx); GlobalUnlock(hPrefix); GlobalUnlock(hSuffix); // 釋放內(nèi)存 GlobalFree(hTableNdx); GlobalFree(hPrefix); GlobalFree(hSuffix); // 退出 return;}/************************************************************************* * * 函數(shù)名稱: * GIF_LZW_WriteCode() * * 參數(shù): * CFile& file - 要保存的文件 * WORD wCode - 要添加的編碼 * LPSTR lpSubBlock - 子塊 * LPBYTE lpbyCurrentBits - 當(dāng)前位數(shù) * LPGIFC_VAR lpGIFCVar - 指向GIFC_VAR結(jié)構(gòu)的指針 * * 返回值: * 無 * * 說明: * 該函數(shù)用來輸出一個編碼。 * *************************************************************************/void WINAPI GIF_LZW_WriteCode(CFile& file, WORD wCode, LPSTR lpSubBlock, LPBYTE lpbyCurrentBits,LPGIFC_VAR lpGIFCVar){ // 輸出該編碼 lpGIFCVar->dwTempCode |= ((DWORD)wCode << lpGIFCVar->byLeftBits); lpGIFCVar->byLeftBits += (*lpbyCurrentBits); while(lpGIFCVar->byLeftBits >= 0x08) { lpSubBlock[lpGIFCVar->wBlockNdx++] = (BYTE)lpGIFCVar->dwTempCode; // 判斷是否超出MAX_SUBBLOCK_SIZE if (lpGIFCVar->wBlockNdx > MAX_SUBBLOCK_SIZE) { // 判斷wByteCnt + 256是否超過MAX_BUFF_SIZE if ((lpGIFCVar->wByteCnt + 256) >= MAX_BUFF_SIZE) { // 輸出 file.Write(lpGIFCVar->lpDataBuff, lpGIFCVar->wByteCnt); lpGIFCVar->lpEndBuff = lpGIFCVar->lpDataBuff; lpGIFCVar->wByteCnt = 0; } lpSubBlock[0] = (BYTE)(lpGIFCVar->wBlockNdx - 1); memcpy(lpGIFCVar->lpEndBuff,lpSubBlock,lpGIFCVar->wBlockNdx); lpGIFCVar->lpEndBuff += lpGIFCVar->wBlockNdx; lpGIFCVar->wByteCnt += lpGIFCVar->wBlockNdx; lpGIFCVar->wBlockNdx = 1; } lpGIFCVar->dwTempCode >>= 8; lpGIFCVar->byLeftBits -= 0x08; } // 返回 return;}/************************************************************************* * * 函數(shù)名稱: * ReadGIF() * * 參數(shù): * CFile& file - 要讀取的文件 * * 返回值: * HDIB - 成功返回DIB的句柄,否則返回NULL。 * * 說明: * 該函數(shù)將讀取指定的GIF文件。將讀取的結(jié)果保存在一個未壓縮 * 編碼的DIB對象中。 * *************************************************************************/HDIB WINAPI ReadGIF(CFile& file){ // DIB句柄 HDIB hDIB; // DIB指針 LPSTR pDIB; // 指向DIB像素的指針 LPSTR lpDIBBits; // 指向BITMAPINFOHEADER的指針 LPBITMAPINFOHEADER lpBIH; // 指向BITMAPINFO的指針 LPBITMAPINFO lpBI; // GIF文件頭 GIFHEADER GIFH; // GIF邏輯屏幕描述塊 GIFSCRDESC GIFS; // GIF圖像描述塊 GIFIMAGE GIFI; // GIF圖像控制擴(kuò)充塊 GIFCONTROL GIFC; // GIF圖像說明擴(kuò)充塊 GIFPLAINTEXT GIFP; // GIF應(yīng)用程序擴(kuò)充塊 GIFAPPLICATION GIFA; // GIF編碼參數(shù) GIFD_VAR GIFDVar; // 顏色數(shù)目 WORD wColors; // 每行字節(jié)數(shù) WORD wWidthBytes; // 調(diào)色板 BYTE byGIF_Pal[768]; // 16色系統(tǒng)調(diào)色板 BYTE bySysPal16[48] = { 0, 0, 0, 0, 0, 128, 0, 128, 0, 0, 128, 128, 128, 0, 0, 128, 0, 128, 128, 128, 0, 128, 128, 128, 192, 192, 192, 0, 0, 255, 0, 255, 0, 0, 255, 255, 255, 0, 0, 255, 0, 255, 255, 255, 0, 255, 255, 255 }; // DIB大小(字節(jié)數(shù)) DWORD dwDIB_Size; // 調(diào)色板大小(字節(jié)數(shù)) WORD wPalSize; // 字節(jié)變量 BYTE byTemp; // 內(nèi)存句柄 HANDLE hSrcBuff; HANDLE hTemp; // 內(nèi)存指針 LPSTR lpTemp; // 字變量 WORD wTemp; // 循環(huán)變量 WORD wi; // 標(biāo)簽 BYTE byLabel; // 塊大小 BYTE byBlockSize; // 讀取GIF文件頭 file.Read((LPSTR)&GIFH, sizeof(GIFH)); // 判斷是否是GIF文件 if (memicmp((LPSTR)GIFH.bySignature,"GIF",3) != 0) { // 非GIF文件,返回NULL return NULL; } // 判斷版本號是否正確 if ((memicmp((LPSTR)GIFH.byVersion,"87a",3) != 0) && (memicmp((LPSTR)GIFH.byVersion,"89a",3) != 0)) { // 不支持該版本,返回NULL return NULL; } // 讀取GIF邏輯屏幕描述塊 file.Read((LPSTR)&GIFS, 7); // 獲取調(diào)色板的位數(shù) GIFDVar.wBits = (WORD)GIFS.GlobalFlag.PalBits + 1; // 判斷是否有全局調(diào)色板 if (GIFS.GlobalFlag.GlobalPal) { // 賦初值 memset((LPSTR)byGIF_Pal,0,768); // 全局調(diào)色板大小 wPalSize = 3 * (1 << GIFDVar.wBits); // 讀取全局調(diào)色板 file.Read((LPSTR)byGIF_Pal,wPalSize); } // 讀取下一個字節(jié) file.Read((LPSTR)&byTemp,1); // 對每一個描述塊循環(huán) while(TRUE) { // 判斷是否是圖像描述塊 if (byTemp == 0x2C) { // 是圖像描述塊,退出循環(huán) break; } // 判斷是否是GIF擴(kuò)展塊 if (byTemp==0x21) { // 是GIF擴(kuò)展塊 // 分配內(nèi)存 hTemp = GlobalAlloc(GHND,(DWORD)MAX_BUFF_SIZE); // 鎖定內(nèi)存 lpTemp = (LPSTR) GlobalLock(hTemp); // 讀取下一個字節(jié) file.Read((LPSTR)&byLabel, 1); // 針對各種擴(kuò)充塊,進(jìn)行分別處理 switch(byLabel) { case 0xF9: { // 圖像控制擴(kuò)充塊 file.Read((LPSTR)&GIFC, 6); // 跳出 break; } case 0x01: { // 圖像說明擴(kuò)充塊 file.Read((LPSTR)&GIFP,sizeof(GIFP)); // 讀取擴(kuò)充塊大小 file.Read((LPSTR)&byBlockSize,1); // 當(dāng)byBlockSize > 0時(shí)循環(huán)讀取 while(byBlockSize) { // 讀取圖像說明擴(kuò)充塊(這里沒有進(jìn)行任何處理) file.Read(lpTemp,byBlockSize); // 讀取擴(kuò)充塊大小 file.Read((LPSTR)&byBlockSize,1); } // 跳出 break; } case 0xFE: { // 注釋說明擴(kuò)充塊 // 讀取擴(kuò)充塊大小 file.Read((LPSTR)&byBlockSize,1); // 當(dāng)byBlockSize > 0時(shí)循環(huán)讀取 while(byBlockSize) { // 讀取注釋說明擴(kuò)充塊(這里沒有進(jìn)行任何處理) file.Read(lpTemp,byBlockSize); // 讀取擴(kuò)充塊大小 file.Read((LPSTR)&byBlockSize,1); } // 跳出 break; } case 0xFF: { // 應(yīng)用程序擴(kuò)充塊 file.Read((LPSTR)&GIFA, sizeof(GIFA)); // 讀取擴(kuò)充塊大小 file.Read((LPSTR)&byBlockSize,1); // 當(dāng)byBlockSize > 0時(shí)循環(huán)讀取 while(byBlockSize) { // 讀取應(yīng)用程序擴(kuò)充塊(這里沒有進(jìn)行任何處理) file.Read(lpTemp,byBlockSize); // 讀取擴(kuò)充塊大小 file.Read((LPSTR)&byBlockSize,1); } // 跳出 break; } default: { // 忽略未知的擴(kuò)充塊 // 讀取擴(kuò)充塊大小 file.Read((LPSTR)&byBlockSize,1); // 當(dāng)byBlockSize > 0時(shí)循環(huán)讀取 while(byBlockSize) { // 讀取未知的擴(kuò)充塊(這里沒有進(jìn)行任何處理) file.Read(lpTemp,byBlockSize); // 讀取擴(kuò)充塊大小 file.Read((LPSTR)&byBlockSize,1); } // 跳出 break; } // 釋放內(nèi)存 GlobalUnlock(hTemp); GlobalFree(hTemp); } } // 讀取下一個字節(jié) file.Read((LPSTR)&byTemp,1); } // 讀取GIF圖像描述塊 file.Read((LPSTR)&GIFI, 9); // 獲取圖像寬度 GIFDVar.wWidth = GIFI.wWidth; // 獲取圖像高度 GIFDVar.wDepth = GIFI.wDepth; // 判斷是否有區(qū)域調(diào)色板 if (GIFI.LocalFlag.LocalPal) { // 賦初值 memset((LPSTR)byGIF_Pal, 0, 768); // 讀取區(qū)域調(diào)色板位數(shù) GIFDVar.wBits = (WORD)GIFI.LocalFlag.PalBits + 1; // 區(qū)域調(diào)色板大小 wPalSize = 3 * (1 << GIFDVar.wBits); // 讀取區(qū)域調(diào)色板 file.Read((LPSTR)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); // 每行字節(jié)數(shù) wWidthBytes = (WORD)DWORD_WBYTES((DWORD)GIFDVar.wWidth * (DWORD)GIFDVar.wBits); // 顏色數(shù)目 wColors = 1 << GIFDVar.wBits; // 調(diào)色板大小 wPalSize = wColors * sizeof(RGBQUAD); // 計(jì)算DIB長度(字節(jié)) dwDIB_Size = sizeof(BITMAPINFOHEADER) + wPalSize + GIFDVar.wDepth * wWidthBytes; // 為DIB分配內(nèi)存 hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIB_Size); if (hDIB == 0) { // 內(nèi)存分配失敗,返回NULL。 return NULL; } // 鎖定 pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); /////////////////////////////////////////////////////////////////////////// // 設(shè)置BITMAPINFOHEADER // 賦值 lpBIH = (LPBITMAPINFOHEADER) pDIB; 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; /////////////////////////////////////////////////////////////////////////// // 設(shè)置調(diào)色板 // 判斷是否指定全局或區(qū)域調(diào)色板 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 { // 沒有指定全局和區(qū)域調(diào)色板,采用系統(tǒng)調(diào)色板 // 按照顏色數(shù)目來分別給調(diào)色板賦值 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; } } } /////////////////////////////////////////////////////////////////////////// // 解碼 // 獲取編碼數(shù)據(jù)長度 GIFDVar.dwDataLen = (DWORD) (file.GetLength() - file.GetPosition()); // 計(jì)算內(nèi)存大小(最大不超過MAX_BUFF_SIZE) GIFDVar.wMemLen = ((GIFDVar.dwDataLen > (DWORD)MAX_BUFF_SIZE) ? (WORD)MAX_BUFF_SIZE : (WORD)GIFDVar.dwDataLen); // 分配內(nèi)存 hSrcBuff = GlobalAlloc(GHND, (DWORD)GIFDVar.wMemLen); // 鎖定內(nèi)存 GIFDVar.lpDataBuff = (LPSTR)GlobalLock(hSrcBuff); // 讀取編碼數(shù)據(jù) ReadSrcData(file,&GIFDVar.wMemLen,&GIFDVar.dwDataLen, GIFDVar.lpDataBuff,&GIFDVar.bEOF); // 緩沖區(qū)起始位置 GIFDVar.lpBgnBuff = GIFDVar.lpDataBuff; // 緩沖區(qū)中止位置 GIFDVar.lpEndBuff = GIFDVar.lpBgnBuff + GIFDVar.wMemLen; // 計(jì)算DIB中像素位置 lpDIBBits = (LPSTR) FindDIBBits(pDIB); // 解碼 DecodeGIF_LZW(file, lpDIBBits, &GIFDVar, wWidthBytes); // 釋放內(nèi)存 GlobalUnlock(hSrcBuff); GlobalFree(hSrcBuff); // 返回DIB句柄 return hDIB;}/************************************************************************* * * 函數(shù)名稱: * ReadSrcData()
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -