⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gifapi.cpp

📁 vc++数字图像处理 ,是一本很不错的介绍数字图像方面的书籍,这里有本书的全部源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// ************************************************************************//  文件名:GIFAPI.cpp////  GIF(Graphics Interchange Format) API函数库:////  DIBToGIF()          - 将指定的DIB对象(< 256色)保存为GIF文件//  EncodeGIF_LZW()		- 对指定图像进行GIF_LZW编码//  GIF_LZW_WriteCode() - 输出一个编码//  ReadGIF()           - 读取GIF文件//  DecodeGIF_LZW()     - 对GIF_LZW编码结果进行解码//  ReadSrcData()       - 读取GIF_LZW编码//// ************************************************************************#include "stdafx.h"#include "DIBAPI.h"#include "GIFAPI.h"#include <io.h>#include <errno.h>#include <math.h>#include <direct.h>/************************************************************************* * * 函数名称: *   DIBToGIF() * * 参数: *   LPSTR lpDIB        - 指向DIB对象的指针 *   CFile& file        - 要保存的文件 *   BOOL	bInterlace	- 是否按照交错方式保存 * * 返回值: *   BOOL               - 成功返回True,否则返回False。 * * 说明: *   该函数将指定的DIB对象(< 256色)保存为GIF文件。 * *************************************************************************/BOOL WINAPI DIBToGIF(LPSTR lpDIB, CFile& file, BOOL bInterlace){	// 循环变量	WORD	i;	WORD	j;		// DIB高度	WORD	wHeight;		// DIB宽度	WORD	wWidth;		// 指向DIB象素指针	LPSTR   lpDIBBits;		// GIF文件头	GIFHEADER          GIFH;		// GIF逻辑屏幕描述块	GIFSCRDESC         GIFS;		// GIF图像描述块	GIFIMAGE           GIFI;		// GIF编码参数	GIFC_VAR           GIFCVar;		// 颜色数目	WORD               wColors;		// 每行字节数	WORD               wWidthBytes;		// 调色板	BYTE               byGIF_Pal[768];		// 字节变量	BYTE               byChar;		// 指向BITMAPINFO结构的指针(Win3.0)	LPBITMAPINFO	   lpbmi;		// 指向BITMAPCOREINFO结构的指针	LPBITMAPCOREINFO   lpbmc;		// 表明是否是Win3.0 DIB的标记	BOOL			   bWinStyleDIB;		// 获取DIB高度	wHeight = (WORD) DIBHeight(lpDIB);		// 获取DIB宽度	wWidth  = (WORD) DIBWidth(lpDIB);		// 找到DIB图像象素起始位置	lpDIBBits = FindDIBBits(lpDIB);		// 给GIFCVar结构赋值	GIFCVar.wWidth     = wWidth;	GIFCVar.wDepth     = wHeight;	GIFCVar.wBits      = DIBBitCount(lpDIB);	GIFCVar.wLineBytes = (WORD)BYTE_WBYTES((DWORD)GIFCVar.wWidth *										   (DWORD)GIFCVar.wBits);		// 计算每行字节数	wWidthBytes = (WORD)DWORD_WBYTES(wWidth * (DWORD)GIFCVar.wBits);		// 计算颜色数目	wColors     = 1 << GIFCVar.wBits;		// 获取指向BITMAPINFO结构的指针(Win3.0)	lpbmi = (LPBITMAPINFO)lpDIB;		// 获取指向BITMAPCOREINFO结构的指针	lpbmc = (LPBITMAPCOREINFO)lpDIB;		// 判断是否是WIN3.0的DIB	bWinStyleDIB = IS_WIN30_DIB(lpDIB);		// 给调色板赋值	if (bWinStyleDIB)	{		j = 0;		for (i = 0; i < wColors; i++)		{			// 读取红色分量			byGIF_Pal[j++] = lpbmi->bmiColors[i].rgbRed;						// 读取绿色分量			byGIF_Pal[j++] = lpbmi->bmiColors[i].rgbGreen;						// 读取蓝色分量			byGIF_Pal[j++] = lpbmi->bmiColors[i].rgbBlue;		}	}	else	{		j = 0;		for (i = 0; i < wColors; i++)		{			// 读取红色分量			byGIF_Pal[j++] = lpbmc->bmciColors[i].rgbtRed;						// 读取绿色分量			byGIF_Pal[j++] = lpbmc->bmciColors[i].rgbtGreen;						// 读取红色分量			byGIF_Pal[j++] = lpbmc->bmciColors[i].rgbtBlue;		}	}		////////////////////////////////////////////////////////////////////////////////////////	// 开始写GIF文件		// 写GIF文件头	GIFH.bySignature[0] = 'G';	GIFH.bySignature[1] = 'I';	GIFH.bySignature[2] = 'F';	GIFH.byVersion[0]='8';	GIFH.byVersion[1]='9';	GIFH.byVersion[2]='a';	file.Write((LPSTR)&GIFH, 6);		// 写GIF逻辑屏幕描述块	GIFS.wWidth               = GIFCVar.wWidth;	GIFS.wDepth               = GIFCVar.wDepth;	GIFS.GlobalFlag.PalBits   = (BYTE)(GIFCVar.wBits - 1);	GIFS.GlobalFlag.SortFlag  = 0x00;	GIFS.GlobalFlag.ColorRes  = (BYTE)(GIFCVar.wBits - 1);	GIFS.GlobalFlag.GlobalPal = 0x01;	GIFS.byBackground         = 0x00;	GIFS.byAspect             = 0x00;	file.Write((LPSTR)&GIFS, 7);		// 写GIF全局调色板	file.Write((LPSTR)byGIF_Pal,(wColors*3));		// 写GIF图像描述间隔符	byChar      = 0x2C;	file.Write((LPSTR)&byChar,1);		// 写GIF图像描述块	GIFI.wLeft                = 0;	GIFI.wTop                 = 0;	GIFI.wWidth               = GIFCVar.wWidth;	GIFI.wDepth               = GIFCVar.wDepth;	GIFI.LocalFlag.PalBits    = 0x00;	GIFI.LocalFlag.Reserved   = 0x00;	GIFI.LocalFlag.SortFlag   = 0x00;	GIFI.LocalFlag.Interlace  = (BYTE)(bInterlace ? 0x01 : 0x00);	GIFI.LocalFlag.LocalPal   = 0x00;	file.Write((LPSTR)&GIFI, 9);		// 写GIF图像压缩数据	HANDLE hSrcBuff = GlobalAlloc(GHND,(DWORD)MAX_BUFF_SIZE);	GIFCVar.lpDataBuff = (LPSTR)GlobalLock(hSrcBuff);	GIFCVar.lpEndBuff  = GIFCVar.lpDataBuff;	GIFCVar.dwTempCode = 0UL;	GIFCVar.wByteCnt   = 0;	GIFCVar.wBlockNdx  = 1;	GIFCVar.byLeftBits = 0x00;		// 进行GIF_LZW编码	EncodeGIF_LZW(lpDIBBits, file, &GIFCVar,wWidthBytes, bInterlace);		// 判断是否编码成功	if (GIFCVar.wByteCnt)	{		// 写入文件		file.Write(GIFCVar.lpDataBuff, GIFCVar.wByteCnt);	}		// 释放内存	GlobalUnlock(hSrcBuff);	GlobalFree(hSrcBuff);		// 写GIF Block Terminator	byChar   = 0x00;	file.Write((LPSTR)&byChar,1);		// 写GIF文件结尾块	byChar   = 0x3B;	file.Write((LPSTR)&byChar,1);		// 返回	return TRUE;}/************************************************************************* * * 函数名称: *   EncodeGIF_LZW() * * 参数: *   LPSTR lpDIBBits		- 指向源DIB图像指针 *   CFile& file			- 要保存的文件 *   LPGIFC_VAR lpGIFCVar	- 指向GIFC_VAR结构的指针 *	 WORD wWidthBytes		- 每行图像字节数 *	 BOOL bInterlace		- 是否按照交错方式保存 * * 返回值: *   无 * * 说明: *   该函数对指定图像进行GIF_LZW编码。 * *************************************************************************/void WINAPI EncodeGIF_LZW(LPSTR lpDIBBits, CFile& file, 						  LPGIFC_VAR lpGIFCVar,WORD wWidthBytes, BOOL bInterlace){	// 内存分配句柄	HANDLE hTableNdx;	HANDLE hPrefix;	HANDLE hSuffix;		// 指向字串表指针	LPWORD lpwTableNdx;		// 用于字串表搜索的索引	LPWORD lpwPrefix;	LPBYTE lpbySuffix;		// 指向当前编码像素的指针	LPSTR  lpImage;		// 计算当前数据图像的偏移量	DWORD  dwDataNdx;		// LZW_CLEAR	WORD   wLZW_CLEAR;		// LZW_EOI	WORD   wLZW_EOI;		// LZW_MinCodeLen	BYTE   byLZW_MinCodeLen;		// 字串表索引	WORD   wPreTableNdx;	WORD   wNowTableNdx;	WORD   wTopTableNdx;		// 哈希表索引	WORD   wHashNdx;	WORD   wHashGap;	WORD   wPrefix;	WORD   wShiftBits;		// 当前图像的行数	WORD   wRowNum;		WORD   wWidthCnt;		// 循环变量	WORD   wi;	WORD   wj;		// 交错方式存储时每次增加的行数	WORD   wIncTable[5]  = { 8,8,4,2,0 }; 		// 交错方式存储时起始行数	WORD   wBgnTable[5]  = { 0,4,2,1,0 }; 		BOOL   bStart;	BYTE   bySuffix;	BYTE   bySubBlock[256];	BYTE   byCurrentBits;	BYTE   byMask;	BYTE   byChar;	BYTE   byPass;		// 临时字节变量	BYTE   byTemp;		// 给字串表分配内存	hTableNdx        = GlobalAlloc(GHND,(DWORD)(MAX_HASH_SIZE<<1));	hPrefix          = GlobalAlloc(GHND,(DWORD)(MAX_HASH_SIZE<<1));	hSuffix          = GlobalAlloc(GHND,(DWORD)MAX_HASH_SIZE);		// 锁定内存	lpwTableNdx      = (LPWORD)GlobalLock(hTableNdx);	lpwPrefix        = (LPWORD)GlobalLock(hPrefix);	lpbySuffix       = (LPBYTE)GlobalLock(hSuffix);		// 计算LZW_MinCodeLen	byLZW_MinCodeLen = (BYTE)((lpGIFCVar->wBits>1) ? lpGIFCVar->wBits : 0x02);		// 写GIF LZW最小代码大小	file.Write((LPSTR)&byLZW_MinCodeLen,1);		wRowNum          = 0;	bStart           = TRUE;	byPass           = 0x00;		// 计算LZW_CLEAR	wLZW_CLEAR       = 1 << byLZW_MinCodeLen;		// 计算LZW_EOI	wLZW_EOI         = wLZW_CLEAR + 1;		// 初始化字串表	byCurrentBits    = byLZW_MinCodeLen + (BYTE)0x01;	wNowTableNdx     = wLZW_CLEAR + 2;	wTopTableNdx     = 1 << byCurrentBits;	for(wi=0; wi<MAX_HASH_SIZE; wi++)	{		// 初始化为0xFFFF		*(lpwTableNdx+wi) = 0xFFFF;	}		// 输出LZW_CLEAR	GIF_LZW_WriteCode(file, wLZW_CLEAR, (LPSTR)bySubBlock,					  &byCurrentBits, lpGIFCVar);		// 逐行编码	for(wi=0; wi<lpGIFCVar->wDepth; wi++)	{		// 计算当前偏移量		dwDataNdx  = (DWORD)(lpGIFCVar->wDepth - 1 - wRowNum) * (DWORD)wWidthBytes;				// 指向当前行图像的指针		lpImage    = (LPSTR) (((BYTE*)lpDIBBits) + dwDataNdx);				wWidthCnt  = 0;		wShiftBits = 8 - lpGIFCVar->wBits;		byMask     = (BYTE)((lpGIFCVar->wBits==1) ? 0x80 : 0xF0);				if (bStart)		{			// 判断是否是256色位图(一个像素一字节)			if (lpGIFCVar->wBits==8)			{				// 256色,直接赋值即可				byTemp      = *lpImage++;			}			else			{				// 非256色,需要移位获取像素值				wShiftBits  = 8 - lpGIFCVar->wBits;				byMask      = (BYTE)((lpGIFCVar->wBits==1) ? 0x80 : 0xF0);				byTemp      = (BYTE)((*lpImage & byMask) >> wShiftBits);				byMask    >>= lpGIFCVar->wBits;				wShiftBits -= lpGIFCVar->wBits;			}			wPrefix    = (WORD)byTemp;			bStart     = FALSE;			wWidthCnt ++;		}				// 每行编码		while(wWidthCnt < lpGIFCVar->wWidth)		{			// 判断是否是256色位图(一个像素一字节)			if (lpGIFCVar->wBits==8)			{				// 256色,直接赋值即可				byTemp = *lpImage++;			}			else			{				// 非256色,需要移位获取像素值				byChar = *lpImage;				byTemp = (BYTE)((byChar & byMask) >> wShiftBits);				if (wShiftBits)				{					byMask    >>= lpGIFCVar->wBits;					wShiftBits -= lpGIFCVar->wBits;				}				else				{					wShiftBits  = 8 - lpGIFCVar->wBits;					byMask      = (BYTE)((lpGIFCVar->wBits==1) ? 0x80 : 0xF0);					lpImage    ++;				}			}			bySuffix   = byTemp;			wWidthCnt ++;						// 查找当前字符串是否存在于字串表中			wHashNdx = wPrefix ^ ((WORD)bySuffix << 4);			wHashGap = (wHashNdx ? (MAX_HASH_SIZE - wHashNdx) : 1);						// 判断当前字符串是否在字串表中			while(TRUE)			{				// 当前字符串不在字串表中				if (*(lpwTableNdx + wHashNdx) == 0xFFFF)				{				   // 新字符串,退出循环				   break;				}								// 判断是否找到该字符串				if ((*(lpwPrefix+wHashNdx)  == wPrefix) &&					(*(lpbySuffix+wHashNdx) == bySuffix))				{					// 找到,退出循环					break;				}								// 第二哈希表				if (wHashNdx < wHashGap)				{					wHashNdx += MAX_HASH_SIZE;				}				wHashNdx -= wHashGap;			}						// 判断是否是新字符串			if (*(lpwTableNdx+wHashNdx) != 0xFFFF)			{				// 不是新字符串				wPrefix = *(lpwTableNdx + wHashNdx);			 }			 else			 {				// 新字符串								// 输出该编码				GIF_LZW_WriteCode(file,wPrefix,(LPSTR)bySubBlock,								   &byCurrentBits,lpGIFCVar);								// 将该新字符串添加到字串表中				wPreTableNdx = wNowTableNdx;								// 判断是否达到最大字串表大小				if (wNowTableNdx < MAX_TABLE_SIZE)				{					*(lpwTableNdx+wHashNdx) = wNowTableNdx++;					*(lpwPrefix+wHashNdx)   = wPrefix;					*(lpbySuffix+wHashNdx)  = bySuffix;				}								if (wPreTableNdx == wTopTableNdx)				{					if (byCurrentBits<12)					{						byCurrentBits ++;						wTopTableNdx <<= 1;					}					else					{						// 字串表到达最大长度												// 输出LZW_CLEAR						GIF_LZW_WriteCode(file, wLZW_CLEAR, (LPSTR)bySubBlock,										 &byCurrentBits,lpGIFCVar);												// 重新初始化字串表						byCurrentBits    = byLZW_MinCodeLen + (BYTE)0x01;						wLZW_CLEAR       = 1 << byLZW_MinCodeLen;						wLZW_EOI         = wLZW_CLEAR + 1;						wNowTableNdx     = wLZW_CLEAR + 2;						wTopTableNdx     = 1 << byCurrentBits;						for(wj=0;wj<MAX_HASH_SIZE;wj++)						{							// 初始化为0xFFFF							*(lpwTableNdx+wj) = 0xFFFF;						}					}				}				wPrefix = (WORD)bySuffix;			}		}				// 判断是否是交错方式		if (bInterlace)		{			// 交错方式,计算下一行位置			wRowNum += wIncTable[byPass];			if (wRowNum>=lpGIFCVar->wDepth)			{				byPass ++;				wRowNum = wBgnTable[byPass];			}		}		else		{			// 非交错方式,直接将行数加一即可			wRowNum ++;		}	}		// 输出当前编码	GIF_LZW_WriteCode(file, wPrefix, (LPSTR)bySubBlock,					  &byCurrentBits,lpGIFCVar);		// 输出LZW_EOI	GIF_LZW_WriteCode(file,wLZW_EOI,(LPSTR)bySubBlock,					  &byCurrentBits,lpGIFCVar);		if (lpGIFCVar->byLeftBits)	{		// 加入该字符		bySubBlock[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;			}			bySubBlock[0]           = (BYTE)(lpGIFCVar->wBlockNdx - 1);			memcpy(lpGIFCVar->lpEndBuff,(LPSTR)bySubBlock,lpGIFCVar->wBlockNdx);			lpGIFCVar->lpEndBuff   += lpGIFCVar->wBlockNdx;			lpGIFCVar->wByteCnt    += lpGIFCVar->wBlockNdx;			lpGIFCVar->wBlockNdx    = 1;		}		lpGIFCVar->dwTempCode = 0UL;		lpGIFCVar->byLeftBits = 0x00;	}	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -