// ARITHCoding.cpp: implementation of the CARITHCoding class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "HIC.h"
#include "ARITHCoding.h"
#include "math.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
static unsigned short qe_value[47]=
{0x5601,0x3401,0x1801,0x0ac1,0x0521,0x0221,0x5601,0x5401,
0x4801,0x3801,0x3001,0x2401,0x1c01,0x1601,0x5601,0x5401,
0x5101,0x4801,0x3801,0x3401,0x3001,0x2801,0x2401,0x2201,
0x1c01,0x1801,0x1601,0x1401,0x1201,0x1101,0x0ac1,0x09c1,
0x08a1,0x0521,0x0441,0x02a1,0x0221,0x0141,0x0111,0x0085,
0x0049,0x0025,0x0015,0x0009,0x0005,0x0001,0x5601};
static unsigned short nmps[47]=
{1, 2, 3, 4, 5, 38,7, 8, 9, 10,11,12,13,29,15,16,17,18,19,20,
21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,45,46};
static unsigned short nlps[47]=
{1, 6, 9, 12,29,33,6, 14,14,14,17,18,20,21,14,14,15,16,17,18,
19,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,
38,39,40,41,42,43,46};
static unsigned short flag[47]=
{1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static unsigned short a_register,ct,mps[20],index[20];
static unsigned long c_register,bp,b0,b1,CC;
static long BytesLimit,sc,TByteLimit; // size limited by compressed image size.
static long num_of_packed_bytes=0; // total bytes written out.
static long num_of_unpacked_bytes=0; // total bytes read in.
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CARITHCoding::CARITHCoding()
{
}
CARITHCoding::~CARITHCoding()
{
}
/**************************************************************************
完成算术编码的初始化 MQ_EncoderInit()
**************************************************************************/
void CARITHCoding::MQ_EncoderInit()
{
short i;
a_register=0x8000;
c_register=0;
ct=12;
bp=0;
sc=0;
for(i=0;i<20;i++)
{
index[i]=0;
mps[i]=0;
if(i==0) index[i]=4;
if(i==17) index[i]=3;
if((i==18)||(i==19)) index[i]=46;
}
}
/**************************************************************************
算术编码的主函数 pack1()
**************************************************************************/
long CARITHCoding::pack1(short bit_num, short bit_value, short con)
{
short i,f_bit;
for(i=0;i<bit_num;i++)
{
f_bit=bit_value>>i;
if((f_bit&1)==mps[con])
{
a_register-=qe_value[index[con]];
if((a_register&0x8000)==0)
{
if(a_register<qe_value[index[con]]) a_register=qe_value[index[con]];
else c_register+=qe_value[index[con]];
index[con]=nmps[index[con]];
do{
a_register<<=1;
c_register<<=1;
ct--;
if (ct==0)
{
byteout();
if(sc>=BytesLimit) return -1;
}
}
while ((a_register&0x8000)==0);
}
else c_register+=qe_value[index[con]];
}
else {
a_register-=qe_value[index[con]];
if(a_register<qe_value[index[con]])
c_register+=qe_value[index[con]];
else
a_register=qe_value[index[con]];
if (flag[index[con]]==1)
mps[con]=1-mps[con];
index[con]=nlps[index[con]];
do
{
a_register<<=1;
c_register<<=1;
ct--;
if (ct==0)
{
byteout();
if(sc>=BytesLimit) return -1;
}
}
while ((a_register&0x8000)==0);
}
}
return 0;
}
/**************************************************************************
算术编码的字节输出函数byteout()
*************************************************************************/
void CARITHCoding::byteout()
{
if(bp==0)
{
b0=c_register>>19;
bp++;
c_register&=0x7ffff;
ct=8;
}
else
{
if (b0==0xff)
{
b1=c_register>>20;
bp++;
c_register&=0xfffff;
ct=7;
}
else
{
if (c_register>=0x8000000)
{
b0++;
c_register&=0x7ffffff;
if(b0==0xff)
{
b1=c_register>>20;
bp++;
c_register&=0xfffff;
ct=7;
}
else
{
b1=c_register>>19;
bp++;
c_register&=0x7ffff;
ct=8;
}
}
else
{
b1=c_register>>19;
bp++;
c_register&=0x7ffff;
ct=8;
}
}
fwrite(&b0,sizeof(char),1,fp_out);
sc++;
b0=b1;
}
}
/**************************************************************************
算术编码的终止函数 flush
**************************************************************************/
void CARITHCoding::flush()
{
unsigned long tempc;
tempc=c_register+a_register;
c_register|=0xffff;
if (c_register>=tempc)
c_register-=0x8000;
c_register<<=ct;
byteout();
c_register<<=ct;
byteout();
if (b0!=0xff)
fwrite(&b0,sizeof(char),1,fp_out);
else bp--;
}
/**************************************************************************
MaxinMatrix()
功能:返回图像中的最大值
**************************************************************************/
short CARITHCoding::MaxinMatrix(BYTE *image, short x_size, short y_size)
{
short i,j,max;
max=abs(image[0]);
for(i=0;i<y_size;i++)
for(j=0;j<x_size;j++)
if(abs(image[i*x_size+j])>max)
max=abs(image[i*x_size+j]);
return max;
}
short CARITHCoding::Bitplane_coding(BYTE *image, short n, short x_size, short y_size)
{
short i,j,Sn;
for(i=0;i<x_size;i++)
for(j=0;j<y_size;j++)
{
Sn=(abs(image[i*x_size+j])>>n)&1;
pack1(1,Sn,0);
}
return 0;
}
short CARITHCoding::Encoding_Pass(BYTE *image, short x_size, short y_size)
{
short n;
n=(short)(log10(MaxinMatrix(image,x_size,y_size))/log10(2));
if(pack1(4,n,0)==-1) return -1;
while(n>=0)
{
if(Bitplane_coding(image,n,x_size,y_size)==-1) return -1;
n--;
}
return 0;
}
/**************************************************************************
AC_code()
功能:算术编码入口函数
**************************************************************************/
void CARITHCoding::AC_code(BYTE *image, short x_size, short y_size)
{
BytesLimit=(long)(x_size*y_size);
MQ_EncoderInit();
if(Encoding_Pass(image,x_size,y_size)==-1)
goto END;
END:flush();
fclose(fp_out);
return;
}
void CARITHCoding::Init_AC_QM_Decoder()
{
short i;
a_register=0x8000;
c_register=0;
ct=12;
bp=0;
sc=0;
fread(&b0,sizeof(char),1,fp_in);
sc=1;
c_register=b0<<16;
bytein();
c_register<<=7;
ct-=7;
a_register=0x8000;
for(i=0;i<20;i++)
{
index[i]=0;
mps[i]=0;
if(i==0) index[i]=4;
if(i==17) index[i]=3;
if((i==18)||(i==19)) index[i]=46;
}
}
short CARITHCoding::Decoding_Pass(BYTE *image, short x_size, short y_size)
{
short n;
if(unpack1(4,&n,0)==-1) return -1;
while(n>=0)
{
if(Decodepass(image,n,x_size,y_size)==-1)
return -1;
n--;
}
return 0;
}
short CARITHCoding::Decodepass(BYTE *image, short n, short x_size, short y_size)
{
int Bit,i,j;
short Sn;
Bit=1<<n;
for (i=0;i<x_size;i++)
for(j=0;j<y_size;j++)
{
if(unpack1(1,&Sn,0)==-1)
return -1;
if(Sn)
image[i*x_size+j]|=Bit;
}
return 0;
}
void CARITHCoding::bytein()
{
fread(&b1,sizeof(char),1,fp_in);
sc++;
if(b0==0xff){
if(b1>0x8f) {
c_register+=0xff00;
ct=8;
}
else{
bp++;
c_register+=b1<<9;
ct=7;
}
}
else{
bp++;
c_register+=b1<<8;
ct=8;
}
b0=b1;
}
long CARITHCoding::unpack1(short bit_num, short *bit_value, short con)
{
unsigned short i,d;
unsigned long chigh;
*bit_value=0;
for(i=0;i<bit_num;i++)
{
chigh=c_register>>16;
a_register-=qe_value[index[con]];
if(chigh<qe_value[index[con]])
{
if(a_register<qe_value[index[con]])
{
a_register=qe_value[index[con]];
d=mps[con];
index[con]=nmps[index[con]];
}
else
{
a_register=qe_value[index[con]];
d=1-mps[con];
if(flag[index[con]]==1) mps[con]=1-mps[con];
index[con]=nlps[index[con]];
}
do
{
if(ct==0)
{
bytein();
if(sc>=BytesLimit) return -1;
}
a_register<<=1;
c_register<<=1;
ct--;
}
while((a_register&0x8000)==0);
}
else
{
chigh-=qe_value[index[con]];
c_register&=0xffff;
c_register+=chigh<<16;
if((a_register&0x8000)==0)
{
if(a_register<qe_value[index[con]])
{
d=1-mps[con];
if(flag[index[con]]==1) mps[con]=1-mps[con];
index[con]=nlps[index[con]];
}
else
{
d=mps[con];
index[con]=nmps[index[con]];
}
do{
if(ct==0)
{
bytein();
if(sc>=BytesLimit) return -1;
}
a_register<<=1;
c_register<<=1;
ct--;
}
while((a_register&0x8000)==0);
}
else d=mps[con];
}
*bit_value+=(short)(d<<i);
}
return 0;
}
BYTE* CARITHCoding::AC_decode(short x_size, short y_size)
{
BYTE *image;
short i,j,mark;
BytesLimit=(long)(x_size*y_size);
image=(BYTE *)new BYTE [x_size*y_size];
Init_AC_QM_Decoder();
for(i=0;i<x_size;++i)
for(j=0;j<y_size;++j)
image[i*x_size+j]=0;
mark=Decoding_Pass(image,x_size,y_size);
if(mark==-1)
goto END;
END:
for(i=0;i<y_size;i++)
{
fwrite(&image[i*x_size],sizeof(unsigned char),y_size,fp_out);
}
fclose(fp_out);
fclose(fp_in);
return image;
}