此4张表是理论表,不是针对某张图片的特定表。如编码程序不统计生成某图片的专用霍夫曼表,应该也可用理论表代用编码。
1.亮度DC表
左边第一列是二进制位数,就是对此位数编码
中间一列是生成比特流的位数,右边是生成的比特流。
2.色度DC表
3.亮度AC表
4. 色度AC表
利用这4张表转换生成亮度,色度的DC,AC比特流
图3图4两张表是用jpeg文件头的形式显示的。
AC 表被编码的数值是两部分组成的,高4比特是0的个数 (a,b)对中的a,低4节为b的二进制位数。
两个AC表中的162个数就是两个输入参数组成的一个字节的值。
对于DC表,直接用if一一例举出现就行了。AC两张表输出都是162个数,这162个数的比特流从1位到16位都有。
看了AC两张表,最多的是16位的比特流。
AC表的输入为0的个数和二进制位数两个参数,输出为比特流和比特流宽度。
--------------------------------
亮度AC表:
2 位:2个 00(1) ,01(2)
3位:1 010(0),
4位:3 0110(4),0111(11), 1000(5)
5位:3 10010(12) ,10011(21),10100(31)
6位:2 101010(41), 101011(6)
7位:4 1011000(13),1011001(51), 1011010(61),1011011(7)
8位:3 10111000(22), 10111001(71), 10111010(14)
9位:5 101110110(32), 101110111(81), 101111000(91) ,101111001(A1), 101111010(8)
10位:5 1011110110(23), 1011110111(42),1011111000(b1), 1011111001(c1),1011111010(15)
11位:4 10111110110(52), 10111110111(d1), 10111111000(f0), 10111111001(24)
12位:4 101111110100(33), 101111110101(62), 101111110110(72),101111110111(82)
15位:1 101111111000000(9),
16位 :125 1011111110000010(0a),,,,,,,
共计162个
亮度AC转换:本想用查表法代码太长了,162个if语句。现还不包括16位的数据转换,准备换一种方法。DC可以用这种方法。
1. 亮度AC编码用正向程序
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <math.h>
int main(void) {
unsigned char i_0=0xf;
unsigned char i_len=0xa;
unsigned char len;
unsigned int o;
unsigned char zj=i_0*16+i_len; //合成一个字节
unsigned char ws[16]={0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};
unsigned char zh[162]={0x1, 0x2, 0x3, 0x0, 0x4, 0x11, 0x5,0x12,0x21,0x31,0x41,0x6, 0x13,0x51,0x61,0x7,
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,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
0xf9,0xfa
};
int cx_ws,cx_b;
unsigned char hfm[17][0x7d]={};
int t=0;
for(int a=0;a<16;a++){ //把要编码的162个数按位数分为16个数组,二位一组....16位一组
if(ws[a]==0){
continue;
}
for(int b=0;b<ws[a];b++){
hfm[a+1][b]=zh[t];
t++;
}
}
for(int a=0;a<16;a++){ //查询输入数的位数和在所在组的顺序,组内顺序从0开始
if(ws[a]==0){
continue;
}
for(int b=0;b<ws[a];b++){
if( hfm[a+1][b]==zj){
cx_ws=a+1; //得到输入数二进制位数,根据此数到相依位数的数组查询
cx_b=b; //输入数在按位数分组的数组中所在的位置,从0开始
break;
}
}
}
int o_js=0; //每一组的第一个数的值
if(cx_ws==2){
o_js=0;
}
if(cx_ws==3){
o_js=0b010;
}
if(cx_ws==4){
o_js=0b0110;
}
if(cx_ws==5){
o_js=0b10010;
}
if(cx_ws==6){
o_js=0b101010;
}
if(cx_ws==7){
o_js=0b1011000;
}
if(cx_ws==8){
o_js=0b10111000;
}
if(cx_ws==9){
o_js=0b101110110;
}
if(cx_ws==10){
o_js=0b1011110110;
}
if(cx_ws==11){
o_js=0b10111110110;
}
if(cx_ws==12){
o_js=0b101111110100;
}
if(cx_ws==15){
o_js=0b101111111000000;
}
if(cx_ws==16){
o_js=0b1011111110000010;
}
len=cx_ws;
o=o_js+cx_b;
printf("len:%d o:%d\n",len,o);
return 0;
}
2.亮度AC 解码程序
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <string.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <math.h>
int main(void) {
unsigned int i_bit=0b1011111110000011;
unsigned char i_len=16;
unsigned char len;
unsigned char o;
unsigned char ws[16]={0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};
unsigned char zh[162]={0x1, 0x2, 0x3, 0x0, 0x4, 0x11, 0x5,0x12,0x21,0x31,0x41,0x6, 0x13,0x51,0x61,0x7,
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,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,
0xf9,0xfa
};
unsigned char cx_ws,cx_b;
unsigned char hfm[17][0x7d]={};
int t=0;
for(int a=0;a<16;a++){
if(ws[a]==0){
continue;
}
for(int b=0;b<ws[a];b++){
hfm[a+1][b]=zh[t];
t++;
}
}
//---------------------------------------
cx_ws=i_len;
int o_js=0;
if(cx_ws==2){
o_js=0;
cx_b=i_bit-o_js;
}
if(cx_ws==3){
o_js=0b010;
cx_b=i_bit-o_js;
}
if(cx_ws==4){
o_js=0b0110;
cx_b=i_bit-o_js;
}
if(cx_ws==5){
o_js=0b10010;
cx_b=i_bit-o_js;
}
if(cx_ws==6){
o_js=0b101010;
cx_b=i_bit-o_js;
}
if(cx_ws==7){
o_js=0b1011000;
cx_b=i_bit-o_js;
}
if(cx_ws==8){
o_js=0b10111000;
cx_b=i_bit-o_js;
}
if(cx_ws==9){
o_js=0b101110110;
cx_b=i_bit-o_js;
}
if(cx_ws==10){
o_js=0b1011110110;
cx_b=i_bit-o_js;
}
if(cx_ws==11){
o_js=0b10111110110;
cx_b=i_bit-o_js;
}
if(cx_ws==12){
o_js=0b101111110100;
cx_b=i_bit-o_js;
}
if(cx_ws==15){
o_js=0b101111111000000;
cx_b=i_bit-o_js;
}
if(cx_ws==16){
o_js=0b1011111110000010;
cx_b=i_bit-o_js;
}
//-----------------------------------------
unsigned char o_zj=hfm[cx_ws][cx_b];
len=o_zj/16;
o=o_zj%16;
printf("%x %x",len,o);
return 0;
}