原理及代码讲解链接: https://blog.csdn.net/qq_44394952/article/details/122587306?spm=1001.2014.3001.5502.
主函数main()
int main()
{
int mm = 2;
printf(" =========功能:将BMP格式图片转换为JPG格式=========\n");
while(mm != 1 )
{
printf("\n");
//输入文件名称
char BMP_filename[64];
char JPG_filename[64];
printf("输入要压缩的BMP格式的图片名称:");
scanf("%s", BMP_filename);
printf("输入压缩完成后JPG格式的图片名称:");
scanf("%s", JPG_filename);
bmp(BMP_filename);//读入bmp信息
init_JPG_and_writ(JPG_filename);//初始化JPG格式并写入
code_all(); //综合变换并写入
printf("\n");
printf("输入'1'退出,输入任意数字继续:");
scanf("%d", &mm);
}
return 0;
}
读入BMP,逆序转换,填充
void bmp(char *bmp_name)
{
unsigned short int x8, y8; //拓展长度
signed short int y2 , a = 0; //用于处理倒序
unsigned char fillbytes; //可被4整除
colorRGB lastcolor;
unsigned short int column, nrline, line_up, line_down;
unsigned char TOPBUF[256]; //存取头部信息
colorRGB *tmpline; //用于交换
FILE *fp_bmp = fopen(bmp_name, "rb");//打开文件
if(fp_bmp == NULL)
{
printf("文件打开失败!");
exit(0);
}
//读取文件头部信息
fread(TOPBUF, 1, 54, fp_bmp);
if((TOPBUF[0]!='B')||(TOPBUF[1]!='M'))
{
printf("文件不是BMP格式!");
exit(0);
}
//图片长和宽
ximage = (unsigned short int)TOPBUF[19]*256 + TOPBUF[18];//图片长度和宽度
y2 = (short int)TOPBUF[23]*256 + TOPBUF[22];
yimage = y2;
//长度负值处理
if(y2 <= 0)
{
a = 1;
yimage = -y2;
}
SOF0info.width = ximage;
SOF0info.height = yimage;
if(ximage%8!=0)
x8 = (ximage/8)*8+8;
else
x8 = ximage;
if(yimage%8!=0)
y8 = (yimage/8)*8+8;
else
y8 = yimage;
//建立并存储,填充每一行,转换为RGB
RGB_buf = (colorRGB *)(malloc(3*x8*y8));
if(RGB_buf == NULL)
{
printf("存储创建失败!");
exit(0);
}
//处理32位
if(TOPBUF[28] == 32)
{
RGBa_buf = (colorRGBa *)(malloc(4*x8*y8));
if(RGBa_buf == NULL)
{
printf("存储创建失败!");
exit(0);
}
for(nrline = 0; nrline < yimage; nrline++)
{
fread(RGBa_buf+nrline*x8,1,ximage*4,fp_bmp);
memcpy(&lastcolor,RGBa_buf+nrline*x8+ximage-1,4);
for(column=ximage;column<x8;column++)
memcpy(RGBa_buf+nrline*x8+column, &lastcolor, 4);
}
for(unsigned long int n = 0; n < x8*yimage; ++n)
{
//转换为RGB
RGB_buf[n].B = RGBa_buf[n].B;
RGB_buf[n].G = RGBa_buf[n].G;
RGB_buf[n].R = RGBa_buf[n].R;
}
}
//处理24位
else if(TOPBUF[28] == 24)
{
//判断有无填充
if(ximage%4!=0)
fillbytes = 4 - (ximage%4);
else
fillbytes = 0;
for(nrline = 0; nrline < yimage; nrline++)
{
fread(RGB_buf+nrline*x8, 1, ximage*3, fp_bmp);
fread(TOPBUF, 1, fillbytes, fp_bmp);
memcpy(&lastcolor, RGB_buf+nrline*x8+ximage-1, 3);
for(column = ximage; column<x8; column++)
memcpy(RGB_buf+nrline*x8+column, &lastcolor, 3);
}
}
else
{
printf("信息错误!");
exit(0);
}
ximage = x8;
tmpline = (colorRGB *)malloc(ximage*8);
if(tmpline == NULL)
{
printf("存储创建失败!");
exit(0);
}
//是否需要逆序处理
if(a == 0)
{
for(line_up = yimage-1, line_down = 0;line_up>line_down; line_up--,line_down++)
{
memcpy(tmpline, RGB_buf+line_up*ximage, ximage*3);
memcpy(RGB_buf+line_up*ximage, RGB_buf+line_down*ximage, ximage*3);
memcpy(RGB_buf+line_down*ximage, tmpline, ximage*3);
}
}
//填充行
memcpy(tmpline, RGB_buf+(yimage-1)*ximage, ximage*3);
for(nrline = yimage; nrline < y8; nrline++)
memcpy(RGB_buf+nrline*ximage, tmpline, ximage*3);
yimage = y8;
free(tmpline);
fclose(fp_bmp);
}
初始化JPG以及写入
void init_JPG_and_writ(char *JPG_filename)
{
fp_jpg = fopen(JPG_filename, "wb");//打开jpg文件
int i;
//初始化量化表
DQTinfo.marker=0xFFDB;
DQTinfo.length=132;
DQTinfo.QTYinfo=0;
DQTinfo.QTCbinfo=1;
for(i = 0; i<64; ++i)
{
DQTinfo.Ytable[i] = DQT_Y[i];
DQTinfo.Cbtable[i] = DQT_C[i];
}
//初始化huffman表
DHTinfo.marker = 0xFFC4;
DHTinfo.length = 0x01A2;
DHTinfo.HTYDCinfo=0; //0号直流表
for (i=0;i<16;i++)
DHTinfo.YDC_codes[i]=dc_y_codes[i+1];
for (i=0;i<=11;i++)
DHTinfo.YDC_values[i]=dc_y_values[i];
DHTinfo.HTYACinfo=0x10; //0号交流表
for (i=0;i<16;i++)
DHTinfo.YAC_codes[i]=ac_y_codes[i+1];
for (i=0;i<=161;i++)
DHTinfo.YAC_values[i]=ac_y_values[i];
DHTinfo.HTCbDCinfo=1; //1号直流表
for (i=0;i<16;i++)
DHTinfo.CbDC_codes[i]=dc_cb_codes[i+1];
for (i=0;i<=11;i++)
DHTinfo.CbDC_values[i]=dc_cb_values[i];
DHTinfo.HTCbACinfo=0x11; //1号交流表
for (i=0;i<16;i++)
DHTinfo.CbAC_codes[i]=ac_cb_codes[i+1];
for (i=0;i<=161;i++)
DHTinfo.CbAC_values[i]=ac_cb_values[i];
writetop(); //写入文件头
}
写入文件头
void writetop()
{
unsigned char i;
//1.SOI
writeword(0xFFD8)
//2.APP0
writeword(APP0info.marker);
writeword(APP0info.length);
writebyte('J');
writebyte('F');
writebyte('I');
writebyte('F');
writebyte(0);
writebyte(APP0info.versionhi);
writebyte(APP0info.versionlo);
writebyte(APP0info.xyunits);
writeword(APP0info.xdensity);
writeword(APP0info.ydensity);
writebyte(APP0info.thumbnwidth);
writebyte(APP0info.thumbnheight);
//3.DQT
writeword(DQTinfo.marker);
writeword(DQTinfo.length);
writebyte(DQTinfo.QTYinfo);
for (i=0;i<64;i++)
writebyte(DQTinfo.Ytable[i]);
writebyte(DQTinfo.QTCbinfo);
for (i=0;i<64;i++)
writebyte(DQTinfo.Cbtable[i]);
//4.SOF0
writeword(SOF0info.marker);
writeword(SOF0info.length);
writebyte(SOF0info.precision);
writeword(SOF0info.height);
writeword(SOF0info.width);
writebyte(SOF0info.nrofcomponents);
writebyte(SOF0info.IdY);
writebyte(SOF0info.HVY);
writebyte(SOF0info.QTY);
writebyte(SOF0info.IdCb);
writebyte(SOF0info.HVCb);
writebyte(SOF0info.QTCb);
writebyte(SOF0info.IdCr);
writebyte(SOF0info.HVCr);
writebyte(SOF0info.QTCr);
//5.DHT
writeword(DHTinfo.marker);
writeword(DHTinfo.length);
writebyte(DHTinfo.HTYDCinfo);
for (i=0;i<16;i++)
writebyte(DHTinfo.YDC_codes[i]);
for (i=0;i<=11;i++)
writebyte(DHTinfo.YDC_values[i]);
writebyte(DHTinfo.HTYACinfo);
for (i=0;i<16;i++)
writebyte(DHTinfo.YAC_codes[i]);
for (i=0;i<=161;i++)
writebyte(DHTinfo.YAC_values[i]);
writebyte(DHTinfo.HTCbDCinfo);
for (i=0;i<16;i++)
writebyte(DHTinfo.CbDC_codes[i]);
for (i=0;i<=11;i++)
writebyte(DHTinfo.CbDC_values[i]);
writebyte(DHTinfo.HTCbACinfo);
for (i=0;i<16;i++)
writebyte(DHTinfo.CbAC_codes[i]);
for (i=0;i<=161;i++)
writebyte(DHTinfo.CbAC_values[i]);
//6.SOS
writeword(SOSinfo.marker);
writeword(SOSinfo.length);
writebyte(SOSinfo.nrofcomponents);
writebyte(SOSinfo.IdY);
writebyte(SOSinfo.HTY);
writebyte(SOSinfo.IdCb);
writebyte(SOSinfo.HTCb);
writebyte(SOSinfo.IdCr);
writebyte(SOSinfo.HTCr);
writebyte(SOSinfo.Ss);
writebyte(SOSinfo.Se);
writebyte(SOSinfo.Bf);
}
综合变换并写入
void code_all()
{
//huffman编码表
bitstring YDC[12];
bitstring CbDC[12];
bitstring YAC[256];
bitstring CbAC[256];
//计算各项的huffman表
huffman_code(dc_y_codes, dc_y_values, YDC);
huffman_code(dc_cb_codes, dc_cb_values, CbDC);
huffman_code(ac_y_codes, ac_y_values, YAC);
huffman_code(ac_cb_codes, ac_cb_values, CbAC);
//二进制长度以及编码
leng_and_numbercode();
bitstring fillbit;
signed short int DCY = 0, DCCb = 0, DCCr = 0;//直流系数
unsigned short int x,y;
//8*8一组进行处理
for(y = 0; y< yimage; y+=8)
for(x = 0; x<ximage; x+=8)
{
//printf("1"); //测试
RGBtoYCbCr(x,y);//RGB->YCbCr
fdct_and_quan(YDU,DQTinfo.Ytable);//离散余弦和量化,z型编码
code_and_write(&DCY,YDC,YAC);//编码并写入
fdct_and_quan(CbDU,DQTinfo.Cbtable);
code_and_write(&DCCb,CbDC,CbAC);
fdct_and_quan(CrDU,DQTinfo.Cbtable);
code_and_write(&DCCr,CbDC,CbAC);
//printf("2");
}
//尾部填充0并写入尾部
if(bytepos > 0)
{
fillbit.length = bytepos;
fillbit.value = 0;
writefile(fillbit);
}
writeword(0xffd9);//EOI
//释放空间
free(RGB_buf);
free(RGBa_buf);
fclose(fp_jpg);
}
计算各个表的huffman编码
void huffman_code(unsigned char *codes, unsigned char *values, bitstring *HT)
{
unsigned char k, j;
unsigned char pos = 0;
unsigned short int codevalue = 0;
for(k = 1; k<=16; ++k)
{
for(j = 1;j<=codes[k]; ++j)
{
HT[values[pos]].value = codevalue; //编码值
HT[values[pos]].length = k; //长度
pos ++;
codevalue++;
}
codevalue *= 2;
}
}
二进制长度以及编码
void leng_and_numbercode()
{
signed long int n;
signed long int one = 1, two = 2;
unsigned char leng;
//开辟空间
code_u = (bitstring *)malloc(65535*sizeof(bitstring));
if(code_u == NULL)
{
printf("存储空间开辟失败");
exit(0);
}
code_d = code_u + 32767;
for(leng = 1; leng <= 15; ++leng)
{
for(n = one; n<two; ++n)
{
code_d[n].length = leng;
code_d[n].value = (unsigned short int)n;
}
for(n = -(two - 1); n<=-one; ++n)
{
code_d[n].length = leng;
code_d[n].value = (unsigned short int)(two-1+n);
}
two<<=1;
one<<=1;
}
}
RGB->YCbCr
void RGBtoYCbCr(unsigned short int x1, unsigned short int y1)
{
unsigned char x,y;
unsigned char pos=0;
unsigned long location;
unsigned char R,G,B;
location=y1*ximage+x1;
for (y=0;y<8;y++)
{
for (x=0;x<8;x++)
{
R=RGB_buf[location].R;
G=RGB_buf[location].G;
B=RGB_buf[location].B;
YDU[pos]=(signed char)(((signed long int)(65536*0.299+0.5)*R+(signed long int)(65536*0.587+0.5)*G+(signed long int)(65536*0.114+0.5)*B)>>16)-128;
CbDU[pos]=(signed char)(((signed long int)(65536*-0.16874+0.5)*R+(signed long int)(65536*-0.33726+0.5)*G+(signed long int)(65536*0.5+0.5)*B)>>16);
CrDU[pos]=(signed char)(((signed long int)(65536*0.5+0.5)*R+(signed long int)(65536*-0.41869+0.5)*G+(signed long int)(65536*-0.08131+0.5)*B)>>16);
location++;pos++;
}
location+=ximage-8;
}
}
离散余弦变换和量化,z型编码
void fdct_and_quan(signed char *data, unsigned char *table)
{
float temp;
signed short int D1[64];
signed char mdata[8][8];
unsigned char i,j;
//离散余弦变换
for(i = 0; i<8; ++i)
for(j = 0;j<8; ++j)
mdata[i][j] = data[8*i+j];
DCT(mdata, table, D1);
//z型编码
for (i = 0; i <= 63; i++)
D2[z[i]] = D1[i];
}
离散余弦变化具体实现以及量化
void DCT(signed char data[8][8], unsigned char *fdtbl, signed short int *outdata)
{
float output[8][8], temp;
double ALPHA, BETA;
short u = 0;
short v = 0;
short i = 0;
short j = 0;
for(u = 0; u < 8; u++)
{
for(v = 0; v < 8; v++)
{
if(u == 0)
ALPHA = sqrt(1.0 / 8);
else
ALPHA = sqrt(2.0 / 8);
if(v == 0)
BETA = sqrt(1.0 / 8);
else
BETA = sqrt(2.0 / 8);
float tmp = 0.0;
for(i = 0; i < 8; i++)
{
for(j = 0; j < 8; j++)
{
tmp += data[i][j] * cos((2*i+1)*u*PI/(2.0 * 8)) * cos((2*j+1)*v*PI/(2.0 * 8));
}
}
output[u][v] = ALPHA * BETA * tmp;
}
}
// 量化
for (i = 0; i < 8; i++)
for(j = 0; j < 8; j++)
{
temp = output[i][j] / (float)((double)fdtbl[z[i*8+j]]);
outdata[i*8+j] = (signed short int) ((signed short int)(temp + 16384.5)-16384);
}
}
编码并写入
void code_and_write(signed short int *DC, bitstring *DCtable, bitstring *ACtable)
{
signed short int diff;
unsigned char endpos, startpos, i = 1, nz;
diff = D2[0]-*DC; //差值
*DC = D2[0];
//写入直流值
if(diff == 0)
writefile(DCtable[0]); //写入0的huffman编码
else
{
writefile(DCtable[code_d[diff].length]);//写入diff长度的huffman编码
writefile(code_d[diff]); //写入二进制编码
}
//写入交流值
for(endpos = 63; (endpos > 0) && (D2[endpos] == 0); --endpos);
if(endpos == 0)
{
writefile(ACtable[0x00]);
return ;
}
while(i <= endpos)
{
startpos = i;
for(; (D2[i] == 0) && (i <= endpos); ++i);
nz = i - startpos;
for(;nz >= 16; nz -= 16)//长度大于16需要分多块
writefile(ACtable[0xf0]);
writefile(ACtable[nz*16+code_d[D2[i]].length]);
writefile(code_d[D2[i]]);
++i;
}
if(endpos != 63)
writefile(ACtable[0x00]); //EOB
}
写入具体实现
void writefile(bitstring a)
{
unsigned short int values = a.value;
signed char leng_a=a.length;
while(leng_a > 0)
{
if(values & mark[leng_a-1]) //判断对应位置是否为1
bytecode |= mark[bytepos-1];//当前最高位至1
leng_a--;
bytepos--;
if(bytepos <= 0)
{
if(bytecode == 0xff)
{
writebyte(0xff);
writebyte(0x00);//说明ff不是段标志
}
else
writebyte(bytecode);
bytecode = 0;
bytepos = 8;
}
}
}
定义结构体等等
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
//BMP像素结构体
typedef struct {
unsigned char B,G,R;
}colorRGB;
typedef struct{
unsigned char B,G,R,a;
}colorRGBa;
typedef struct{
unsigned char length;
unsigned short int value;
}bitstring;
#define PI 3.1415926
//写入文件操作
#define writebyte(b) fputc((b), fp_jpg)
#define writeword(w) writebyte((w)/256);writebyte((w)%256);
colorRGB *RGB_buf; // 24位
colorRGBa *RGBa_buf; // 32位
signed short int ximage, yimage; //图片的长和宽
FILE *fp_jpg; //打开jpg文件
//二进制编码
static bitstring *code_u;
static bitstring *code_d; //长度以及编码
//存储YCbCr
static signed char YDU[64];
static signed char CbDU[64];
static signed char CrDU[64];
static signed short int D2[64];//存储z型编码后的值
static unsigned char bytecode = 0;
static signed char bytepos = 8;
//JPG头SOI1
//图像识别信息2
static struct APP0
{
unsigned short int marker; //段标识和类型FFE0
unsigned short int length; // 段长度 16
unsigned char JFIFsignature[5]; // 存储ASCII码 "JFIF",'\0'
unsigned char versionhi; // 主版本号1
unsigned char versionlo; // 次版本号1
unsigned char xyunits; // 密度单位 0(无单位)
unsigned short int xdensity; // 水平方向的密度 1
unsigned short int ydensity; // 垂直方向的密度 1
unsigned char thumbnwidth; // 略缩图水平像素数目0
unsigned char thumbnheight; // 略缩图垂直像素数目0
}APP0info={ 0xFFE0,16,'J','F','I','F',0,1,1,0,1,1,0,0};
//定义量化表3
static struct DQT {
unsigned short int marker; // 段标识和类型 0xFFDB
unsigned short int length; // 段长度
unsigned char QTYinfo; // 亮度QT值 00
unsigned char Ytable[64];//内容
unsigned char QTCbinfo; // 色度QT值 01
unsigned char Cbtable[64];
} DQTinfo;
//图像基本信息SOF0 4
static struct SOF0 {
unsigned short int marker; //段标识和类型 0xFFC0
unsigned short int length; // 段长度 17
unsigned char precision ;// 每个样本的位数
unsigned short int height ; //图片高度
unsigned short int width; //图片宽度
unsigned char nrofcomponents;//组件数量 3
unsigned char IdY; // 亮度= 1
unsigned char HVY; // 采样系数 高位标识水平采样系数,低位表示垂直采样系数
unsigned char QTY; // 量化表号 0
unsigned char IdCb; // 红色分量= 2
unsigned char HVCb;
unsigned char QTCb; // 1
unsigned char IdCr; // 蓝色分量= 3
unsigned char HVCr;
unsigned char QTCr; // Normally equal to QTCb = 1
} SOF0info = { 0xFFC0,17,8,0,0,3,1,0x11,0,2,0x11,1,3,0x11,1};
//定义huffman表 5
static struct DHT {
unsigned short int marker; //段标识和类型 0xFFC4
unsigned short int length; //段长度 19+n+....
unsigned char HTYDCinfo; // 低4位HT号 第5位HT类型 高3位为0
unsigned char YDC_codes[16]; //HT位表
unsigned char YDC_values[12];// HT值表
unsigned char HTYACinfo; // = 0x10
unsigned char YAC_codes[16];
unsigned char YAC_values[162];
unsigned char HTCbDCinfo; // = 1
unsigned char CbDC_codes[16];
unsigned char CbDC_values[12];
unsigned char HTCbACinfo; // = 0x11
unsigned char CbAC_codes[16];
unsigned char CbAC_values[162];
} DHTinfo;
//扫描行开始 6
static struct SOS {
unsigned short int marker; //段标识和类型 0xFFDA
unsigned short int length; //长度 12
unsigned char nrofcomponents; // 扫描行内组件数量 通常为3
unsigned char IdY; //1
unsigned char HTY; //低4位是AC表号,高4位是DC表号
unsigned char IdCb; //2
unsigned char HTCb; //0x11
unsigned char IdCr; //3
unsigned char HTCr; //0x11
unsigned char Ss,Se,Bf; // not interesting, they should be 0,63,0
} SOSinfo={ 0xFFDA,12,3,1,0,2,0x11,3,0x11,0,0x3F,0};
//亮度量化表
static unsigned char DQT_Y[64] = {
0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07,
0x07, 0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14,
0x0d, 0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13,
0x0f, 0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a,
0x1c, 0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22,
0x2c, 0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c,
0x30, 0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39,
0x3d, 0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32
};
//色差量化表
static unsigned char DQT_C[64] = {
0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0d,
0x0d, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32
};
//标准huffman表
static unsigned char dc_y_codes[17]={ 0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};
static unsigned char dc_y_values[12]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
static unsigned char dc_cb_codes[17]={ 0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
static unsigned char dc_cb_values[12]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
static unsigned char ac_y_codes[17]={ 0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d };
static unsigned char ac_y_values[162]= {
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
static unsigned char ac_cb_codes[17]={ 0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
static unsigned char ac_cb_values[162]={
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
0xf9, 0xfa };
//z型编码
static unsigned char z[64]={ 0, 1, 5, 6,14,15,27,28,
2, 4, 7,13,16,26,29,42,
3, 8,12,17,25,30,41,43,
9,11,18,24,31,40,44,53,
10,19,23,32,39,45,52,54,
20,22,33,38,46,51,55,60,
21,34,37,47,50,56,59,61,
35,36,48,49,57,58,62,63 };
//按位取值表
static unsigned short int mark[16]={ 1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};