一种二值图象无损压缩算法 南京理工大学电光学院 【摘 要】利用稀疏矩阵和差分编码对二色图像进行压缩保存

源代码在线查看: j.cpp

软件大小: 7645 K
上传用户: xhaibo
关键词: 图象 图像 无损压缩 大学
下载地址: 免注册下载 普通下载 VIP

相关代码

				/********************************************************************
				
					Created:	2006/12/09 12:32
					FileName: 	J.cpp
					Author:		Jar 包杰
					
					Purpose:	将24位BMP二色图像文件压缩
					
					  Copyright By Jar 2006.12
				*********************************************************************/
				#include "stdafx.h"
				#include "J.h"
				
				// 声明串行化过程
				IMPLEMENT_SERIAL(CJ, CObject, 0);
				
				CJ::CJ() 
				{
					JFileName = "";
					m_pBMFH = NULL;
					m_pBMIH = NULL;
					m_pBits = NULL;
					m_pJFH = NULL;
				}
				
				CJ::~CJ()
				{
					if (m_pBMFH != NULL)
					{
						delete m_pBMFH;
						m_pBMFH = NULL;
					}
					if (m_pBMIH != NULL)
					{
						delete m_pBMIH;
						m_pBMIH = NULL;
					}
					if(m_pBits != NULL)
					{
						m_pBits = NULL;
					}
					if(m_pJFH != NULL)
					{
						m_pJFH = NULL;
					}
				}
				
				/*************************************************
				Function:		BMPRead
				Description:	读取BMP图像
				Input:			CFile *pFile
				Output:         
				Return:			BOOL 成功返回TRUE,否则返回FALSE
				Others:			读取BMP文件头、信息头和图像数据
								创建J文件头
				*************************************************/
				BOOL CJ::BMPRead(CFile *pFile)
				{
					int nSize = sizeof(BITMAPFILEHEADER);
					m_pBMFH = (LPBITMAPFILEHEADER) new BYTE[nSize];
				
					//创建J文件头
					nSize = sizeof(JFILEHEADER);
					m_pJFH = (LPJFILEHEADER) new BYTE[nSize];
				
					//读取文件头
					pFile->Read(m_pBMFH, sizeof(BITMAPFILEHEADER));
					// 判断是否是BMP格式的位图
					if(m_pBMFH->bfType != BMP_HEADER_MARKER)
						return FALSE;
				
					nSize = sizeof(BITMAPINFOHEADER);
					m_pBMIH = (LPBITMAPINFOHEADER) new BYTE[nSize];
				
					//生成.J文件名
					JFileName=pFile->GetFileName()+".j";
				
					//读取信息头
					pFile->Read(m_pBMIH, sizeof(BITMAPINFOHEADER));
					//非24位图像打开失败
					if (m_pBMIH->biBitCount != 24)
						return FALSE;
				
					//读取图象数据
					m_pBits = (LPBYTE) new BYTE[m_pBMIH->biSizeImage];
					pFile->Read(m_pBits, m_pBMIH->biSizeImage);
				
					return TRUE;
				}
				
				/*************************************************
				Function:		JWrite
				Description:	压缩BMP图像
				Input:			*pDC
				Output:         
				Return:			BOOL 成功返回TRUE,否则返回FALSE
				Others:			第一次扫描将BMP图像转换成二值矩阵,只含'0''1'
								第二次扫描,求跳变点的坐标差分值,写入文件
									注意:差分值类型为WORD,最大为65536,故需要判断差分大小
									但一般的图像不会造成这种情况
									也可以通过二维求差分压缩法来解决,具体见论文
								第三次扫描,显示图像
				*************************************************/
				BOOL CJ::JWrite(CDC *pDC)
				{
					int i = 0,j = 0,k = 0;
					int nSize = m_pBMIH->biHeight * m_pBMIH->biWidth;
					LPBYTE DivMatrix;
					DivMatrix = new BYTE[nSize];	//二值矩阵
					WORD FirstDis = 0;	//定义第一次出现颜色跳变的偏移量
					LPBYTE BitsH = m_pBits;
					LPBYTE DivMatrixH = DivMatrix;	//标记数据区开始,防止刷新时越界
					CString s;
				
					//写入.J文件头
					m_pJFH->JType = J_HEADER_MARKER;
					m_pJFH->JHeight = (WORD)m_pBMIH->biHeight;
					m_pJFH->JWidth = (WORD)m_pBMIH->biWidth;
					for (i = 0;i < 3;i++)	//读取第一种颜色值
						m_pJFH->FirstColor[i] = *(m_pBits+2-i);
				
					//第一次扫描,转换成二值矩阵
					for (i = 0;i < m_pBMIH->biHeight;i++)
					{
						for (j = 0;j < m_pBMIH->biWidth;j++)
						{
							BYTE tmpColor[3];	//临时存放颜色量
							for (k = 0;k < 3;k++)
								tmpColor[k] = *m_pBits++;
							if ((tmpColor[0] != m_pJFH->FirstColor[2])
								||(tmpColor[1] != m_pJFH->FirstColor[1])
								||(tmpColor[2] != m_pJFH->FirstColor[0]))
							{
								for (k = 0;k									m_pJFH->OpposeColor[k] = tmpColor[2-k];
								*DivMatrix++ = 1;
							}
							else *DivMatrix++ = 0;
						}
						m_pBits = m_pBits + m_pBMIH->biWidth%4;
					}
					m_pBits = BitsH;
					DivMatrix = DivMatrixH;		//指针复位
				
					//记录第一次颜色跳变的位置
					do{
						FirstDis++;
						DivMatrix++;
					}while (*DivMatrix != *(DivMatrix-1));
				
					//创建文件,写入文件头信息
					CFile JFile;
					JFile.Open(JFileName,CFile::modeCreate|CFile::modeReadWrite);
					JFile.Write(m_pJFH,sizeof(JFILEHEADER));
					JFile.Write(&FirstDis,sizeof(WORD));
					pDC->TextOut(0,0,"Completed ");
				
					WORD tmpDis = FirstDis;	//临时存放跳变点之间距离
					BYTE tmpDivMatrix;		//临时存放二值矩阵
					//第二次扫描,记录跳变位置的差值,写入文件
					for (i = FirstDis;i < nSize;i++)
					{
						tmpDivMatrix = *DivMatrix++;
						if (*DivMatrix != tmpDivMatrix)
						{
							WORD Dis = i - tmpDis;
							JFile.Write(&Dis,sizeof(WORD));
							tmpDis = i;
						}
						s.Format("%d %%",i*100/nSize);	//显示进度
						pDC->TextOut(75,0,s);
					}
				
					JFile.Close();
				
					//第三次扫描,显示图像
					s.Format("Compressed to %s",JFileName);
					pDC->TextOut(0,0,s);
					s.Format("Height = %d pix",m_pJFH->JHeight);
					pDC->TextOut(0,20,s);
					s.Format("Width = %d pix",m_pJFH->JWidth);
					pDC->TextOut(0,40,s);
					s.Format("FirstColor = RGB(%d,%d,%d)",m_pJFH->FirstColor[0],m_pJFH->FirstColor[1],m_pJFH->FirstColor[2]);
					pDC->TextOut(0,60,s);
					s.Format("SecondColor = RGB(%d,%d,%d)",m_pJFH->OpposeColor[0],m_pJFH->OpposeColor[1],m_pJFH->OpposeColor[2]);
					pDC->TextOut(0,80,s);
					for (i = 0;i < m_pBMIH->biHeight;i++)
					{
						for (j = 0;j < m_pBMIH->biWidth;j++)
						{
							BYTE b = *m_pBits++;
							BYTE g = *m_pBits++;
							BYTE r = *m_pBits++;
							pDC->SetPixel(j,m_pBMIH->biHeight-i+100,RGB(r,g,b));
						}
						m_pBits = m_pBits + m_pBMIH->biWidth%4;
					}
					m_pBits = BitsH;		//指针复位
				
					return TRUE;
				}
				
				//串行化
				void CJ::Serialize(CArchive &ar)
				{
					BMPRead(ar.GetFile());
				}
				
				//获取文件头指针 
				LPJFILEHEADER CJ::GetJFH()
				{
					return m_pJFH;
				}			

相关资源