JPEG - 想法與實踐/頭部部分
JPEG 檔案的頭部部分被劃分為段,每個段以一個標記開始,標識該段。 通常,JPEG 檔案包含 7 個不同的標記。標記是一個位元組對,第一個位元組是 255,第二個位元組不同於 0 和 255。我們透過第二個位元組來標識一個標記。有兩個標記是獨立的(因此不開啟一個段):開啟檔案的標記 SOI(開始影像)= 216 和關閉檔案的標記 EOI(結束影像)= 217。(還有另一種獨立的標記,但它不在我們這裡討論的順序 DCT 模式中使用:它標誌著掃描的重啟,並由 0、1、...、7 中的一個數字索引:RST0、...、RST7(重啟)= 208、...、215)。其他標記開啟一個段,在這種情況下,接下來的兩個位元組(b1,b2)表示段的長度(包括這兩個位元組):l = b1 * 256 + b2。接下來的 l - 2 個位元組序列是該段的內容。以下是段的型別(用它們的標記標識)
- APP0、APP1、...、APP15(應用) 224-239
- COM(註釋) 254
- SOF(開始幀) 192-207,除了 196、200 和 204
- DHT(定義霍夫曼表) 196
- DQT(定義量化表) 219
- SOS(開始掃描) 218
(以及其他幾個在此處未使用的標記:DNL(定義行數 = 220)、DRI(定義重啟間隔 = 221)、DHP(定義分層漸進 = 222)、EXP(擴充套件參考分量 = 223)、DAC(定義算術編碼條件 = 204)、TEM(用於算術編碼中的 TEMporary 使用 = 1)以及一些保留標記:JPG(保留用於 JPeG 擴充套件 = 200、240、241、...、253)和 RES(REServed = 2、...、191))
前兩個 - APP 和 COM - 指定了在 JPEG 程式之外的內容。通常只存在一個 APP 段(即 APP0),它指定了實現。APP 段還可以包含有關相機型別和拍攝圖片時間的資訊。COM 可以說明用於建立檔案的程式、選擇的質量百分比等。
JPEG 程式的出發點是“圖片”,圖片可以定義為數字、數字對、數字三元組或數字四元組的(矩形)矩陣。也就是說,圖片是具有 1-4 之間的一個數字的長度的陣列的矩陣。灰度圖片是位元組矩陣。彩色圖片是 RGB 三元組(位元組)矩陣或 YCbCr 三元組(有符號位元組)矩陣。因此,圖片可以被認為是由一個或多個(最多四個)整數矩陣組成的,這樣的矩陣被稱為圖片的分量。每個分量都分配一個分量識別符號(位元組):例如,灰度圖片的(一個)分量為 0,彩色圖片的三個分量為 0、1 和 2。
圖片的尺寸、分量識別符號和分量的順序在幀段 SOF 中指定,以及如何處理分量之間的關係。由於顏色通常只在位置之間緩慢變化(而且我們不太擅長區分顏色的微小變化),對於兩個顏色分量,我們可以例如將圖片分成 2x2 畫素的方塊並取平均值,這樣我們就可以將這個方塊看作是一個畫素,從而處理四倍小的彩色圖片。我們也可以只限於兩個畫素,要麼水平排列,要麼垂直排列。每個分量的數字對 (Hi, Vi) 決定了如何掃描分量之間的關係。Hi 和 Vi 可以從 1 到 4(Hi 和 Vi 必須比較小:它們的乘積之和不能超過 10)。分別設 H 和 V 為最大的 Hi 和 Vi 值。這些最大值通常與 Y 分量相關聯,而 ((Hi, Vi) = (H, V)) 意味著畫素按原樣取值:水平樣本數與圖片的寬度相同,水平行數與圖片的高度相同。如果一個(顏色)分量的對為 (Hi, Vi),則水平線上的樣本數是 (Hi/H) 乘以寬度,取樣線的數量是 (Vi/V) 乘以高度,也就是說,收集了 (H/Hi)x(V/Vi) 畫素的小矩形(並被認為是一個畫素)。通常情況下,顏色分量的 (Hi, Vi) = (1, 1),而 Y 分量的 (Hi, Vi) = (1, 1) 或 (2, 1) 或 (1, 2) 或 (2, 2)。(Hi, Vi) = (2, 2) 意味著收集了四個顏色畫素,並且“這個”畫素與四個 Y 畫素組合在一起。由於圖片被劃分為 8x8 的方塊,這意味著 Y 分量的四個 8x8 方塊與顏色分量的一個 8x8 方塊組合在一起。四個 Y 方塊的編碼資料(編碼的 64 陣列)按通常的掃描順序寫入檔案:從左到右沿行,從上到下。接下來是兩個顏色分量的編碼資料(編碼的 64 陣列)。當只收集兩個畫素(水平或垂直)時,類似的過程。由所有分量和收集的 8x8 方塊產生的資料流的這一部分被稱為最小編碼單元(MCU)。
這張圖片展示了當收集四個 Y 分量 8x8 方塊時的繪製方式(畫素對畫素 - 並且按放大的比例) - 你要想象中間的四個 8x8 方塊,兩個(最上面的)已經繪製了,第三個正在繪製
-
繪製
以下圖片(佔用 3.2 Kb)下面的兩張圖片是這張圖片,每隔一條垂直線都繪製為黑色,但以不同的方式掃描:對於顏色分量,分別在垂直和水平方向上收集兩個畫素(即顏色分量的 (Hi, Vi) = (1, 1),而 Y 分量的 (Hi, Vi) = (1, 2) 和 (2, 1))。在第一張圖片(佔用 5.9 Kb)中,顏色是正確的,在第二張圖片(佔用 4.7 Kb)中,顏色是褪色的,因為它們與線的黑色混合在一起
-
原始
-
垂直子取樣
-
水平子取樣
幀段 SOF 由以下位元組組成:標記 (255, b),其中位元組 b 指定掃描模式。我們假設這裡 b = 192,表示基線順序 DCT 模式;然後是表示段長度的位元組對(包括這兩個位元組),這對位元組為 (0, 8 + 3 * 分量數);然後是一個表示顏色值位數的位元組,這裡設定為 8(表示顏色值為位元組),但在擴充套件模式中為 12;然後是一對位元組 (b1, b2) 表示圖片的高度 (= b1 * 256 + b2) 和一對位元組表示寬度;最後是一個表示分量數(1-4)的位元組,以及每個分量的以下位元組:分量識別符號(位元組)、Hi(½ 位元組)和 Vi(½ 位元組)(位元組 = Hi * 16 + Vi)以及量化表目標選擇器(位元組)。
這裡,顏色分量的對 (Hi, Vi) 為 (1, 1),而 Y 分量的 (Hi, Vi) 為 (1, 1)、(1, 2)、(2, 1) 或 (2, 2)。量化表目標選擇器是 0-3 之間的數字之一,例如,Y 分量為 0,顏色分量為 1。
通常,灰度圖片的檔案中會有兩個霍夫曼表段,彩色圖片中有四個:每個分量的 DC 和 AC 數字的編碼方式不同,Y 分量和兩個顏色分量的編碼方式也不同。在霍夫曼段中,資訊(在標記和表示長度的位元組對之後)以這種方式排列:如果霍夫曼表用於 DC 數字,則第一個半位元組為 0,如果用於 AC 數字,則為 1。下一個半位元組是霍夫曼表目標識別符號(0 或 1),例如,Y 分量為 0,顏色分量為 1(將在掃描段 SOS 中引用,在 SOS 中指定了霍夫曼表)。接下來的 16 個位元組序列是列表 BITS,它表示 i = 1、...、16 時長度為 i 的程式碼數量。然後是列表 HUFFVAL,它表示霍夫曼值:對於每個非零的程式碼長度,將有與該長度的程式碼數量相同的數值。如果我們將霍夫曼值的數量稱為 nhv,則段中的位元組數(包括表示長度的位元組對)為 19 + nhv。
量化表是一個 8x8 位元組矩陣,按之字形原則排序。通常情況下,Y 分量和顏色分量有不同的量化表。在 T.81 的附錄“示例和指南”中,你可以分別找到 Y 分量和顏色分量的以下內容
- 16 11 10 16 24 40 51 61
- 12 12 14 19 26 58 60 55
- 14 13 16 24 40 57 69 56
- 14 17 22 29 51 87 80 62
- 18 22 37 56 68 109 103 77
- 24 35 55 64 81 104 113 92
- 49 64 78 87 103 121 120 101
- 72 92 95 98 112 100 103 99
- 17 18 24 47 99 99 99 99
- 18 21 26 66 99 99 99 99
- 24 26 56 99 99 99 99 99
- 47 66 99 99 99 99 99 99
- 99 99 99 99 99 99 99 99
- 99 99 99 99 99 99 99 99
- 99 99 99 99 99 99 99 99
- 99 99 99 99 99 99 99 99
它指出“如果將這些量化值除以 2,則生成的重建影像通常與源影像幾乎無法區分”。透過我們的程式“JPEG_File”,你可以看到一張圖片的表格(使用順序 DCT 程式,並且)指定了名稱“pict”。在我們生成(真實的)JPEG 檔案的程式中,我們為 Y 分量選擇了另一個表格,而不是上面的表格,即在影像編輯程式(IrfanView)中使用,將質量設定為 70% 時使用的表格
- 10 7 6 10 14 24 31 37
- 7 8 11 16 35 36 33
- 8 8 10 14 24 34 41 34
- 10 13 17 31 52 48 37
- 11 13 22 34 41 65 62 46
- 14 21 33 38 49 62 68 55
- 29 38 47 52 62 73 72 61
- 43 55 57 59 67 60 62 59
量化表在 DQT 段中指定。DQT 段以標記 DQT = 219 和長度開頭,長度為 (0, 67)。然後是一個位元組,其前半部分為 0,表示該表由位元組(8 位數字 - 對於擴充套件模式,為 1,表示該表由字,16 位數字)組成,後半部分為表的 *目標識別符號* (0-3),例如,Y 分量為 0,顏色分量為 1。接下來是表的 64 個數字(位元組)。
緊接掃描段 SOS 之後是圖片的編碼資料,掃描段指定了用於分量的哈夫曼表。該段以標記 SOS = 218 和長度開頭,長度為 (0, 6 + 2 * 分量數)。然後是一個位元組,表示分量數 (1-4),然後是每個分量的兩個位元組,第一個是分量識別符號(在幀段中定義),第二個分為兩部分,第一部分表示 DC 哈夫曼表的目標選擇器,第二部分表示 AC 哈夫曼表的目標選擇器(例如,Y 分量為 0,顏色分量為 1)。該段以三個位元組結束,在我們的案例(順序 DCT)中,它們是 0、63 和 0(最後一個分為兩個半位元組)。
