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

📄 ezwcode.cpp

📁 this walet there is pictures in it you can debug it
💻 CPP
字号:
// EzwCode.cpp: implementation of the CEzwCode class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "wavelet.h"
#include "EzwCode.h"
#include "ompressOption.h"
#include<math.h>

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

#define NUL -1
//直接对应Huffman编码的概率
#define IZ  3    //孤立
#define POS 2    //正
#define NEG 1    //负
#define ZTR 0    //零树
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CEzwCode::CEzwCode()
{

}

CEzwCode::~CEzwCode()
{

}

bool CEzwCode::EzwQualitition(int minthr, int datheight, int datwidth, int k, short *p_store, long * fsize)
{
int i,j,tem,num[4]={0,0,0,0},totalnum=0;
	float pro[4];//各个符号出现的概率
	int cur,algin;
	//写文件
	CFile *pFile=new CFile();
	LPCTSTR lpszFilter;
	switch(k){
		case 0:
			lpszFilter="Red EZW Files(*.ezwr)|*.ezwr|任何文件|*.*||";
			break;
		case 1:
			lpszFilter="Green EZW Files(*.ezwg)|*.ezwg|任何文件|*.*||";
			break;
		case 2:
			lpszFilter="Blue EZW Files(*.ezwb)|*.ezwb|任何文件|*.*||";
			break;
	}
	CFileDialog *SaveDlg=new CFileDialog (FALSE, lpszFilter, "DATA",OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_NOCHANGEDIR,lpszFilter );
    if(SaveDlg->DoModal()==IDOK)
		pFile->Open(SaveDlg->GetPathName(),CFile::modeCreate |CFile::modeWrite|CFile::typeBinary,NULL);
	else
	{
		::AfxMessageBox("Cannot open file to write !");
		return 0;
	}


	
	EzwIn=new short [datheight*datwidth];
    EzwBigIn=new short [datheight*datwidth];
	//存放大数
	EzwTmp=new short [datheight*datwidth];
	
	//Huffman编码的初始化
	mask = 0x80;
	output_byte = 0;
	ones=0;
	
	zeroes=0;
    
	algin=(datwidth*3+3)/4 *4;

	//主循环对RGB分别处理
	for (k=0;k<=2;k++)
	{
	for(i=0;i<datheight;i++)
	{
		for(j=0;j<datwidth;j++)
		{	
			//把数据读到EzwIn中

            cur= i*algin+3*j;
			EzwIn[i*datwidth+j]=p_store[cur+k];

            //EzwBigIn存放标记
			//EzwTmp存放大数
			EzwBigIn[i*datwidth+j]=NUL;
			EzwTmp[i*datwidth+j]=NUL;
			
		}

	}

 

	//Produce DominateChart
	//找到最大值max,log2(max)向上取整-1,并存入TreFstFtr
	//以pow(2,TreFstFtr)作为初始的阈值,而pow(2,minthr)作为终止阈值
	FirstFactor(datheight,datwidth,EzwIn);
	
	Thresholdnum=TreFstFtr-minthr+1;//循环次数


	pFile->Write (&TreFstFtr,sizeof(TreFstFtr));//实际上是int型变量,最大阈值
    
	

	for(thr=TreFstFtr-minthr;thr>=0;thr--)
	{
		//处理主表
	    
		for(i=0;i<datheight;i++)
		{
			for(j=0;j<datwidth;j++)
			{
                if (abs(EzwTmp[i*datwidth+j])>=1)
				{
				  if(!PrtsIsZTR(thr,i,j,datheight,datwidth))
				  {
					//如果不是零树的子孙系数

					if(abs(EzwIn[i*datwidth+j])<(int)(1<<(thr+minthr)))
					{
						
						//如果绝对值小于当前阈值
						if(ChldIsMin(thr+minthr,i,j,datheight,datwidth))
						{
							//如果子孙都小于阈值
							EzwBigIn[i*datwidth+j]=ZTR;
							ChildIsZero(i,j,datheight,datwidth);
							//记为零树
							num[ZTR]++;
						}
						else
						{	//如果子孙系数有意义,记为孤立零点
							EzwBigIn[i*datwidth+j]=IZ;
							num[IZ]++;
						}
					}
					else//如果当前系数绝对值大于阈值
					{
						if(EzwIn[i*datwidth+j]>0)
						{	
							//为正数,记为P
						    EzwBigIn[i*datwidth+j]=POS;
							num[POS]++;
						}
						else
						{	//为负数,记为N
							EzwBigIn[i*datwidth+j]=NEG;
							num[NEG]++;
						}
						//将重要数据转移到EzeBigIn数组中,原数置零
						EzwTmp[i*datwidth+j]=EzwIn[i*datwidth+j];//if not 0 this piont ready to produce sub-chart
						EzwIn[i*datwidth+j]=0;
					}
					
				}//end if PrtsIsZTR

				}//end if EzwTmp
			} //end for j
		} //end for i
        




        HuffmanEncode(minthr,datheight,datwidth,pFile);
	}//end for thr
    if (mask!=0x80)
	{
		pFile->Write(&output_byte,sizeof(output_byte));
	}


	}//end for k

	

	char temp[100];
	float compression,bpp;
	compression=(float)datheight*datwidth*8/(ones+zeroes);
	bpp=(float)(ones+zeroes)/datheight/datwidth;
    sprintf(temp,"压缩比例:%2.2f",compression);
	::AfxMessageBox(temp);

	delete SaveDlg;
	pFile->Close();
	delete pFile;
    

	delete [] EzwIn;
	delete [] EzwBigIn;
	delete [] EzwTmp;

	
	
	return 1;
}

void CEzwCode::FirstFactor(int datheight, int datwidth, short *Ez)
{
//寻找最大量化阈值
	short max=0;
	for(int i=0;i<datheight;i++)
		for(int j=0;j<datwidth;j++)
			if(abs(Ez[i*datwidth+j])>max)
			{
				max=abs(Ez[i*datwidth+j]);
			}
	//找到最大值max,log2(max)向上取整-1;
    TreFstFtr=int(ceil(log10(max)/log10(2))-1);
    return;
}

bool CEzwCode::PrtsIsZTR(int thr, int i, int j, int datheight, int datwidth)
{
//判断某结点是否为零树的子孙
	if((i==0)&&(j==0))//根节点,非零树子孙
		return 0;
	if (i<0)
		i=0;
	if (j<0)
		j=0;
	int k=(int)floor(i>>1);//父节点
	int l=(int)floor(j>>1);
	if(EzwBigIn[k*datwidth+l]==ZTR)//查找主系数表
		return 1;
	else
		return PrtsIsZTR(thr,k,l,datheight,datwidth);//递归调用
}

bool CEzwCode::ChldIsMin(int thr, int i, int j, int datheight, int datwidth)
{
int k,l,ElgFactor=1;
	while((i<datheight/2)&&(j<datwidth/2))//在倒数第二层上截止
	{
		for(k=i*2;k<2*i+(int)(1<<ElgFactor);k++)
			for(l=j*2;l<2*j+(int)(1<<ElgFactor);l++)
			{
				//依次寻找子孙节点
				if (k*datwidth+l<datwidth*datheight)
					if(abs(EzwIn[k*datwidth+l])>=(int)(1<<thr))
						return 0;
				
			}
		i=i<<1;
		j=j<<1;
		ElgFactor+=1;
	}
	return 1; 
}

void CEzwCode::ChildIsZero(int i, int j, int datheight, int datwidth)
{
 int k,l,ElgFactor=1;
	while((i<datheight/2)&&(j<datwidth/2))//在倒数第二层上截止
	{
		for(k=i*2;k<2*i+(int)(1<<ElgFactor);k++)
			for(l=j*2;l<2*j+(int)(1<<ElgFactor);l++)
			{
				//依次寻找标记子孙节点为零树子节点
				if (k<datheight && l<datwidth)
					if((EzwTmp[k*datwidth+l]==NUL))
						EzwTmp[k*datwidth+l]=0;			
			}
		i=i<<1;
		j=j<<1;
		ElgFactor+=1;
	}

	return;
}

bool CEzwCode::HuffmanEncode(int minthr, int datheight, int datwidth, CFile *pFile)
{
//map:ZTR,NEG,POS,IZ->0,10,110,111

	int i,j,k,OrdOfHuff[4];
	for(i=0;i<4;i++)
		OrdOfHuff[i]=i;

	//输出1的个数,概率最大的为0个(ZTR)
	//最小的为3个,合乎huffman编码的规律

	//文件数据
	//for(thr=TreFstFtr-minthr;thr>=0;thr--)
	{
		//主表数据

		for(i=0;i<datheight;i++)
			for(j=0;j<datwidth;j++)
			{
				if((EzwBigIn[i*datwidth+j]<4)&&(EzwBigIn[i*datwidth+j]>=0))
				{

					for(k=OrdOfHuff[EzwBigIn[i*datwidth+j]];k>0;k--)
					{
						PutBit('1',pFile);

					}
					if((OrdOfHuff[EzwBigIn[i*datwidth+j]]<3)&&(OrdOfHuff[EzwBigIn[i*datwidth+j]]>=0))
					{
						PutBit('0',pFile);

					}

				}

			}//end for j
			
		//附表数据

			for(i=0;i<datheight;i++)
				for(j=0;j<datwidth;j++)
				{
					//修改处
					if(abs(EzwTmp[i*datwidth+j])>1)
					{
					    EzwBigIn[i*datwidth+j]=CalSV(thr+minthr,i,j,datheight,datwidth);
						if(!EzwBigIn[i*datwidth+j])
						{
							PutBit('0',pFile);
						}
					    else
						{
						    PutBit('1',pFile);
						}
					}
					//修改处
					if (EzwTmp[i*datwidth+j]==0)
						EzwTmp[i*datwidth+j]=NUL;
					EzwBigIn[i*datwidth+j]=NUL;
				}

	}

	return 1;
}

bool CEzwCode::PutBit(char bit, CFile *pf)
{
//以一个字节为单位输出数据
	//开始掩模   mask=128=1000 0000
	//开始output_byte=0  =0000 0000
	if (bit=='1') 
	{
		output_byte |= mask;//位或
		ones++;
	}
	else 
		zeroes++;
	//用于计算压缩率
	mask >>= 1;//右移一位
	if (mask==0) 
	{	
		//每8位输出一次,并把mask和output_byte初始化
		pf->Write(&output_byte,sizeof(output_byte));
		output_byte = 0;
		mask = 0x80;
	}
	return 1;
}

int CEzwCode::CalSV(int nowthr, int i, int j, int datheight, int datwidth)
{
//计算附表值
	//三个门限值,此时阈值的1 1.5 2倍
	int low=(int)(1<<nowthr);
	int middle=(int)((1<<nowthr)*1.5);
	int high=(int)(1<<(nowthr+1));
	while(high<=(int)(1<<(TreFstFtr+1)))//不大于最高阈值
	{
		if((abs(EzwTmp[i*datwidth+j])>=low)&&(abs(EzwTmp[i*datwidth+j])<high))
			if(abs(EzwTmp[i*datwidth+j])>=middle)
				return 1;//大于中门限
			else
				return 0;//小于中门限

		low+=int(1<<nowthr);
		middle+=int(1<<nowthr);
		high+=int(1<<nowthr);
	}
	//出错
	return -1;
}

int CEzwCode::BitToEzwDV(CFile *pf)
{
	switch (GetBit(pf)) 
	{
		case '1':
			switch (GetBit(pf)) 
			{
				case '0': 
					return 1;
				case '1':
					switch (GetBit(pf)) 
					{
						case '0': 
							return 2;
						case '1':
							return 3;	
					}
			}
			break;
		case '0':
	 		return 0;
			break;

	}

	return 1;	
	//出错
}

int CEzwCode::BitToEzwSV(CFile *pf)
{
//Reads a code from the input stream,output SV
	switch (GetBit(pf)) //need to change to common style of cal
	{
		case '1':
	 		return 1;
			break;
		case '0':
	 		return 0;
			break;

	}

	return 0;
}

char CEzwCode::GetBit(CFile *pf)
{
	//以一个字节为单位读入数据
	
	unsigned char bit;

	if (mask==0)
	{
		//每8位读一次

		pf->Read (&input_byte,sizeof(input_byte));
	
		mask = 0x80;//128=1000 0000
	}

	if ((input_byte&mask)==0) 
	{
		bit = '0';
		zeroes++;
	}
	else 
	{
		bit = '1';
		ones++;
	}

	mask >>= 1;

	return (bit);
}

bool CEzwCode::EzwInverseQualitition(int minthr, int datheight, int datwidth, int k, short *p_store)
{
//零树反量化
	int i,j;

	//把POS和NEG标志的值求出来
		for(i=0;i<datheight;i++)
			for(j=0;j<datwidth;j++)
				if((thr!=0)||(minthr!=0))
					if((EzwIn[i*datwidth+j]==1)||(EzwIn[i*datwidth+j]==0))
					{
						if(FlagOut[i*datwidth+j]==-1)//第一次赋初值
							FlagOut[i*datwidth+j]=EzwIn[i*datwidth+j];
						else
						{
							//第一次以后累加
							FlagOut[i*datwidth+j]=FlagOut[i*datwidth+j]*2+2+EzwIn[i*datwidth+j];
						}

						EzwOut[i*datwidth+j]=(int)((1<<(thr+minthr))*(1.25+FlagOut[i*datwidth+j]*0.5))*sign(EzwOut[i*datwidth+j]);
					}
     
	

		for(i=0;i<datheight;i++)
			for(j=0;j<datwidth;j++)
			{
				if((thr==0)&&(minthr==0))
					if((EzwBigIn[i*datwidth+j]==POS)||(EzwBigIn[i*datwidth+j]==NEG))
						EzwOut[i*datwidth+j]=1;
				if(EzwBigIn[i*datwidth+j]==NEG)
					EzwOut[i*datwidth+j]*=-1;
			}
		



	return 1;
}

bool CEzwCode::HuffmanDecode(int minthr, int datheight, int datwidth, int k, short *p_store, long fsize)
{
int i,j,Thresholdnum;
	bool *EzwSVFlag=(bool *)HeapAlloc(GetProcessHeap(),0,datheight*datwidth*sizeof(bool));
	input_byte = 0;
	mask = 0;
	ones=0;
	zeroes=0;
    char str_tmp[20];

	CFile *pFile=new CFile();
	LPCTSTR lpszFilter;
	switch(k){
		case 0:
			lpszFilter="Red EZW Files(*.ezwr)|*.ezwr|任何文件|*.*||";
			break;
		case 1:
			lpszFilter="Green EZW Files(*.ezwg)|*.ezwg|任何文件|*.*||";
			break;
		case 2:
			lpszFilter="Blue EZW Files(*.ezwb)|*.ezwb|任何文件|*.*||";
			break;
	}
	CFileDialog *SaveDlg=new CFileDialog (TRUE, lpszFilter, "DATA",OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT|OFN_NOCHANGEDIR,lpszFilter );
    if(SaveDlg->DoModal()==IDOK)
		pFile->Open(SaveDlg->GetPathName(),CFile::modeRead|CFile::typeBinary,NULL);
	else
	{
		::AfxMessageBox("Cannot open file to read !");
		return 0;
	}

	//for (k=0;k<=1;k++)
	{
	    //读头文件
		
	

		pFile->Read (&TreFstFtr,sizeof(TreFstFtr));//读最大量化阈值
		Thresholdnum=TreFstFtr-minthr+1;

		EzwIn=new short [datheight*datwidth];
        EzwBigIn=new short [datheight*datwidth];
		FlagOut=(int *)HeapAlloc(GetProcessHeap(),0,datheight*datwidth*sizeof(int));
    	EzwOut=(int *)HeapAlloc(GetProcessHeap(),0,datheight*datwidth*sizeof(int));

		for(i=0;i<datheight;i++)
		{
			for(j=0;j<datwidth;j++)
			{
				FlagOut[i*datwidth+j]=-1;
			    EzwOut[i*datwidth+j]=0;
				//初始化主附表数组
                //EzwSVFlag存放区间状态
				EzwSVFlag[i*datwidth+j]=0;
                //EzwBigIn存放四种状态
				EzwBigIn[i*datwidth+j]=NUL;
				EzwIn[i*datwidth+j]=NUL;

			}
		}
        


		for (i=0;i<=3;i++)
			EzwDVOfPro[i]=i;
        

		
		for(thr=TreFstFtr-minthr;thr>=0;thr--)
		{
			//读主表
			for(i=0;i<datheight;i++)
				for(j=0;j<datwidth;j++)
					if (abs(EzwBigIn[i*datwidth+j])>0)	
					{
						EzwBigIn[i*datwidth+j]=EzwDVOfPro[BitToEzwDV(pFile)];//读取主表数据


                        if (EzwBigIn[i*datwidth+j]==ZTR)
							DecodeZero(i,j,datheight,datwidth);

						if((EzwBigIn[i*datwidth+j]==POS)||(EzwBigIn[i*datwidth+j]==NEG))
						{
							EzwSVFlag[i*datwidth+j]=1;//重要数据对应附表
						}
					}

			
			
			//读附表

				for(i=0;i<datheight;i++)
					for(j=0;j<datwidth;j++)
						if(EzwSVFlag[i*datwidth+j]==1)
						{
							EzwIn[i*datwidth+j]=BitToEzwSV(pFile);
						}
			
			
			EzwInverseQualitition(minthr,datheight,datwidth,k,p_store);
			for (i=0;i<datheight;i++)
				for (j=0;j<datwidth;j++)
					EzwBigIn[i*datwidth+j]=NUL;
		}
        


    }//end for k



	int align,cur;
	align=(datwidth*3+3)/4 *4;
	for(i=0;i<datheight;i++)
	{
		for(j=0;j<datwidth;j++)
		{
            cur= i*align+3*j;
			p_store[cur+k]=EzwOut[i*datwidth+j];
		}

	}

	char temp[100];
	float compression,bpp;
	compression=(float)datheight*datwidth*8/(ones+zeroes);
    bpp=(float)(ones+zeroes)/datheight/datwidth;
    sprintf(temp,"解压缩比例:%2.2f",compression);
	::AfxMessageBox(temp);
	
	HeapFree(GetProcessHeap(),0,EzwSVFlag);
	HeapFree(GetProcessHeap(),0,FlagOut);
    HeapFree(GetProcessHeap(),0,EzwOut);
	delete [] EzwBigIn;
	delete [] EzwIn;
	
	delete SaveDlg;
	pFile->Close();
	delete pFile;
	
	return 1;
}

int CEzwCode::sign(int Ezwnum)
{
	if (Ezwnum>=0)
		return 1;
	else 
		return -1;
}

void CEzwCode::DecodeZero(int i, int j, int datheight, int datwidth)
{
int k,l,ElgFactor=1;
	while((i<datheight/2)&&(j<datwidth/2))//在倒数第二层上截止
	{
		for(k=i*2;k<2*i+(int)(1<<ElgFactor);k++)
			for(l=j*2;l<2*j+(int)(1<<ElgFactor);l++)
			{
				//依次寻找标记子孙节点为零树子节点
				if (k<datheight && l<datwidth)
					if((EzwBigIn[k*datwidth+l]==NUL))
						EzwBigIn[k*datwidth+l]=0;			
			}
		i=i<<1;
		j=j<<1;
		ElgFactor+=1;
	}

	return;
}

⌨️ 快捷键说明

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