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

📄 bmpcompressdlg.cpp

📁 本源码是用VC++6.0实现的
💻 CPP
📖 第 1 页 / 共 2 页
字号:

	str="文件大小->";
	::itoa(m_bfsize,strChar1,10);
	strcpy(strChar,str);
	strcat(strChar,strChar1);
	strcat(strChar,"bit");
	pDC->TextOut(left+5,top+25,strChar);
	if(strTitle=="位图文件名称->")
	{
	str="颜色位数->";
	::itoa(m_numberofcolor,strChar1,10);
	strcpy(strChar,str);
	strcat(strChar,strChar1);
	pDC->TextOut(left+5,top+45,strChar);
	}
	if(strTitle=="被压缩后文件名称->")
	{
	str="压缩比->";
	strcpy(strChar,str);
    strcat(strChar,m_compressionRatio);
	pDC->TextOut(left+5,top+45,strChar);
	}
}

void CBmpCompressDlg::OnOutofmemoryScaleDisplayBMP(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here

	*pResult = 0;
}

void CBmpCompressDlg::OnUpdateClient(int nIDDlgItem)
{
	
}


void CBmpCompressDlg::OnReleasedcaptureScale(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	CWnd *pBtn=GetDlgItem(IDDDISPLAY);
	CString str;
	pBtn->GetWindowText(str);
	if((m_Dib.GetData()!=NULL)&&(str!="Display"))
	{
		m_ratio=((float)m_scale.GetPos())/100;
		OnDrawBMP();
		*pResult = 0;
	}
	else
	{
		MessageBox("没有显示图像!", "系统提示" , 
			MB_ICONINFORMATION | MB_OK);
		m_scale.SetPos(0);
	}
}

BOOL CBmpCompressDlg::CompressBMP(CFile & dibfile)
{

	int bH=m_Dib.GetHeight();//the height of BMP
	int bW=m_Dib.GetWidth();//the width of BMP
	DWORD dwSizeUsedRow=0;//行扫描有用字节数
	DWORD dwSizeUsedCol=0;//列扫描有用字节数
	DWORD i=0;
	BYTE *pBitmapData=m_Dib.GetData();
	LPBYTE bufferIn;
	LPBYTE bufferOutRow;
	LPBYTE bufferOutCol;
	DWORD realSize;
	realSize=m_Dib.GetSize();
	bufferIn=new BYTE[realSize];
	bufferIn=pBitmapData;
	bufferOutRow=new BYTE[realSize];
	bufferOutCol=new BYTE[realSize];
	//写入DAT文件头结构
	DATHEADER datHdr;
	datHdr.bManufacturer= 0x0A;
	datHdr.bVersion=5;
	datHdr.wHeight=m_Dib.GetHeight();
	datHdr.wWidth=m_Dib.GetWidth();
	datHdr.numberOfColor=m_numberofcolor;
	datHdr.biSizeImage=m_Dib.GetSize();
	//压缩编码开始
	//选取标志位
	int id[255];
	memset(id,0,256);//初始化数组
	for(i=0;i<realSize;i++)
		id[(int)bufferIn[i]]++;
	int idOfMinCount=id[0];
	BYTE identify;//标志位
	for(i=0;i<256;i++)
	{	if(id[i]<idOfMinCount)
		{
			idOfMinCount=id[i];
			identify=(BYTE)i;
			if(idOfMinCount==0)
				break;
		}
	}
	datHdr.identify=identify;
	//按行压缩:
	BYTE CH=bufferIn[0];
	if(CH==identify)
	{
		if((int)identify!=0)
			CH=BYTE((int)identify-1);//如果图像中存在标志位的实际像素将该像素值减一
		else 
			CH=BYTE((int)identify+1);
	}
	BYTE SC;
	int iCount=1;//重复字符个数
	for(i=1;i<realSize;i++)
	{
		SC=bufferIn[i];
		if(SC==identify)
		{
			if((int)identify!=0)
				CH=BYTE((int)identify-1);//如果图像中存在标志位的实际像素将该像素值减一
			else 
				CH=BYTE((int)identify+1);
		}
		if((SC==CH)&&(iCount<255))
			iCount++;
		else if(iCount<4)
		{
			memset(&bufferOutRow[dwSizeUsedRow],CH,iCount);
			dwSizeUsedRow+=iCount;
			iCount=1;
			CH=SC;
		}
		else
		{
			bufferOutRow[dwSizeUsedRow]=identify;
			bufferOutRow[dwSizeUsedRow+1]=iCount;
			bufferOutRow[dwSizeUsedRow+2]=CH;
			CH=SC;
			dwSizeUsedRow+=3;
			iCount=1;
			 
		}
	}
	//--保存最后一部分编码
	if(iCount<4)
	{
			memset(&bufferOutRow[dwSizeUsedRow],CH,iCount);
			dwSizeUsedRow+=iCount;
			CH=SC;
	}
	else
	{
		bufferOutRow[dwSizeUsedRow]=identify;
		bufferOutRow[dwSizeUsedRow+1]=iCount;
		bufferOutRow[dwSizeUsedRow+2]=CH;
		CH=SC;
		dwSizeUsedRow+=3;
	}
	
	//按列压缩:
	BYTE **bufferInCol;
	bufferInCol=new  BYTE *[bH];
	for(int index=0;index<bH;index++)
		bufferInCol[index]=new BYTE[bW];
	int row;
	int col;
	for(row=0;row<bH;row++)
		for( col=0;col<bW;col++)
			bufferInCol[row][col]=*bufferIn++;//将像素数据存于二维数组中

	CH=bufferInCol[0][0];
	if(CH==identify)
	{
		if((int)identify!=0)
			CH=BYTE((int)identify-1);//如果图像中存在标志位的实际像素将该像素值减一
		else 
			CH=BYTE((int)identify+1);
	}
	
	iCount=1;//重复字符个数
	for( col=0;col<bW;col++)
		for( row=0;row<bH;row++)
		{
			SC=bufferInCol[row][col];
			if(SC==identify)
			{
				if((int)identify!=0)
					CH=BYTE((int)identify-1);//如果图像中存在标志位的实际像素将该像素值减一
				else 
					CH=BYTE((int)identify+1);
			}
			if((SC==CH)&&(iCount<255))
				iCount++;
			else if(iCount<4)
			{
				memset(&bufferOutCol[dwSizeUsedCol],CH,iCount);
				dwSizeUsedCol+=iCount;
				iCount=1;
				CH=SC;
			}
			else
			{
				bufferOutCol[dwSizeUsedCol]=identify;
				bufferOutCol[dwSizeUsedCol+1]=iCount;
				bufferOutCol[dwSizeUsedCol+2]=CH;
				CH=SC;
				dwSizeUsedCol+=3;
				iCount=1;
			}
		}
	//----保存最后一部分编码
	if(iCount<4)
		{
			memset(&bufferOutCol[dwSizeUsedCol],CH,iCount);
			dwSizeUsedCol+=iCount;
			
		}
	else
		{
			bufferOutCol[dwSizeUsedCol]=identify;
			bufferOutCol[dwSizeUsedCol+1]=iCount;
			bufferOutCol[dwSizeUsedCol+2]=CH;
			dwSizeUsedCol+=3;
		}
	//计算压缩比,并比较三种扫描方法的压缩比大小取其中最小的。
	
	DWORD dwHdSize=sizeof(DATHEADER)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)
		+sizeof(RGBQUAD)*m_numberofcolor;
	m_bfsize=dwHdSize+dwSizeUsedRow;
	float ratioRow=((float)m_bfsize/(float)m_Dib.GetFileSize());//按行扫描的压缩比:
	m_bfsize=dwHdSize+dwSizeUsedCol;
	float ratioCol=((float)m_bfsize/(float)m_Dib.GetFileSize());//按列扫描的压缩比:
	
	float ratio=(ratioRow<ratioCol)?ratioRow:ratioCol;//取小的
	::gcvt( ratio*100, 4, m_compressionRatio);//float to string
	::strcat(m_compressionRatio,"%");
	
	if(ratio==ratioRow)
		datHdr.iWay=0;
	else if(ratio==ratioCol)
		datHdr.iWay=1;
	//写入位图头信息
	dibfile.Write((LPSTR)&datHdr,sizeof(DATHEADER));
	dibfile.Write((void *)&m_Dib.bitmapFileHeader,sizeof(BITMAPFILEHEADER));
	dibfile.Write(m_Dib.m_pBitmapInfoHeader,sizeof(BITMAPINFOHEADER));
	dibfile.Write(m_Dib.m_pRGB,sizeof(RGBQUAD)*m_numberofcolor);
	//写入最小压缩比的压缩后数据
	if(datHdr.iWay==0)
		dibfile.WriteHuge((LPSTR)bufferOutRow, dwSizeUsedRow);
	else if(datHdr.iWay==1)
		dibfile.WriteHuge((LPSTR)bufferOutCol, dwSizeUsedCol);
	//显示文件信息
	m_filename=dibfile.GetFileName();
	m_numberofcolor=-1;
	CString str="被压缩后文件名称->";
	OnDrawTEXT(str);
	//写入压缩后的数据编码文件(十进制)
	char strFileName[256];
	strcpy(strFileName,dibfile.GetFilePath());
	strcat(strFileName,"行扫描");
	strcat(strFileName , ".txt");
	FILE *fp;
	fp=fopen(strFileName,"w");
	fprintf(fp,"%s","游程标志=");
	fprintf(fp,"%d ",identify);
	fprintf(fp,"%s","压缩比=");
	fprintf(fp,"%f\n",ratioRow);
	fprintf(fp,"%s%d %s%d\n","图像宽度=",bW,"图像高度=",bH);
	if(datHdr.iWay==0)
		fprintf(fp,"%s\n\n","-->由于压缩比低于列扫描方式,所以被程序采用!");
	int irow=0;//换行计数
	char c='\n';
	
	for(i=0;i<dwSizeUsedRow;i++)
	{	
		fprintf(fp,"%d  ",bufferOutRow[i]);irow++;
		if(irow==30)
		{
			fprintf(fp,"%c",c);irow=0;
		}
	}
	fclose(fp);
	
	strcpy(strFileName,dibfile.GetFilePath());
	strcat(strFileName,"列扫描");
	strcat(strFileName , ".txt");
	fp=fopen(strFileName,"w");
	fprintf(fp,"%s","游程标志=");
	fprintf(fp,"%d ",identify);
	fprintf(fp,"%s","压缩比=");
	fprintf(fp,"%f\n",ratioCol);
	fprintf(fp,"%s%d %s%d\n","图像宽度=",bW,"图像高度=",bH);
	if(datHdr.iWay==1)
		fprintf(fp,"%s\n\n","-->由于压缩比低于行扫描方式,所以被程序采用!");
	irow=0;//换行计数
	for(i=0;i<dwSizeUsedCol;i++)
	{	
			fprintf(fp,"%d  ",bufferOutCol[i]);irow++;
			if(irow==30)
			{
				fprintf(fp,"%c",c);irow=0;
			}
	}
	fclose(fp);
	
	return TRUE;
}

BOOL CBmpCompressDlg::DeCompressBmp(CFile & dibfile)
{  
	//读取DAT文件结构信息
	DATHEADER datHdr;
	m_CompressFile.Read((LPSTR)&datHdr,sizeof(DATHEADER));
	WORD bW= WIDTHBYTES(datHdr.wWidth * 8);
	WORD bH=datHdr.wHeight;
	WORD numOfColor=datHdr.numberOfColor;
	DWORD realSize=datHdr.biSizeImage;
	BYTE identify=datHdr.identify;
	//处理位图文件结构头,信息头,颜色表
	LPBYTE buffer;
	buffer=new BYTE[sizeof(BITMAPFILEHEADER)];
	m_CompressFile.Read(buffer,sizeof(BITMAPFILEHEADER));
	dibfile.Write(buffer,sizeof(BITMAPFILEHEADER));
	buffer=new BYTE[sizeof(BITMAPINFOHEADER)];
	m_CompressFile.Read(buffer,sizeof(BITMAPINFOHEADER));
	dibfile.Write(buffer,sizeof(BITMAPINFOHEADER));
	buffer=new BYTE[sizeof(RGBQUAD)*numOfColor];
	m_CompressFile.Read(buffer,sizeof(RGBQUAD)*numOfColor);
	dibfile.Write(buffer,sizeof(RGBQUAD)*numOfColor);
	//解压缩位图(像素)数据
	LPBYTE bufferIn;
	LPBYTE bufferOut;
	DWORD i=0;
	DWORD size=0;//bufferOut的下标
	int iCount=0;//重复字符个数
	BYTE bChar;
	DWORD sizeData=0;
	sizeData=m_CompressFile.GetLength()-sizeof(DATHEADER)-
		sizeof(BITMAPFILEHEADER)-sizeof(BITMAPINFOHEADER)
		-sizeof(RGBQUAD)*numOfColor;
	bufferIn=new BYTE[sizeData];
	m_CompressFile.Read(bufferIn,sizeData);
	bufferOut=new BYTE[bW*bH*2];
	for(i=0;i<sizeData;i++)
	{
		bChar=bufferIn[i];
		if(bChar==identify)
		{
			bChar=bufferIn[i+1];
			iCount=(int)bChar;
			bChar=bufferIn[i+2];
			i+=2;
			memset(bufferOut,bChar,iCount);
			bufferOut+=iCount;
			size+=iCount;
		}
		else
		{
			*bufferOut=bChar;
			bufferOut+=1;
			size+=1;
		}
	}
	bufferOut-=size;
	
	if(datHdr.iWay==0) //行扫描的解压存储
	{
		dibfile.WriteHuge((LPSTR)bufferOut,size);
		delete[] bufferOut;
	}
	else if(datHdr.iWay==1) //列扫描的解压
	{
		BYTE **bufferOutCol=new BYTE *[bH];
		for(int index=0;index<bH;index++)
			bufferOutCol[index]=new BYTE[bW];
		int	row=0;
		int col=0;
		BYTE bcharX='0';
		DWORD dwSz=0;
		for(col=0;col<bW;col++)
			for(row=0;row<bH;row++)
			{
				bcharX=bufferOut[dwSz];
				bufferOutCol[row][col]=bcharX;
				dwSz++;
			}
		LPBYTE bufferResultCol;
		bufferResultCol=new BYTE[dwSz];
		for(row=0;row<bH;row++)
			for(col=0;col<bW;col++)
			{
				bcharX=bufferOutCol[row][col];
				*bufferResultCol=bcharX;
				bufferResultCol++;
			}
		bufferResultCol-=dwSz;
		dibfile.WriteHuge((LPSTR)bufferResultCol,dwSz);
		delete[] bufferResultCol;
	}

	CString str="解压缩后文件名称->";
	m_bfsize=dibfile.GetLength();
	OnDrawTEXT(str);
	m_CompressFile.SetFilePath("");
	dibfile.Close();
	return TRUE;
}


void CBmpCompressDlg::OnDisplay() //显示位图
{
	// TODO: Add your control notification handler code here
	//图象显示比例
	CWnd *pBtn=GetDlgItem(IDDDISPLAY);
	CString str;
	pBtn->GetWindowText(str);
	if(m_Dib.GetData()!=NULL)
	{
		if(str=="Display")
		{
			pBtn->SetWindowText("HidePicture");
			m_ratio=1.0;
			m_scale.SetPos((int)(m_ratio*100));
			OnDrawBMP();
		}
		else
		{
			OnHideBMP();
			m_scale.SetPos(0);
		}
	}
	else
	{
		AfxMessageBox("请先装载位图文件!");
		return ;
	}
	
}

void CBmpCompressDlg::OnHideBMP()
{
	//刷新显示区
	CRect rect;
	CWnd *pDisplay=GetDlgItem(IDC_BMPINFO);
	pDisplay->GetWindowRect(rect);
	ScreenToClient(rect);
	CDC * pDC=GetDC();
	CBrush brush(RGB(255,255,255));
	rect.SetRect(rect.left+5,rect.top+5,rect.right-5,rect.bottom-5);
	pDC->FillRect(&rect,&brush);
	CWnd *pBtn=GetDlgItem(IDDDISPLAY);
	CString str;
	pBtn->GetWindowText(str);
	pBtn->SetWindowText("Display");
}

⌨️ 快捷键说明

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