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

📄 coding.cpp

📁 各种数据压缩和解压的源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// ************************************************************************
//  文件名:Coding.cpp
//
//  图像编码压缩、解压缩函数库:
//
//	LoadJPG()			- 装载JPEG图象(解压用)
//	SaveJPG()			- 保存JPEG图象(压缩用)
//	SaveBMP()			- 保存BMP图象到文件(解压用)
//	LoadBMP()			- 从文件装载BMP图象(压缩用)
//  DIBToPCX()			- 将DIB保存为PCX文件
//  PCXToDIB()			- 读取PCX文件
//	Huffman()			- 哈夫曼编码
//	Shannon_Fannon()	- 仙农-弗诺编码
//	DIBToGIF()			- 将DIB保存到GIF文件
//	LZW_Encode()		- 对图象进行LZW编码
//	OutputCode()		- 为GIF-LZW算法输出一个编码
//	GIFToDIB()			- 读取GIF到DIB
//	LZW_Decode()		- 对LZW编码进行解码
//	ReadGIF()			- 读取指定GIF文件中的图像编码
//
//*************************************************************************

#include "stdafx.h"
#include "Data_Compress_System.h"
#include "Coding.h"
#include "JPEGfile.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//	Dib文件头标志(字符串"BM",写DIB时用到该常数)
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')

/////////////////////////////////////////////////////////////////////////////
// CCoding

CCoding::CCoding()
{
}

CCoding::~CCoding()
{
}


BEGIN_MESSAGE_MAP(CCoding, CWnd)
	//{{AFX_MSG_MAP(CCoding)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CCoding message handlers

/*************************************************************************
 *
 * 函数名称:
 *   SaveJPG()
 *
 * 参数:
 *   CData_Compress_SystemDoc* pDoc	- 文档指针
 *	 CString fileName		- 保存文件路径
 *
 * 返回值:
 *   void			    - 无返回值
 *
 * 说明:
 *   该函数对图象进行JPEG编码压缩
 *
 ************************************************************************/

void CCoding::SaveJPG(CData_Compress_SystemDoc* pDoc, CString fileName)
{
	// 临时缓存
	BYTE *buf;
	buf = NULL;

	// 
	CSize size = pDoc->GetDocSize();
	UINT width = size.cx;
	UINT height = size.cy;

	buf = LoadBMP(pDoc->m_strCurrentFile, &width, &height);

	// 压缩位图到JPEG文件,函数的最后参数标明压缩质量(1 - 100)
	JpegFile::RGBToJpegFile(fileName, buf, width, height, TRUE, 80);
}
/*************************************************************************
 *
 * 函数名称:
 *   SaveJPG()
 *
 * 参数:
 *   CData_Compress_SystemDoc* pDoc	- 文档指针
 *	 CString fileName		- 保存文件路径
 *    int quality           -质量参数
 *
 * 返回值:
 *   void			    - 无返回值
 *
 * 说明:
 *   该函数对图象进行JPEG编码压缩
 *
 ************************************************************************/
void CCoding::SaveJPG(CData_Compress_SystemDoc* pDoc, CString fileName,int quality)
{
		// 临时缓存
	BYTE *buf;
	buf = NULL;

	// 
	CSize size = pDoc->GetDocSize();
	UINT width = size.cx;
	UINT height = size.cy;

	buf = LoadBMP(pDoc->m_strCurrentFile, &width, &height);

	// 压缩位图到JPEG文件,函数的最后参数标明压缩质量(1 - 100)
	JpegFile::RGBToJpegFile(fileName, buf, width, height, TRUE, quality);

}

/*************************************************************************
 *
 * 函数名称:
 *   SavePC()
 *
 * 参数:
 *   HDIB hDIB				- DIB句柄
 *   CString strPath	    - 要保存的文件路径
 *
 * 返回值:
 *   BOOL               - 成功返回True,否则返回False。
 *
 * 说明:
 *   该函数将指定的图象保存为PC文件。
 *
 *************************************************************************/
BOOL CCoding::SavePC(HDIB hDIB, CString strPath)
{
		// 循环变量
	LONG	i;
	LONG	j;
	LONG	k;
	// 参与预测的象素和当前编码的象素
	BYTE	bCharA;
	BYTE	bCharB;
	BYTE	bCharC;
	BYTE	bCharD;
	// 预测值
	BYTE		nTemp;	
	// 预测后的残差
	BYTE	nDpcm;

	// 中间变量
	BYTE	bChar1;
	BYTE	bChar2;
	
	// 指向源图像象素的指针
	unsigned char*	lpSrc;
	unsigned char* A;
		unsigned char* B;
	// 指向编码后图像数据的指针
//	BYTE*	lpDst;
	
	// 重复像素计数
	int		iCount;
	
	// 调整顺序:B、G、R
	int	RGB[3] = {2, 1, 0};

	// 打开文件
	CFile file;
	file.Open(strPath, CFile::modeCreate | CFile::modeReadWrite);
	
	// 缓冲区已使用的字节数
	DWORD	dwBuffUsed;
	
	// 指向DIB的指针
	LPBYTE lpDIB;
	
	// 指向DIB象素指针
	LPBYTE lpDIBBits;
	
	// 锁定DIB
	lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);

	// 找到DIB图像象素起始位置
	lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
	
	// 判断是否是8-bpp位图
	if (m_clsDIB.DIBBitCount(lpDIB) != 8)
	{
		// 提示用户
		MessageBox("请先将其转换为8位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 返回
		return FALSE;
	}
	
	// 更改光标形状
	BeginWaitCursor();
	
	// DIB的宽度
	LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
	
	// DIB的高度
	LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
	
	// 计算图像每行的字节数
	LONG lLineBytes = WIDTHBYTES(lWidth * 8);
	
	//*************************************************************************
	/**********************************************************************
	*写入PC文件头信息
	***********************************************************************
	*/
	PCHEADER pcheader;

	// 给文件头赋值
	pcheader.bManufacturer = 0x0A;
	pcheader.bVersion = 5;
	pcheader.bEncoding = 1;	
	// 像素位数(24位色为8位)
	pcheader.bBpp = 8;	
	// 图像相对于屏幕的左上角X坐标(以像素为单位)
	pcheader.wLeft = 0;	
	// 图像相对于屏幕的左上角Y坐标(以像素为单位)
	pcheader.wTop = 0;	
	// 图像相对于屏幕的右下角X坐标(以像素为单位)
	pcheader.wRight = lWidth - 1;	
	// 图像相对于屏幕的右下角Y坐标(以像素为单位)
	pcheader.wBottom = lHeight - 1;		
	// 图像的水平分辨率
	pcheader.wXResolution = (WORD)lWidth;	
	// 图像的垂直分辨率
	pcheader.wYResolution = (WORD)lHeight;
	// 保留域,设定为0。
	pcheader.bReserved = 0;	
	// 图像色彩平面数目
	pcheader.bPlanes = 3;	
	// 图像的宽度(字节为单位),必须为偶数。
	pcheader.wLineBytes = (WORD)lWidth;	
	// 图像调色板的类型,1表示彩色或者单色图像,2表示图像是灰度图。
	pcheader.wPaletteType = 1;	
	// 制作该图像的屏幕宽度(像素为单位)
	pcheader.wSrcWidth = 0;	
	// 制作该图像的屏幕高度(像素为单位)
	pcheader.wSrcDepth = 0;	
	// 保留域,取值设定为0。
	for (i = 0; i < 54; i ++)
	{
		pcheader.bFiller[i] = 0;
	}
	
	// 写入文件头
	file.Write((LPBYTE)&pcheader, sizeof(PCHEADER));
	
	//*******************************************************************************
	// 开始编码
	// 编码第0行
	i = 0;

	for ( j = 0; j < lWidth; j++)
	{
		// 指向图象0行j列象素的指针
		lpSrc = (BYTE *)lpDIBBits + lLineBytes * (lHeight - 1 - i) +j ;
		
		// 给bCharD赋值
		bCharD = (BYTE)*lpSrc;
		// 如果是第0行0列,直接将象素值写入
		if(j == 0)
		{
			nDpcm = bCharD;
		}
		// 利用 Dpcm =D - A 计算残差 
		else
		{
			bCharA = *(lpSrc - 1);
			nDpcm  = bCharD - bCharA;
		}
		// 将残差写入文件
		file.Write(&nDpcm , sizeof(BYTE));
	}



	// 编码第1行到lHeight-1行
	for ( i=1;i<lHeight; i++)
	{
		for ( j = 0; j < lWidth; j++)
		{
			// 指向当前编码元素的指针
			lpSrc = (BYTE *)lpDIBBits + j + lLineBytes * (lHeight - 1 - i);
		
			// 赋值
			bCharD = *lpSrc;
			bCharB = *(lpSrc + lLineBytes);

			// 如果是第一列,利用 残差=D -B 进行预测
			if(j == 0)
				nDpcm = bCharD - bCharB;
			else
			{
				// 利用(B-C)/2+A计算预测值
				bCharA = *(lpSrc - 1);
				bCharC = *(lpSrc + lLineBytes - 1);
				nTemp  = (BYTE)((bCharB-bCharC) / 2 + bCharA);
				
				// 如果预测值小于0,直接赋零
				if(nTemp < 0)
					nTemp = 0;
				// 如果预测值大于255,直接赋值255
				else if(nTemp > 255)
					nTemp = 255;
				else
					nTemp = nTemp;

				// 得到残差
				nDpcm = bCharD - nTemp;
			}

			// 将残差写入文件
			file.Write(&nDpcm , sizeof(BYTE));
		}
	}

	
	// 释放内存
	//delete[] lpDst;
	
	// 关闭文件
	file.Close();

	// 更改光标形状
	EndWaitCursor();

	// 返回
	return TRUE;
}
/*************************************************************************
 *
 * 函数名称:
 *   LoadJPG()
 *
 * 参数:
 *   HDIB hDIB				- DIB句柄
 *   CData_Compress_SystemDoc* pDoc	- 文档指针
 *	 CString fileName		- 装载文件路径
 *
 * 返回值:
 *   void			    - 无返回值
 *
 * 说明:
 *   该函数对图象进行JPEG编码解压缩
 *
 ************************************************************************/

void CCoding::LoadJPG(HDIB hDIB, CData_Compress_SystemDoc* pDoc, CString fileName)
{
	// 临时缓存
	BYTE *buf;
	buf = NULL;

	// JPEG图象高度、宽度
	UINT width = 0;
	UINT height = 0;

	// 读到临时缓存
	buf = JpegFile::JpegFileToRGB(fileName, &width, &height);

	// 交换红绿象素
	JpegFile::BGRFromRGB(buf, width, height);

	// 垂直翻转显示
	JpegFile::VertFlipBuf(buf, width * 3, height);

	// 保存解压后的数据到临时位图文件
	SaveBMP("Temp.bmp", buf, width, height);

	// 装载临时位图文件
	pDoc->OnOpenDocument("Temp.bmp");

	// 删除临时文件
	::DeleteFile("Temp.bmp");

	// 初始化标记为FALSE
	pDoc->SetModifiedFlag(TRUE);
}


/*************************************************************************
 *
 * 函数名称:
 *   SaveBMP()
 *
 * 参数:
 *	 CString fileName		- 保存文件路径
 *	 BYTE* buf				- BGR缓存
 *	 UINT width				- 宽度
 *	 UINT height			- 高度
 *
 * 返回值:
 *   void			    - 无返回值
 *
 * 说明:
 *   该函数把BMP图象从内存保存到文件
 *
 ************************************************************************/

void CCoding::SaveBMP(CString fileName,	BYTE * buf,	UINT width,	UINT height)
{
	// 位图文件头
	char m1 = 'B';
	char m2 = 'M';
	short res1 = 0;
    short res2 = 0;
    long pixoff = 54;

	// 宽度
	DWORD widthDW = WIDTHBYTES(width * 24);

	// 文件长度
	long bmfsize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + widthDW * height;	
	
	// 文件指针
	long byteswritten = 0;

	// 位图信息头
	BITMAPINFOHEADER header;
  	header.biSize = 40; 		   		    // 头大小
	header.biWidth = width;
	header.biHeight = height;
	header.biPlanes = 1;
	header.biBitCount = 24;					// 24位
	header.biCompression = BI_RGB;			// 非压缩
	header.biSizeImage = 0;
	header.biXPelsPerMeter = 0;
	header.biYPelsPerMeter = 0;
	header.biClrUsed = 0;
	header.biClrImportant = 0;

	// 二进制写方式打开文件
	FILE *fp;	
	fp = fopen(fileName, "wb");

	// 写文件头
	fwrite((BYTE*)&(m1), 1, 1, fp); 
	byteswritten += 1;
	fwrite((BYTE*)&(m2), 1, 1, fp); 
	byteswritten += 1;
	fwrite((long*)&(bmfsize), 4, 1, fp);
	byteswritten += 4;
	fwrite((int*)&(res1), 2, 1, fp);
	byteswritten += 2;
	fwrite((int*)&(res2), 2, 1, fp);
	byteswritten += 2;
	fwrite((long*)&(pixoff), 4, 1, fp);
	byteswritten += 4;

	// 写位图信息头
	fwrite((BITMAPINFOHEADER *)&header, sizeof(BITMAPINFOHEADER), 1, fp);
	
	// 移动指针
	byteswritten += sizeof(BITMAPINFOHEADER);
	
	// 临时变量
	long row = 0;
	long rowidx;
	long row_size;
    long rc;

	// 行大小
	row_size = header.biWidth * 3;
	
	// 保存位图阵列
	for (row = 0; row < header.biHeight; row++)
	{
		rowidx = (long unsigned)row * row_size;						      

		// 写一行
		rc = fwrite((void *)(buf + rowidx), row_size, 1, fp);
		if (rc != 1) 
			break;
		byteswritten += row_size;	

		for (DWORD count = row_size; count < widthDW; count++) 
		{
			char dummy = 0;
			fwrite(&dummy, 1, 1, fp);
			byteswritten++;							  
		}
	}

	// 关闭文件
	fclose(fp);
}


/*************************************************************************
 *
 * 函数名称:
 *   LoadBMP()
 *
 * 参数:
 *	 CString fileName		- 装载路径
 *	 UINT width				- 宽度
 *	 UINT height			- 高度
 *
 * 返回值:
 *   BYTE*					- 读取图象缓存首地址
 *
 * 说明:
 *   该函数把BMP图象从文件装载到内存
 *
 ************************************************************************/

BYTE* CCoding::LoadBMP(CString fileName, UINT *width, UINT *height)
{
	BITMAP inBM;
	BYTE m1,m2;
    long filesize;
    short res1,res2;
    long pixoff;
    long bmisize;                    
    long compression;
    unsigned long sizeimage;
    long xscale, yscale;
    long colors;
    long impcol;
    
	// 初始化
	BYTE *outBuf = NULL;
	*width = 0;
	*height = 0;
	DWORD m_bytesRead = 0;

	// 以二进制读方式打开文件
	FILE *fp;
	fp = fopen(fileName, "rb");
	
	// 读取文件
	if (fp != NULL)
	{
		// 检验BMP标志
	    long rc;
		rc = fread((BYTE*)&(m1), 1, 1,fp);
		m_bytesRead += 1;
		if (rc == -1) 
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((BYTE*)&(m2), 1, 1,fp);
		m_bytesRead += 1;
		if ((m1!='B') || (m2!='M')) 
		{
			fclose(fp);
			return NULL;
        }
        
		// 读文件头信息
		rc = fread((long*)&(filesize), 4, 1, fp); 
		m_bytesRead += 4;

		if (rc != 1)
		{
			fclose(fp); 
			return NULL;
		}

		rc = fread((int*)&(res1), 2, 1, fp); 
		m_bytesRead += 2;

		if (rc != 1) 
		{
			fclose(fp); 
			return NULL;
		}

⌨️ 快捷键说明

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