📄 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); // 释放内存 GlobalFree(hTableNdx); GlobalFree(hPrefix); GlobalFree(hSuffix); // 退出 return;}/************************************************************************* * * 函数名称: * GIF_LZW_WriteCode() * * 参数: * CFile& file - 要保存的文件 * WORD wCode - 要添加的编码 * LPSTR lpSubBlock - 子块 * LPBYTE lpbyCurrentBits - 当前位数 * LPGIFC_VAR lpGIFCVar - 指向GIFC_VAR结构的指针 * * 返回值: * 无 * * 说明: * 该函数用来输出一个编码。 * *************************************************************************/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;}/************************************************************************* * * 函数名称: * ReadGIF() * * 参数: * CFile& file - 要读取的文件 * * 返回值: * HDIB - 成功返回DIB的句柄,否则返回NULL。 * * 说明: * 该函数将读取指定的GIF文件。将读取的结果保存在一个未压缩 * 编码的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图像控制扩充块 GIFCONTROL GIFC; // GIF图像说明扩充块 GIFPLAINTEXT GIFP; // GIF应用程序扩充块 GIFAPPLICATION GIFA; // GIF编码参数 GIFD_VAR GIFDVar; // 颜色数目 WORD wColors; // 每行字节数 WORD wWidthBytes; // 调色板 BYTE byGIF_Pal[768]; // 16色系统调色板 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大小(字节数) DWORD dwDIB_Size; // 调色板大小(字节数) WORD wPalSize; // 字节变量 BYTE byTemp; // 内存句柄 HANDLE hSrcBuff; HANDLE hTemp; // 内存指针 LPSTR lpTemp; // 字变量 WORD wTemp; // 循环变量 WORD wi; // 标签 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); // 获取调色板的位数 GIFDVar.wBits = (WORD)GIFS.GlobalFlag.PalBits + 1; // 判断是否有全局调色板 if (GIFS.GlobalFlag.GlobalPal) { // 赋初值 memset((LPSTR)byGIF_Pal,0,768); // 全局调色板大小 wPalSize = 3 * (1 << GIFDVar.wBits); // 读取全局调色板 file.Read((LPSTR)byGIF_Pal,wPalSize); } // 读取下一个字节 file.Read((LPSTR)&byTemp,1); // 对每一个描述块循环 while(TRUE) { // 判断是否是图像描述块 if (byTemp == 0x2C) { // 是图像描述块,退出循环 break; } // 判断是否是GIF扩展块 if (byTemp==0x21) { // 是GIF扩展块 // 分配内存 hTemp = GlobalAlloc(GHND,(DWORD)MAX_BUFF_SIZE); // 锁定内存 lpTemp = (LPSTR) GlobalLock(hTemp); // 读取下一个字节 file.Read((LPSTR)&byLabel, 1); // 针对各种扩充块,进行分别处理 switch(byLabel) { case 0xF9: { // 图像控制扩充块 file.Read((LPSTR)&GIFC, 6); // 跳出 break; } case 0x01: { // 图像说明扩充块 file.Read((LPSTR)&GIFP,sizeof(GIFP)); // 读取扩充块大小 file.Read((LPSTR)&byBlockSize,1); // 当byBlockSize > 0时循环读取 while(byBlockSize) { // 读取图像说明扩充块(这里没有进行任何处理) file.Read(lpTemp,byBlockSize); // 读取扩充块大小 file.Read((LPSTR)&byBlockSize,1); } // 跳出 break; } case 0xFE: { // 注释说明扩充块 // 读取扩充块大小 file.Read((LPSTR)&byBlockSize,1); // 当byBlockSize > 0时循环读取 while(byBlockSize) { // 读取注释说明扩充块(这里没有进行任何处理) file.Read(lpTemp,byBlockSize); // 读取扩充块大小 file.Read((LPSTR)&byBlockSize,1); } // 跳出 break; } case 0xFF: { // 应用程序扩充块 file.Read((LPSTR)&GIFA, sizeof(GIFA)); // 读取扩充块大小 file.Read((LPSTR)&byBlockSize,1); // 当byBlockSize > 0时循环读取 while(byBlockSize) { // 读取应用程序扩充块(这里没有进行任何处理) file.Read(lpTemp,byBlockSize); // 读取扩充块大小 file.Read((LPSTR)&byBlockSize,1); } // 跳出 break; } default: { // 忽略未知的扩充块 // 读取扩充块大小 file.Read((LPSTR)&byBlockSize,1); // 当byBlockSize > 0时循环读取 while(byBlockSize) { // 读取未知的扩充块(这里没有进行任何处理) file.Read(lpTemp,byBlockSize); // 读取扩充块大小 file.Read((LPSTR)&byBlockSize,1); } // 跳出 break; } // 释放内存 GlobalUnlock(hTemp); GlobalFree(hTemp); } } // 读取下一个字节 file.Read((LPSTR)&byTemp,1); } // 读取GIF图像描述块 file.Read((LPSTR)&GIFI, 9); // 获取图像宽度 GIFDVar.wWidth = GIFI.wWidth; // 获取图像高度 GIFDVar.wDepth = GIFI.wDepth; // 判断是否有区域调色板 if (GIFI.LocalFlag.LocalPal) { // 赋初值 memset((LPSTR)byGIF_Pal, 0, 768); // 读取区域调色板位数 GIFDVar.wBits = (WORD)GIFI.LocalFlag.PalBits + 1; // 区域调色板大小 wPalSize = 3 * (1 << GIFDVar.wBits); // 读取区域调色板 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); // 每行字节数 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) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIB_Size); if (hDIB == 0) { // 内存分配失败,返回NULL。 return NULL; } // 锁定 pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); /////////////////////////////////////////////////////////////////////////// // 设置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; /////////////////////////////////////////////////////////////////////////// // 设置调色板 // 判断是否指定全局或区域调色板 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 = (LPSTR)GlobalLock(hSrcBuff); // 读取编码数据 ReadSrcData(file,&GIFDVar.wMemLen,&GIFDVar.dwDataLen, GIFDVar.lpDataBuff,&GIFDVar.bEOF); // 缓冲区起始位置 GIFDVar.lpBgnBuff = GIFDVar.lpDataBuff; // 缓冲区中止位置 GIFDVar.lpEndBuff = GIFDVar.lpBgnBuff + GIFDVar.wMemLen; // 计算DIB中像素位置 lpDIBBits = (LPSTR) FindDIBBits(pDIB); // 解码 DecodeGIF_LZW(file, lpDIBBits, &GIFDVar, wWidthBytes); // 释放内存 GlobalUnlock(hSrcBuff); GlobalFree(hSrcBuff); // 返回DIB句柄 return hDIB;}/************************************************************************* * * 函数名称: * ReadSrcData()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -