跳至內容

JPEG - 想法與實踐 / 壓縮與編碼

來自華夏公益教科書,開放的書籍,開放的世界

檔案的壓縮

[編輯 | 編輯原始碼]

對於每個 sxs 方塊和三個 YCbCr 座標(或分量),在完成餘弦變換和量化後,我們得到一個按之字形原則排序的 s2 個整數序列。在每個序列中,我們將第一個數字 - DC 係數 - 用它與前一個 DC 係數的差值來代替(即前一個 sxs 方塊的相同分量)。然而,由於這些整數中的大多數(當方塊遍歷影像時)通常為零,因此將它們以特定方式引入檔案是可取的,即讓每隔一個整數為真實數字,而其他整數為零的數量(連續的)。這些整數(在新序列中)可以為負數,並且可以是任意大小,現在我們的任務是將這些整數轉換為儘可能短的位元序列。由於檔案由位元組組成,因此我們必須將所得的位元流分成 8 位元塊,並將這些位元塊轉換為位元組。

由於允許整數為任意大小,因此我們必須將每個整數表示為兩個位元序列對,第一個序列以某種方式(可能以編碼形式)對應於一個自然數,該自然數表示第二個序列的長度,第二個序列是該數字的二進位制表示式。第一個位元序列可以簡單地是自然數的二進位制表示式,但這些序列必須具有相同的長度,例如 4。由於 4 位元可以表示從 1 到 16 的自然數,並且透過使用不超過 16 個位元,我們可以表示高達 216-1 = 65535 的整數,因此這種方法可用於顏色變化很大或不是太大的圖片。如果你正在編寫 JPEG 程式,你應該從這種方法開始,並在程式工作後,再引入下面描述的方法之一,因為它是一種簡單的方法,可以將合適的照片壓縮到其 BMP 尺寸的 15%。但是,如果程式要能夠處理各種圖片,則必須將 4 位元擴充套件到 5 位元,即使 4 位元對於表示這些長度來說也是太多了,因為大多數長度都相當短。如果我們有一種方法,可以使這些對的第一序列(長度)可變,那就更好了。

我們的數字(表示位元數)是自然數,我們希望以這樣的方式用位元序列來表示它們:最常用的數字對應於最短的序列,並且我們必須有一種方法能夠確定何時一個序列終止。第一個描述了一種原理,該原理可以將給定集合的元素(在我們的案例中是自然數集合)與位元序列一一對應,使序列的長度與元素的使用頻率成反比,這是夏農和法諾在 1949 年提出的編碼方法。

夏農-法諾編碼

[編輯 | 編輯原始碼]

假設我們有一個過程,其結果是資訊的長串,這些資訊使用給定集合的元素來表達。我們希望用由位元序列組成的集合來代替這個集合,這樣最常用的序列是最短的。為此,你可以執行以下操作:將集合分成兩部分,使每部分中的元素使用頻率大致相同。對於第一部分中的元素,讓序列以 0 開頭,對於第二部分中的元素,讓序列以 1 開頭。將這兩部分中的每部分再分成兩部分,使每部分中的元素使用頻率大致相同,並讓下一個位元對於第一部分中的元素為 0,對於第二部分中的元素為 1,依此類推。

在我們的案例中,集合是自然數集合,此類數字的含義是它表示一個整數的二進位制表示式長度。自然數的使用頻率與其大小成反比,我們應該對頻率進行理論化,或者測試一些隨機圖片並取平均值。但是,在這種情況下,我們只會根據我們想要獲得一個簡單公式的願望來進行猜測:我們假設 {1, 2, 3}(的元素)使用頻率與其他元素相同,{1} 的使用頻率與 {2, 3} 相同,{4, 5} 的使用頻率與 {6, 7, ...} 相同,{6, 7} 的使用頻率與 {8, 9, ...} 相同,依此類推。在這些假設下,自然數的編碼將如下所示

1        00
2        010
3        011
4        100
5        101
6        1100
7        1101
8        11100
9        11101
10      111100
11      111101
12      1111100
13      1111101
等等。

注意,對於大於 3 的 n,第一個 0 之前的 1 的數量是 n/2 的整數部分減 1,並且在這個 0 之後,只有一個位元:n 為偶數時為 0,n 為奇數時為 1。當(在位元流中)我們知道一些後面的位元形成這樣的位元塊時,我們可以很容易地確定它何時終止,以及確定相應的自然數:如果第一個位元是 0,則後面會跟一個位元;如果它是 0,則數字是 1,如果它是 1,則後面會跟一個位元;如果它是 0,則數字是 2,如果它是 1,則數字是 3。如果第一個位元是 1,我們統計第一個 0 之前的 1 的數量,我們知道序列在這個 0 之後立即終止。我們將 1 加到 1 的數量上,並將這個數字乘以 2。然後,如果最後一個位元是 0,則自然數是這個數字,如果最後一個位元是 1,則自然數是下一個數字。

餘弦變換和量化產生的整數(每個 sxs 方塊和每個分量 s2 個整數),當方塊遍歷影像時,以特定方式寫入,即讓每隔一個整數為真實數字,而其他整數表示零的數量(可能是零)。此外,我們將這些整數寫成位元序列,每個序列都有兩個部分:第一部分以編碼形式寫入,對應於一個自然數,該自然數的目的是表示第二部分的位元數,即該整數的二進位制表示式。但由於整數(“真實”型別)可以為負數,因此我們必須以某種方式表示這一點。你可能認為我們必須為此使用一個額外的位元,但實際上沒有必要:數字表達式的第一個數字(即最高有效位)始終為 1,我們可以透過將這個 1 替換為 0 來表示該數字為負數。所得的位元流最終被分成 8 位元塊,並作為位元組寫入檔案 - 可能擴充套件最後一個塊(用 0 或 1)使其成為 8 位元塊。

我們在演示程式中使用了這種簡單的編碼方法,由於它可以將合適的照片壓縮到其原始尺寸的 6-12%,因此我們在這裡沒有看到選擇使用更復雜的編碼方法的理由。不過,我們現在將簡單介紹一下 JPEG 使用的編碼方法(將在“第二部分”中詳細說明)。

霍夫曼編碼

[編輯 | 編輯原始碼]

如果我們花更多時間研究頻率,我們可以得到一個更有效的程式。然而,夏農-法諾方法並不是最好的方法。最有效的編碼方法是霍夫曼方法,該方法由霍夫曼於 1951 年發明。這種方法在 JPEG 過程中幾乎是通用的。我們將在“第二部分”中對其進行描述,讀者將瞭解為什麼我們在這裡迴避它:它不容易描述和說明,編碼和解碼需要更多操作。此外,在 JPEG 過程中,DC 數和 AC 數以不同的方式進行霍夫曼編碼,並且 Y 分量和顏色分量使用不同的霍夫曼表。

霍夫曼編碼方法可以被證明是最有效的,但這種優越性假設所有資料都以相同的方式進行編碼,而 JPEG 壓縮並非如此。因此,JPEG 委員會除了霍夫曼編碼之外,還規定了所謂的“算術”編碼,它可以壓縮圖片更多。然而,算術編碼速度較慢,並且使用得不多 - 部分原因是它已獲得專利。

華夏公益教科書