MQ算术编码

作者在 2008-04-10 18:37:44 发布以下内容

// 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;

}

版本: V1.0
出品: 本站原创
来源: 本地
语言: 简体中文
授权: 免费
本地下载[1]: TestMQCoder.rar (下载后,请将文件重命名为 TestMQCoder.rar 方可正常使用)
编码 | 阅读 4689 次
文章评论,共1条
guoshengwei
2008-07-18 17:51
1
你好,TestMQCoder.rar里面文件不全,下载了用不了。<br />
请问可否给我完整的工程文件,以便学习,谢谢!<br />
QQ:371998216&nbsp;&nbsp;email:guoshengwei2000@163.com
游客请输入验证码
浏览1940090次