将BMP 格式图片转换为 JPEG 格式【c语言源码】

原理及代码讲解链接: 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};
    原文作者:居宝居宝要加油
    原文地址: https://blog.csdn.net/qq_44394952/article/details/122587475
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞