1.    实验说明
前提:
JPEG的图像数据用Pspad16进制打开为一大堆16进制数据,这对数据实际分为两大部分,Marker(标记0x FFxx)与数据.其中标记为2个byte.
根据上课理解以及课后阅读规格书以及实际读取,归纳出常用的Marker有这几种:SOI,APP0,DQT,SOF0,DHT,EOI等
下面一边对JPEG数据解读一边解释相关Marker意义以及数据的读取.
例图:
使用Pspad打开图像所得16进制数据截图如下:   
2. 基本Marker介绍
a.       FFD8:SOI(Start of Image)
表示:为图像的开始
b.       FFE0:APP0
表示:应用程序的保留标记/数据
长度:之后紧接着的2个byte为APP0段的数据长度(从长度开始包括长度的2个byte)
l  这里由于我们不关注APP0的信息,因此直接读取长度后根据长度跳过此段.
长度:0010 + 0003(当前位置) = 0013
直接找到0013的位置.继续读取
c.       FFDB:DQT (Define Quantization Table)
表示:定义量化表
内容:
①   长度
  两个byte紧接着FFDB,表示定义量化表的长度(包括自身)
②   量化表
a)       精度 & 量化表ID  : 占一个byte
精度: 前四位,两个选择,0代表精度为8位,1代表16位.
量化表ID: 后四位, 取值为0~3
b)       表内容:占 64*(精度+1)个字节
l  可以看到例图中有两个FFDB Marker,读取内容具体在程式解释时介绍.
同样地跳过量化表的内容之后,读到了009D的位置,接下来就看到FFC0的Marker
d.       FFC0:SOF0 (Start of Frame)
表示:帧图像开始 
  内容:
①   长度 
2个byte接近着Marker之后表示本段的长度(包括自身)  
②   精度  
1个byte,每个数据样本的位数
③   图像高度 
2个byte,表示图像高度(单位:像素)
④   图像宽度
2个byte,表示图像宽度(单位:像素)
⑤   颜色分量数
1个byte,只有 3个数值可选
a)       1:灰度图 
b)       3:YcbCr或者 YIQ
c)       4:CMYK  
⑥   颜色分量信息
长度:颜色分量数×3 byte
a)         颜色分量ID, 长1 byte
b)         水平/垂直采样因子
1个byte
高 4位:水平采样因子; 低4位:垂直采样因子  
c)         量化表
1个byte,表示当前分量使用的量化表的 ID
l  照着说明读取本例图的数据可得:
FFC0 0011 08 0122 01B6 03 01 11 00 02 11 01 03 11 01
0011: 数据长度为17
08:   每个数据样本的位数为8位
0122: 图像高度为0x0122 = 290px
01B6:  图像宽度为 438px
03:颜色分量数为3:YCrCb
01 11 00:01分量:Y ; 水平垂直采样1, 1; 量化表为0
02 11 01:02分量:Cr; 水平垂直采样1, 1; 量化表为1
03 11 01:03分量:Cb; 水平垂直采样1, 1; 量化表为1
FFC0段完了之后读取数据,读到FFC4
e.       FFC4:DHT(Define Huffman Table)
表示:定义哈夫曼表
内容:
①   长度
2个byte紧接着Marker表示数据的长度(包括自身)
②   哈夫曼表
a)       哈夫曼表类型  与  哈夫曼表ID
长度:1个byte
类型:前四位, 0为DC直流表, 1为AC交流表
表ID:第四位.
b)       各个编码长度的数量
长度:16个byte
具体: L1, L2, L3, L4, L5, L6, L7, L8, L9, L10, L11, L12, L13, L14, L15, L16
表示:  编码长度为1的有L1个;
       编码长度为2的有L2个;
       编码长度为3的有L3个……
c)       编码内容
长度: Length = (L1+L2+…+L16) 个byte
表示: DC为对应编码的顺序/Category/权值
                                AC为对应编码的Run/Size
具体:  L1个:V1-0, V1-1…
              L2个:V2-0, V2-1…
              L16个:V16-0,V16-1…
l  可以看到例图中有四个FFDB Marker,读取内容具体在程式解释时介绍.
同样地跳过哈夫曼表的内容之后,读到了0180的位置,接下来就看到FFDA的Marker
f.        FFDA:SOS(Start of Scan)
①   长度
2个byte(但包括自身)
②   颜色分量数
1个byte  (与SOF中的值类似)值为三种 
a)       1:灰度图
b)       3:YCbCr或 YIQ
c)       4:CMYK
③   颜色分量信息
长度:颜色分量数×3 byte
a)         颜色分量ID, 长1 byte
b)         直流/交流系数表号,长1 byte 
高4位:直流分量使用的哈夫曼树编号
              低4位:交流分量使用的哈夫曼树编号
④   压缩图像数据
        a)谱选择开始   1字节  固定值 0x00
        b)谱选择结束   1字节  固定值 0x3F
        c)谱选择       1字节  在基本 JPEG中总为 00
l  照着说明读取例图数据可得:
FFDA  000C 03 01 00  02 11  03 11  00 3F 00
000c: 长度为12
03:   颜色分量数 3: YCbCr
01 00: 颜色分量01(Y) 直流使用0号,交流使用0号
02 11: 颜色分量02(Cr) 直流使用1号,交流使用1号
03 11: 颜色分量03(Cb) 直流使用1号,交流使用1号
l  本段结束后,紧接着就是真正的图像信息了.图像信息直至遇到一个标记代码就自动结束,一般就是以 EOI 标记表示结束.
l  真正的图像压缩信息分析于后面解码时解释
g.       FFD9:EOI(End of Image)
表示图像结束
3.    程序解码分析:
a.       程序界面
界面设计四个tabsheet分开显示读取分析到的数据以及一个open按钮打开图像文件
b.       程序设计
①   文件读取
使用FILE型的指针 FILE *fp 打开目标图片.
对于fp具体使用到的函数有:
l  fp = fopen(路径, 方式);
l  fseek()
原型是int fseek(FILE *stream, long offset, int whence);如果成功返回0,参数offset是移动的字符数,whence是移动的基准,取值是符号常量.
SEEK_SET 0 文件开头
SEEK_CUR 1 当前读写的位置
SEEK_END 2 文件尾部
l  fread()
原型是size_t fread(void *ptr, size_t size, size_t n, FILE *stream);参数ptr是保存读取的数据,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是读取的块数,如果成功,返回实际读取的块数(不是字节数)
l  feof(fp)
判断是否到达文件尾,是则返回true,否则false
l  fclose()
fclose()的功能就是关闭用fopen()打开的文件,其原型是:int fclose(FILE *fp);如果成功,返回0,失败返回EOF.
②   相关Marker位置读取
先用一个函数来全盘扫描文件,寻找FFDB以及FFC4的Maker位置并储存于数组中.
对应判断则用Marker的10进制值来判断.如FF为255,DB为219.
③   量化表读取分析
根据FFDB相关说明,读取了表的精度以及ID之后,读取64个字节存于数组中则可.
程序先用一维数组储存ZigZag扫描索引,再用另一个一维数组读取64个数据,然后用ZigZag索引读取该一维数组并显示于文本中则可.
结果量化表为:
④  哈夫曼表读取分析
根据FFC4相关说明,读取了哈夫曼表的类型以及ID之后,读取L1~L16(Ln)之后,先产生Ln个n,继续读取Vn-m值(权值),按顺序赋值给刚刚产生的长度顺序(若是AC表,此处的Vn-m值则包含两个信息为 Run/Size,切分则可),同时产生相应编码.
l  编码产生算法如下:
每个Huffman表第一个编码值为0,下一个编码值的产生为:与前一编码相同长度的则按顺序在前一个编码值加一,不同长度的则=(上一个编码值+1)*2,产生新的编码值.再用相应长度表示该值的二进制值则可.
l  字节值与表类型
| 
00 | 
DC /直流0号表 | 
| 
01 | 
DC /直流1号表 | 
| 
10 | 
AC /交流0号表 | 
| 
11 | 
AC /交流1号表 | 
l  哈夫曼表获取程序
| 
void TForm1::getHuffmanTable(unsigned char *LenList, vector<int> Value, bool isAC) 
{ 
         //五个空格 
   this->Edittext->Text = this->Edittext->Text+ "\n序号     长度     值     二进制     权值\n"; 
   //传进了的Value为权值,values 
   vector<int> Code; 
   int rankNow = 0; 
   int ValueNow = 0; 
   if(!isAC) 
   { 
           for(int i = 0 ; i < 16; i ++) 
           { 
                    for(int j = 0 ; j <LenList[i]; j ++) 
                    { 
                              this->Edittext->Text = this->Edittext->Text+ AnsiString(rankNow) + "            ";//序号 
                              this->Edittext->Text = this->Edittext->Text+ AnsiString((i+1)) + "          ";//长度 
                              Code.push_back(ValueNow); 
                              this->Edittext->Text = this->Edittext->Text+ AnsiString(ValueNow) + "          ";//值 
                              showBinary(ValueNow, (i+1), 0); 
                              this->Edittext->Text = this->Edittext->Text+ AnsiString(Value[rankNow++]) + "       \n"; 
                             ValueNow ++; 
                    } 
                  ValueNow = ValueNow<<1; 
           } 
   } 
   else 
   { 
      int R,S; 
           for(int i = 0 ; i < 16; i ++) 
           { 
                    for(int j = 0 ; j <LenList[i]; j ++) 
                    { 
                              this->Edittext->Text = this->Edittext->Text+ AnsiString(rankNow) + "            ";//序号 
                              this->Edittext->Text = this->Edittext->Text+ AnsiString((i+1)) + "          ";//长度 
                              Code.push_back(ValueNow); 
                              this->Edittext->Text = this->Edittext->Text+ AnsiString(ValueNow) + "          ";//值 
                              showBinary(ValueNow, (i+1), 0); 
                              R = Value[rankNow]/16; 
                              S = Value[rankNow]%16; 
                              this->Edittext->Text = this->Edittext->Text+   AnsiString(R)+"/"+AnsiString(S)+ "       \n"; 
              rankNow++; 
                              ValueNow ++; 
                    } 
                  ValueNow = ValueNow<<1; 
           } 
   } 
} | 
l  按以上顺序产生哈夫曼表如下:
          TcTh: 00  DC /直流0号表        Y
| 
序号        长度        值        二进制      权值 
0            2          0           00         5       
1            3          2           010        3       
2            3          3           011        4       
3            3          4           100        6       
4            3          5           101        7       
5            4          12          1100       1       
6            4          13          1101       2       
7            4          14          1110       8       
8            5          30          11110      0       
9            6          62          111110     9       | 
                   TcTh: 10      AC /交流0号表      Y
| 
序号        长度          值             二进制              权值 
0            2            0                00                0/1                            
1            3            2                010               0/2       
2            3            3                011               0/3       
3            3            4                100               0/4       
4            4            10              1010               0/0       
5            4            11              1011               0/5        
6            4            12              1100               1/1       
7            5            26              11010              0/6       
8            5            27              11011              1/2       
9            5            28              11100               2/1       
10            6          58               111010              3/1       
11            7          118             1110110              0/7       
12            7          119             1110111              1/3        
13            7          120             1111000              2/2       
14            7          121             1111001              4/1       
15            7          122             1111010              5/1       
16            7          123             1111011              6/1       
17            8          248             11111000             0/8       
18            8          249             11111001             1/4       
19            8          250             11111010             3/2       
20            8          251             11111011             7/1       
21            9          504             111111000            2/3       
22            9          505             111111001            4/2       
23            9          506             111111010            8/1       
24            10        1014            1111110110            1/5       
25            10        1015            1111110111            9/1       
26            10        1016            1111111000           10/1       
27            11        2034            11111110010           0/9       
28            11        2035            11111110011           1/6       
29            11        2036            11111110100           3/3       
30            11        2037            11111110101           5/2       
31            11        2038            11111110110           6/2       
32            11        2039            11111110111           11/1       
33            11        2040            11111111000           12/1       
34            11        2041            11111111001           13/1       
35            12        4084            111111110100          2/4       
36            12        4085            111111110101          4/3       
37            12        4086            111111110110          7/2       
38            12        4087            111111110111          11/3       
39            13        8176            1111111110000         1/7       
40            13        8177            1111111110001         2/6        
41            13        8178            1111111110010         3/4       
42            13        8179            1111111110011         7/3       
43            13        8180            1111111110100         8/2       
44            13        8181            1111111110101         11/4       
45            13        8182            1111111110110         14/1       
46            14        16366          11111111101110         2/5       
47            14        16367          11111111101111         2/7        
48            14        16368          11111111110000         4/4       
49            14        16369          11111111110001         4/5       
50            14        16370          11111111110010         5/3       
51            14        16371          11111111110011         6/3       
52            14        16372          11111111110100         6/4       
53            14        16373          11111111110101         7/4       
54            14        16374          11111111110110         7/5        
55            14        16375          11111111110111         7/6       
56            14        16376          11111111111000         8/4       
57            14        16377          11111111111001         10/4       
58            15        32756          111111111110100        3/5       
59            15        32757          111111111110101        3/6       
60            15        32758          111111111110110        3/8       
61            15        32759          111111111110111        4/6        
62            15        32760          111111111111000        5/4       
63            15        32761          111111111111001        5/5       
64            15        32762          111111111111010        5/6       
65            15        32763          111111111111011        6/5       
66            15        32764          111111111111100        10/3       
67            16        65530          1111111111111010       9/2       
68            16        65531          1111111111111011       10/2        
69            16        65532          1111111111111100       11/2       
70            16        65533          1111111111111101       15/0       
71            16        65534          1111111111111110       15/1       | 
                              TcTh: 01    DC /直流1号表   CbCr
| 
序号       长度         值        二进制         权值 
0            2          0          00              2       
1            2          1          01              3       
2            3          4          100             0       
3            3          5          101             4       
4            3          6          110             5       
5            4          14        1110             1       
6            5          30        11110            6       
7            6          62        111110           7       
8            7          126      1111110           8       | 
                            TcTh: 11      AC /交流1号表  CbCr
| 
序号        长度          值        二进制                     权值 
0             2           0              00                   0/0       
1             2           1              01                   0/1       
2             3           4              100                  0/2       
3             3           5              101                  0/3       
4             4           12             1100                 0/4       
5             4           13             1101                 1/1       
6             5           28             11100                1/2       
7             5           29             11101                2/1       
8             6           60             111100               3/1       
9             7           122            1111010              0/5       
10            7           123            1111011              1/3       
11            7           124            1111100              2/2       
12            7           125            1111101              4/1       
13            8           252            11111100             3/2       
14            9           506            111111010            1/4       
15            9           507            11111101             2/3       
16            9           508            111111100            5/1       
17            10          1018           1111111010           0/6       
18            10          1019           1111111011           3/3       
19            10          1020           1111111100           4/2       
20            11          2042           11111111010          1/5       
21            11          2043           11111111011          6/1       
22            11          2044           11111111100          8/1       
23            12          4090           111111111010         1/6       
24            12          4091           111111111011         7/1       
25            12          4092           111111111100         9/1       
26            13          8186           1111111111010        4/3       
27            13          8187           1111111111011        5/2       
28            13          8188           1111111111100        10/1       
29            13          8189           1111111111101        11/1       
30            14          16380          11111111111100       2/4       
31            14          16381          11111111111101       6/2       
32            14          16382          11111111111110       14/1       | 
⑤   图像压缩数据解压缩
图像压缩信息截图:
l  程序读出的16进制(每100个byte分开)
| 
      8 5 E 8 F D 5 1 0 A 4 6 8 5 B B 4 B B A A D 3 1 6 D 9 3 9 4 B 4 C 6 9 A F A 3 6 B 4 F 2 4 9 3 E 1 0 6 B C 0 D 9 5 4 A 1 6 6 C F A 5 5 5 1 8 D B 1 D 1 6 9 F 6 1 1 A 4 A D E F 7 6 7 D 6 4 5 3 3 1 2 1 A D 5 6 A 9 2 E 2 1 B 7 D B 4 0 2 A D 8 4 E 5 2 4 2 B E C 6 B B 9 7 3 7 2 8 6 8 C C 9 D 7 E C C 8 B 9 1 B 4 F 7 6 7 6 E 0 8 0 4 7 0 7 1 C 0 A F 3 A D 8 0 8 2 B 0 8 2 4 9 4 9 C 6 4 7 B 1 A 1 6 1 6 C 7 F   // 
2 E 0 A 6 5 D B 2 5 4 6 4 9 0 8 E F 9 A 5 B 6 4 A 8 7 0 0 2 9 2 4 6 7 F 8 D 1 D 7 1 E 5 3 5 2 2 6 B 4 B 4 5 0 D D 9 6 7 C 3 8 3 B D 8 F C 9 B D 2 8 5 E 1 8 B 9 D 9 E E 1 C A 2 1 3 6 D 0 4 2 5 B 5 E 4 9 2 4 F A E 6 B 7 7 3 E D E 5 1 8 C 4 B 3 8 D 5 F B 6 F 6 4 A 5 3 A 0 9 8 8 6 C 3 8 D C 6 7 1 6 D 3 2 A 3 B D 2 D 1 F 1 A 1 0 A F 5 0 0 D 6 6 4 2 C 3 4 9 C 9 C 8 7 1 6 A D 3 7 1 6 D 5 B D 6 7 7 3 E F   // 
3 A 4 A 9 6 F A F A A C D 4 9 3 D 8 A 7 B 4 5 A 3 A 7 A F 8 F B 1 6 6 8 E D A 1 4 4 7 7 4 9 2 9 1 8 E 4 5 5 6 5 3 D 9 9 F 7 4 3 B 0 D 3 7 A B 5 D D 8 D 8 7 0 2 0 8 3 D 4 9 1 5 1 F 6 2 5 2 D 2 3 7 9 7 3 6 3 D D 1 8 0 D 9 4 B 4 8 7 3 8 3 D E 0 4 8 C 8 F 6 A 3 A 9 F 7 D 9 C 6 0 4 9 9 6 3 7 1 D 6 C 8 6 5 6 C 2 D 4 0 E 7 3 9 D A 4 D 1 E 4 4 6 3 2 4 7 6 20 D 5 C B 7 A D 1 1 6 4 3 9 7 9 0 8 8 7 1 D 9 1 
//尾到02B0行处 | 
l  利用程序全部转为二进制数值后对二进制进行手工解码.
数值的译码表如下
                              AC((Run/Size) 的形式來描述,RS = binary 'RRRRSSSS')
| 
SSSS     AC   coefficients | 
| 
1        -1, 1 2 -3,-2, 2, 3 3 -7..-4, 4..7 4 -15..-8, 8..15 5 -31..-16, 16..31 6 -63..-32, 32..63 7 -127..-64, 64..127 8 -255..-128, 128..255 9 -511..-256, 256..511 10 -1023..-512, 512..1023 | 
| 
DC | 
| 
SSSS     DIFF   values | 
| 
0          0 1 -1, 1 2 -3,-2, 2, 3 3 -7..-4, 4..7 4 -15..-8, 8..15 5 -31..-16, 16..31 6 -63..-32, 32..63 7 -127..-64, 64..127 8 -255..-128, 128..255 9 -511..-256, 256..511 10 -1023..-512, 512..1023 11 -2047..-1024, 1024..2047 | 
l  由于整理的采样因子是1:1:1,则Y分量,Cb分量和Cr的分量的水平方向和垂直方向都是每一个像素采样1次.也就是图像的每一个像素都是采样点.
因此,对于整张图片来说,数据流的数据为:
[Y1,Cb1,Cr1], [Y2,Cb2,Cr2], [Y3,Cb3,Cr3], [Y4,Cb4,Cr4], [Y5,Cb5,Cr5]……
颜色分量单元内部综合运用了RLE行程编码和哈夫曼编码来压缩数据.每
个像素的数据流由两部分构成:编码和数值,并且两者基本以互相隔开方式出现(除非该编码的权值为零).具体读入单个颜色分量单元的步骤如下:
a)       从此颜色分量单元数据流的起点开始一位一位的读入,直到读入的编码与该分量直流哈夫曼树的某个码字(叶子结点)一致,然后用直流哈夫曼树查得该码字对应的权值.权值(共 8位)表示该直流分量数值的二进制位数,也就是接下来需要读入的位数.
b)       继续读入位数据,直到读入的编码与该分量交流哈夫曼树的某个码字(叶子结点)一致,然后用交流哈夫曼树查得该码字对应的权值.权值的高4位表示当前数值前面有多少个连续的零,低4位表示该交流分量数值的二进制位数,也就是接下来需要读入的位数.
c)       不断重复步骤 b,直到满足交流分量数据结束的条件.而结束条件有两个,只要满足其中一个即可:
读入码字的权值为零,表示往后的交流变量全部为零;
已经读入 63 个交流分量.
d)       各个数值的译码按照上面的两个译码表进行.
l  译码过程
    把所有的颜色分量单元按颜色分量(Y、Cr、Cb)分类.每一种颜色分量内,相邻的两个颜色分量单元的直流变量是以差分来编码的.也就是说,通过步骤 3解码出来的直流变量数值只是当前颜色分量单元的实际直流变量减去前一个颜色分量单元的实际直流变量.也就是说,当前直流变量要通过前一个颜色分量单元的实际(非解码)直流分量来校正: DCn=DCn-1+Diff
其中Diff为差分校正变量,也就是直接解码出来的直流系数.但如果当前颜色分量单元是第一个单元,则解码出来的直流数值就是真正的直流变量.
我的做法是先解码,直接解出diff,等绘制block时再算DCn=DCn-1+Diff.
l  译码
<mcu1> Y
1000 0101  111010 001111  11010 101000  100 0010     100 1000  11010 000101 
权=6         0/6 值=-63+15     0/6  值=40      0/4 值=2-15   0/4  8     0/6     5-63=-58
值=-63+11=-52     =-48                                                =-13
         [-52]                  [-48]           [40]                 [ -13]               [8]           [-58]
1011 10110  100 1011  1011 10101  010 11  010 01     100 0101  1011 01100  100 1110
0/5     22       0/4  11      0/5   21       0/2  3    0/2  1-3=-2  0/4  5-15   0/5   12-31     0/4  14
          [22]              [11]           [21 ]           [3]        [-2 ]            [-10]         [-19]         [14]
010 10  010 11  010 01  100 0110  100 1101  011 111  010 00  11011 01    011 010 
0/2  2    0/2   3   0/2  1-3   0/4  6-15   0/4   13     0/3  7     0/2  -3    1/2    1-3     0/3  2-7
          [2]         [ 3 ]      [-2]         [-9]         [13]         [7]          [-3]          [0,-2]      [ -5]
011 110  010  0100   1  00 1    001  1   1110  0001  000   0  0110  10
0/3  6      0/2  1-3  0/1  1  0/1  1   0/1 1           2/2    1-3  0/1 -1  0/1  1   0/0       
       [6]         [-2]         [1]     [1]        [1]          [0,0,-2]         [-1]     [1]     EOB
Cb
11  1100  0000  1101  1001  0101  0100  1010  0001  0110  0110  11  00  
权:6         1-63        0/3   4     0/3  2-7    0/2   2   0/2  -3  0/3   4     1/1     1   0/0
[-62]              [4]                 [-5]        [2]       [-3]       [4]         [0,1]    EOB
Cr
1111  1010  0101  0101  0101  0001  1000  1101  1011  0001  1101  000
权:7          74            0/3  2-7   0/2   1-3  0/2  1-3  0/3   5    0/2  1-3   1/1  -1  0/0
  [74]                [-5]          [-2]         [-2]          [5]          [-2]      [0,-1]     EOB
 由于部落格的文字排版一直出现问题(二进制编码排版对不齐以及保存文章出错),因此后续的解码以及作业心得如有需要可以点击 pdf文章 进入直接浏览pdf文章.










沒有留言:
張貼留言