?? ezwcode.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
//直接對應(yīng)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];//各個符號出現(xiàn)的概率
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];
//存放大數(shù)
EzwTmp=new short [datheight*datwidth];
//Huffman編碼的初始化
mask = 0x80;
output_byte = 0;
ones=0;
zeroes=0;
algin=(datwidth*3+3)/4 *4;
//主循環(huán)對RGB分別處理
for (k=0;k<=2;k++)
{
for(i=0;i<datheight;i++)
{
for(j=0;j<datwidth;j++)
{
//把數(shù)據(jù)讀到EzwIn中
cur= i*algin+3*j;
EzwIn[i*datwidth+j]=p_store[cur+k];
//EzwBigIn存放標(biāo)記
//EzwTmp存放大數(shù)
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;//循環(huán)次數(shù)
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))
{
//如果不是零樹的子孫系數(shù)
if(abs(EzwIn[i*datwidth+j])<(int)(1<<(thr+minthr)))
{
//如果絕對值小于當(dāng)前閾值
if(ChldIsMin(thr+minthr,i,j,datheight,datwidth))
{
//如果子孫都小于閾值
EzwBigIn[i*datwidth+j]=ZTR;
ChildIsZero(i,j,datheight,datwidth);
//記為零樹
num[ZTR]++;
}
else
{ //如果子孫系數(shù)有意義,記為孤立零點
EzwBigIn[i*datwidth+j]=IZ;
num[IZ]++;
}
}
else//如果當(dāng)前系數(shù)絕對值大于閾值
{
if(EzwIn[i*datwidth+j]>0)
{
//為正數(shù),記為P
EzwBigIn[i*datwidth+j]=POS;
num[POS]++;
}
else
{ //為負數(shù),記為N
EzwBigIn[i*datwidth+j]=NEG;
num[NEG]++;
}
//將重要數(shù)據(jù)轉(zhuǎn)移到EzeBigIn數(shù)組中,原數(shù)置零
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)
{
//判斷某結(jié)點是否為零樹的子孫
if((i==0)&&(j==0))//根節(jié)點,非零樹子孫
return 0;
if (i<0)
i=0;
if (j<0)
j=0;
int k=(int)floor(i>>1);//父節(jié)點
int l=(int)floor(j>>1);
if(EzwBigIn[k*datwidth+l]==ZTR)//查找主系數(shù)表
return 1;
else
return PrtsIsZTR(thr,k,l,datheight,datwidth);//遞歸調(diào)用
}
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))//在倒數(shù)第二層上截止
{
for(k=i*2;k<2*i+(int)(1<<ElgFactor);k++)
for(l=j*2;l<2*j+(int)(1<<ElgFactor);l++)
{
//依次尋找子孫節(jié)點
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))//在倒數(shù)第二層上截止
{
for(k=i*2;k<2*i+(int)(1<<ElgFactor);k++)
for(l=j*2;l<2*j+(int)(1<<ElgFactor);l++)
{
//依次尋找標(biāo)記子孫節(jié)點為零樹子節(jié)點
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的個數(shù),概率最大的為0個(ZTR)
//最小的為3個,合乎huffman編碼的規(guī)律
//文件數(shù)據(jù)
//for(thr=TreFstFtr-minthr;thr>=0;thr--)
{
//主表數(shù)據(jù)
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
//附表數(shù)據(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)
{
//以一個字節(jié)為單位輸出數(shù)據(jù)
//開始掩模 mask=128=1000 0000
//開始o(jì)utput_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)
{
//以一個字節(jié)為單位讀入數(shù)據(jù)
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標(biāo)志的值求出來
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;
//初始化主附表數(shù)組
//EzwSVFlag存放區(qū)間狀態(tài)
EzwSVFlag[i*datwidth+j]=0;
//EzwBigIn存放四種狀態(tài)
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)];//讀取主表數(shù)據(jù)
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;//重要數(shù)據(jù)對應(yīng)附表
}
}
//讀附表
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))//在倒數(shù)第二層上截止
{
for(k=i*2;k<2*i+(int)(1<<ElgFactor);k++)
for(l=j*2;l<2*j+(int)(1<<ElgFactor);l++)
{
//依次尋找標(biāo)記子孫節(jié)點為零樹子節(jié)點
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;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -