JPEG 圖片壓縮原理(一)

一、系統架構

本文以一個實際的產品爲例,來說明 JPEG 在其中的應用。

本系統爲一個嵌入式 Linux 網絡播放器,主要的功能爲播放家庭網絡中的多媒體文件,在家庭客廳等環境中有着大量的應用,它可以給用戶提供更方便快捷的媒體文件的播放方式,並能充分利用家庭音響系統的巨大功能,而非 PC 環境下有限的外部設備,大大改善了媒體文件的播放體驗。

系統主要的功能包括:

本系統架構如下圖:

本系統是基於嵌入式 Linux 的一個應用,使用的是 ucLinux 2.4.22,並使用了 microwindows 作爲 GUI 界面,底層使用了 Linux kernel 的 FrameBuffer 作爲顯示輸出。

此係統在兩個方面使用到了 JPEG 庫:

1、 UI 的顯示,即各種人機交互界面,考慮到用戶體驗,所以大量使用了貼圖來美化 UI

2、 JPEG 圖片文件的全屏播放,包括用戶手中的各種照片等

二、JPEG 概述

JPEG 是 Joint Photographic Experts Group 的縮寫,即 ISO 和 IEC 聯合圖像專家組,負責靜態圖像壓縮標準的制定,這個專家組開發的算法就被稱爲 JPEG 算法,並且已經成爲了大家通用的標準,即 JPEG 標準。 JPEG 壓縮是有損壓縮,但這個損失的部分是人的視覺不容易察覺到的部分,它充分利用了人眼對計算機色彩中的高頻信息部分不敏感的特點,來大大節省了需要處理的數據信息。

人眼對構成圖像的不同頻率成分具有不同的敏感度,這個是由人眼的視覺生理特性所決定的。如人的眼睛含有對亮度敏感的柱狀細胞1.8億個,含有對色彩敏感的椎狀細胞0.08億個,由於柱狀細胞的數量遠大於椎狀細胞,所以眼睛對亮度的敏感程度要大於對色彩的敏感程度。

總體來說,一個原始圖像信息,要對其進行 JPEG 編碼,過程分兩大步:

1、 去除視覺上的多餘信息,即空間冗餘度

2、 去除數據本身的多餘信息,即結構(靜態)冗餘度

1、去除視覺上的多餘信息

當你拿到一個原始未經處理的圖像,是由各種色彩組成的,即在一個平面上,有各種色彩,而這個平面是由水平和垂直方向上的很多點組成的。實際上,每個點的色彩,也即計算機能表示的每個像素點的色彩,能分解成紅、綠、藍,即 RGB 三元色來表示,即這三種顏色的一定比例的混合就能得到一個實際的色彩值。

所以,實際上,這個平面的圖像,可以理解爲除了水平 X 和垂直 Y 以外,還有一個色彩值的 Z 的三維的系統。Z 代表了三元色中各個分支 R/G/B 的混合時所佔的具體數值大小,每個像素的 RGB 的混合值可能都有所不同,各個值有大有小,但臨近的兩個點的 R/G/B 三個值會比較接近。

由於這個原始圖像是由很多個獨立的像素點組成的,也就是說它們都是分散的,離散的。比如有些圖像的尺寸爲640X480,就表示水平有640個像素點,垂直有480個像素點。

從上面的內容,我們可以知道兩個相鄰的點,會有很多的色彩是很接近的,那麼如何能在最後得到的圖片中,儘量少得記錄這些不需要的數據,也即達到了壓縮的效果。

這個就要涉及到圖像信號的頻譜特性了。

圖像信號的頻譜線一般在0-6MHz範圍內,而且一幅圖像內,包含了各種頻率的分量。但包含的大多數爲低頻頻譜線,只在佔圖像區域比例很低的圖像邊緣的信號中才含有高頻的譜線。這個是對 JPEG 圖像壓縮的理論依據。

因此具體的方法就是,在對圖像做數字處理時,可根據頻譜因素分配比特數:對包含信息量大的低頻譜區域分配較多的比特數,對包含信息量低的高頻譜區域分配較少的比特數,而圖像質量並沒有可察覺的損傷,達到數據壓縮的目的。

將原始圖像這個色彩空間域,轉換爲頻譜域,怎麼轉呢,這個就用到了數學上的離散餘弦變換,即 DCT(Discrete Cosine Transform) 變換。

DCT 是可逆的、離散的正交變換。變換過程本身雖然並不產生壓縮作用,但是變換後的頻率係數卻非常有利於碼率壓縮。即這個變換過程得到一個 DCT 變換系數,而對這個係數可以再進行更進一步的處理,即所謂的量化。經過量化,就能達到數據壓縮的作用了。

總體說來,這第一步,對圖像進行編碼,去除多餘的信息,要用到 DCT 變換中的正向 DCT(FDCT),然後再對變換的係數做量化(Quantization),這個過程就是依據的經驗值,來處理人眼視覺系統所不敏感的高頻數據,從而極大地減少了需要處理的數據量,這個是結合數學方法與經驗值而做的處理。

2、去除數據本身的多餘信息

利用 Huffman 編碼,來將最後的數據用無損的方式做壓縮,這個是純數學上的處理方式。

總體來說,上面的兩步即:

如果處理的是彩色圖像,JPEG 算法首先將 RGB 分量轉化成亮度分量和色差分量,同時丟失一半的色彩信息(空間分辨率減半)。然後,用 DCT 來進行塊變換編碼,捨棄高頻的係數,並對餘下的係數進行量化以進一步減小數據量。最後,使用 RLE 行程編碼和 Huffman 編碼來完成壓縮任務。

三、JPEG 原理詳細分析

下面將更加詳細地介紹這兩步中的各個細節。

JPEG 編碼中主要涉及到的內容主要包括:

1. Color Model Conversion (色彩模型)

2. DCT (Discrete Cosine Transform 離散餘弦變換)

3. 重排列 DCT 結果

4. 量化

5. RLE 編碼

6. 範式 Huffman 編碼

7. DC 的編碼

1、色彩空間 color space

在圖像處理中,爲了利用人的視角特性,從而降低數據量,通常把 RGB 空間表示的彩色圖像變換到其他色彩空間。

現在採用的色彩空間變換有三種:YIQ,YUV 和 YCrCb。

每一種色彩空間都產生一種亮度分量信號和兩種色度分量信號,而每一種變換使用的參數都是爲了適應某種類型的顯示設備。

YUV 不是哪個英文單詞的縮寫,而只是符號,Y 表示亮度,UV 用來表示色差,U、V 是構成彩色的兩個分量;

YUV 表示法的重要性是它的亮度信號(Y)和色度信號(U、V)是相互獨立的,也就是 Y 信號分量構成的黑白灰度圖與用 U、V 信號構成的另外兩幅單色圖是相互獨立的。由於 Y、U、V 是獨立的,所以可以對這些單色圖分別進行編碼。此外,黑白電視能接收彩色電視信號也就是利用了 YUV 分量之間的獨立性。

舉例來說明一下:

要存儲 RGB 8∶8∶8的彩色圖像,即 R、G 和 B 分量都用8位二進制數(1個字節)表示,圖像的大小爲640×480像素,那麼所需要的存儲容量爲640×480×(1+1+1)=921 600字節,即900KB,其中(1+1+1)表示 RGB 各佔一個字節。

如果用 YUV 來表示同一幅彩色圖像,Y 分量仍然爲640×480,並且 Y 分量仍然用8位表示,而對每四個相鄰像素(2×2)的 U、V 值分別用相同的一個值表示,那麼存儲同樣的一幅圖像所需的存儲空間就減少到640×480×(1+1/(22)+1/(22))=460 800字節,即450KB。也就是把數據壓縮了一半。

無論是用 YIQ、YUV 和 YCrCb 還是其他模型來表示的彩色圖像,由於現在所有的顯示器都採用 RGB 值來驅動,這就要求在顯示每個像素之前,須要把彩色分量值轉換成 RGB 值。

對電視機,在考慮人的視覺系統和電視陰極射線管(CRT)的非線性特性之後,RGB 和 YUV 的對應關係可以近似地用下面的方程式表示:

即:

Y=0.3R+0.59G+0.11B

U=B-Y

V=R-Y

對計算機而言,計算機用的數字域的色彩空間變換與電視模擬域的色彩空間變換不同,它們的分量使用 Y、Cr 和 Cb 來表示,與 RGB 空間的轉換關係如下:

從這裏,就可以看出,計算出來的 Y、Cr 和 Cb 分量,會出現大量的小數,即浮點數,從而導致了在 JPEG 編碼過程中會出現大量的浮點數的運算,當然經過一定的優化,這些浮點數運算可以用移位與加法這些計算機能更快速處理的方式來對其進行編碼。

RGB 與 YCrCb 之間的逆變換關係可寫成如下的形式:

總體來說,上面講的這些內容,主要就是對原始圖片,可以先進行色彩空間的處理,使採集到的圖像數據有所減少。

請注意,實際上,JPEG 算法與色彩空間無關,色彩空間是涉及到圖像採樣的問題,它和數據的壓縮並沒有直接的關係。

因此“RGB 到 YUV 變換”和“YUV 到 RGB 變換”不包含在 JPEG 算法中。JPEG 算法處理的彩色圖像是單獨的彩色分量圖像,因此它可以壓縮來自不同色彩空間的數據,如 RGB,YcbCr 和 CMYK。

2、色彩深度 color depth

在圖像中,它是由很多個點來組成的,那麼存儲每個像素點所用的位數就叫做像素深度。對一個圖片,這個值是可以有所不同的,從而會使得圖片的數據有多和少的區別。

一幅彩色圖像的每個像素用 R,G,B 三個分量表示,若每個分量用8位,那麼一個像素共用3X8=24位表示,就說像素的深度爲24 bit,每個像素可以是2的24次方=16 777 216種顏色中的一種。表示一個像素的位數越多,它能表達的顏色數目就越多。

在用二進制數表示彩色圖像的像素時,除 R,G,B 分量用固定位數表示外,往往還增加1位或幾位作爲屬性(Attribute)位。例如,RGB 5∶5∶5表示一個像素時,用2個字節共16位表示,其中 R,G,B 各佔5位,剩下一位作爲屬性位。在這種情況下,像素深度爲16位,而圖像深度爲15 位。

在用32位表示一個像素時,若 R,G,B 分別用8位表示,剩下的8位常稱爲 alpha 通道(alpha channel)位,或稱爲覆蓋(overlay)位、中斷位、屬性位。它的用法可用一個預乘 α 通道(premultiplied alpha)的例子說明。假如一個像素(A,R,G,B)的四個分量都用歸一化的數值表示,(A,R,G,B)爲(1,1,0,0)時顯示紅色。當像素爲 (0.5,1,0,0)時,預乘的結果就變成(0.5,0.5,0,0),這表示原來該像素顯示的紅色的強度爲1,而現在顯示的紅色的強度降了一半。

這個 alpha 值,在這裏就用來表示該像素如何產生特技效果。

總體來說,圖像的寬高、分辨率越高,就是組成一幅圖的像素越多,則圖像文件越大;像素深度越深,就是表達單個像素的顏色和亮度的位數越多,圖像文件就越大。

只有黑白兩種顏色的圖像稱爲單色圖像(monochrome),每個像素的像素值用1位存儲,它的值只有“0”或者“1”,一幅640×480的單色圖像需要佔據37.5 KB的存儲空間。

而灰度圖像,即有色深的黑白圖像,如果每個像素的像素值用一個字節表示,而不是僅僅只有一位,那麼灰度值級數就等於256級,每個像素可以是0~255之間的任何一個值,一幅640×480的灰度圖像就需要佔用300 KB的存儲空間,類似上面說到過的 Y 分量。

3、離散餘弦變換 DCT

將圖像從色彩域轉換到頻率域,常用的變換方法有:

DCT變換的公式爲:

f(i,j) 經 DCT 變換之後,F(0,0) 是直流係數,其他爲交流係數。

還是舉例來說明一下。

8x8的原始圖像:

推移128後,使其範圍變爲 -128~127:

使用離散餘弦變換,並四捨五入取最接近的整數:

上圖就是將取樣塊由時間域轉換爲頻率域的 DCT 係數塊。

DCT 將原始圖像信息塊轉換成代表不同頻率分量的係數集,這有兩個優點:其一,信號常將其能量的大部分集中於頻率域的一個小範圍內,這樣一來,描述不重要的分量只需要很少的比特數;其二,頻率域分解映射了人類視覺系統的處理過程,並允許後繼的量化過程滿足其靈敏度的要求。

當u,v = 0 時,離散餘弦正變換(DCT)後的係數若爲F(0,0)=1,則離散餘弦反變換(IDCT)後的重現函數 f(x,y)=1/8,是個常 數值,所以將 F(0,0) 稱爲直流(DC)係數;當 u,v≠0 時,正變換後的係數爲 F(u,v)=0,則反變換後的重現函數 f(x,y) 不是常數,此時 正變換後的係數 F(u,v) 爲交流(AC)係數。

DCT 後的64個 DCT 頻率係數與 DCT 前的64個像素塊相對應,DCT 過程的前後都是64個點,說明這個過程只是一個沒有壓縮作用的無損變換過程。

單獨一個圖像的全部 DCT 係數塊的頻譜幾乎都集中在最左上角的係數塊中。

DCT 輸出的頻率係數矩陣最左上角的直流 (DC)係數幅度最大,圖中爲-415;以 DC 係數爲出發點向下、向右的其它 DCT 係數,離 DC 分量越遠,頻率越高,幅度值越小,圖中最右下角爲2,即圖像信息的大部分集中於直流係數及其附近的低頻頻譜上,離 DC 係數越來越遠的高頻頻譜幾乎不含圖像信息,甚至於只含雜波。

DCT 本身雖然沒有壓縮作用,卻爲以後壓縮時的"取"、"舍" 奠定了必不可少的基礎。

4、量化

量化過程實際上就是對 DCT 係數的一個優化過程。它是利用了人眼對高頻部分不敏感的特性來實現數據的大幅簡化。

量化過程實際上是簡單地把頻率領域上每個成份,除以一個對於該成份的常數,且接着四捨五入取最接近的整數。

這是整個過程中的主要有損運算。

以這個結果來說,經常會把很多高頻率的成份四捨五入而接近0,且剩下很多會變成小的正或負數。

整個量化的目的是減小非“0”係數的幅度以及增加“0”值係數的數目。

量化是圖像質量下降的最主要原因。

因爲人眼對亮度信號比對色差信號更敏感,因此使用了兩種量化表:亮度量化值和色差量化值。

使用這個量化矩陣與前面所得到的 DCT 係數矩陣:

如,使用−415(DC係數)且四捨五入得到最接近的整數

總體上來說,DCT 變換實際是空間域的低通濾波器。對 Y 分量採用細量化,對 UV 採用粗量化。

量化表是控制 JPEG 壓縮比的關鍵,這個步驟除掉了一些高頻量;另一個重要原因是所有圖片的點與點之間會有一個色彩過渡的過程,大量的圖像信息被包含在低頻率中,經過量化處理後,在高頻率段,將出現大量連續的零。

5、“Z”字形編排

量化後的數據,有一個很大的特點,就是直流分量相對於交流分量來說要大,而且交流分量中含有大量的0。這樣,對這個量化後的數據如何來進行簡化,從而再更大程度地進行壓縮呢。

這就出現了“Z”字形編排,如圖:

對於前面量化的係數所作的 “Z”字形編排結果就是:

底部 −26,−3,0,−3,−3,−6,2,−4,1 −4,1,1,5,1,2,−1,1,−1,2,0,0,0,0,0,−1,−1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 頂部

這樣做的特點就是會連續出現多個0,這樣很有利於使用簡單而直觀的行程編碼(RLE:Run Length Coding)對它們進行編碼。

8×8圖像塊經過 DCT 變換之後得到的 DC 直流係數有兩個特點,一是係數的數值比較大,二是相鄰8×8圖像塊的 DC 係數值變化不大。根據這個特點,JPEG 算法使用了差分脈衝調製編碼(DPCM)技術,對相鄰圖像塊之間量化 DC 係數的差值(Delta)進行編碼。即充分利用相鄰兩圖像塊的特性,來再次簡化數據。

即上面的 DC 分量-26,需要單獨處理。

而對於其他63個元素採用zig-zag(“Z”字形)行程編碼,以增加行程中連續0的個數。

6、行程編碼

Run Length Coding,行程編碼又稱“運行長度編碼”或“遊程編碼”,它是一種無損壓縮編碼。

例如:5555557777733322221111111

這個數據的一個特點是相同的內容會重複出現很多次,那麼就可以用一種簡化的方法來記錄這一串數字,如

(5,6)(7,5)(3,3)(2,4)(l,7)

即爲它的行程編碼。

行程編碼的位數會遠遠少於原始字符串的位數。

對經過“Z”字形編排過的數據,即可以用行程編碼來對其進行大幅度的數據壓縮。

我們來用一個簡單的例子來詳細說明一下:

57,45,0,0,0,0,23,0,-30,-16,0,0,1,0,0,0,0 ,0 ,0 ,0,..,0

可以表示爲

(0,57) ; (0,45) ; (4,23) ; (1,-30) ; (0,-16) ; (2,1) ; EOB

即每組數字的頭一個表示0的個數,而且爲了能更有利於後續的處理,必須是 4 bit,就是說,只能是 0~15,這是的這個行程編碼的一個特點。

7、範式 Huffman 編碼

在直流 DC 係數經過上面的 DPCM 編碼,交流 AC 係數經過 RLE 編碼後,得到的數據,還可以再進一補壓縮,即使用 Huffman 編碼來處理。

範式 Huffman 編碼即 Canonical Huffman Code,現在流行的很多壓縮方法都使用了範式哈夫曼編碼技術,如 GZIB、ZLIB、PNG、JPEG、MPEG 等。

對上面的例子中 RLC 後的結果,對它的存儲,JPEG 裏並不直接保存這個數值,這樣主要是爲了提高效率。

對上面的例子內容,就可以得到:

57 爲第 6 組的,實際保存值爲 111001,編碼爲 (6,111001)

45編碼爲 (6,101101)

23爲(5,10111)

-30爲(5,00001)

這個時候前面的例子就變爲:

(0,6),111001 ; (0,6),101101 ; (4,5),10111; (1,5),00001; (0,4) ,0111 ; (2,1),1 ; (0,0)

這樣,括號裏的數值正好再合成一個字節,高4位是前面0的個數,低4位描述了後面數字的位數;後面被編碼的數字表示範圍是 -32767..32767。

使用上面這個表簡化後的內容,再到 Huffman 編碼表裏去查詢,從而得到最後的編碼。

如06對應 Huffman 表的111000,那麼

69 = (4,5) --- 1111111110011001 (69=0x45=4*16+5 )

21 = (1,5) --- 11111110110

從而得到最後的結果:

111000 111001 ; 111000 101101 ; 1111111110011001 10111 ; 11111110110 00001…

使用範式 Huffman 編碼表的好處就是使得出現頻率高的數字小於8位,而出現頻率低的數字大於8位,這樣對整體而言,就會極大地減少數據量。

需要注意的是,在 JPG 文件中,一般有兩個 Huffman 表,一個是 DC 用,一個是 AC 用,它們是類似的。

對 DC 編碼的部分是單獨來處理的,並且是放在上面這個串的最前面。

總體來說,到目前爲止,我們就得到了最後需要真正存儲用的簡化後,也即壓縮後的數據了。

四、JPEG文件存儲格式

介紹了 JPEG 的原理,我們再來結合一個具體的實例來詳細討論上面所涉及到的細節。

我們先來製作一個簡單的8X8大小的像素圖,然後把它存成JPEG格式。

方法是用 windows 的畫圖工具,定義一個8X8大小的圖,用一些色塊填充進去,然後另存爲 JPEG 格式,如 test8x8.jpg。如下圖所示:

保存成的文件後綴爲 jpg,但按標準來說,它是一種 JFIF 格式標準的文件,裏面的圖像的壓縮方式是 JPEG。

JFIF 是一個文件格式標準,JPEG 是一個壓縮標準,總體來說它們不是一個概念。

JFIF 是 JPEG File Interchange Format 的縮寫,也即 JPEG 文件交換格式。JFIF 是一個圖片文件格式標準,它是一種使用 JPEG 圖像壓縮技術存儲攝影圖像的方法。JFIF 代表了一種"通用語言"文件格式,它是專門爲方便用戶在不同的計算機和應用程序間傳輸 JPEG 圖像而設計的語言。

JFIF 文件格式定義了一些內容是 JPEG 壓縮標準未定義的,如 resolution/aspect ratio,color space 等。

我們可以打開 JPEG 文件查看裏面的內容,即可看到上面的各個標記段:

從圖上可以看出:

在頭部有 FFD8 ,表示圖像的開始;結束部分有 FFD9 ,表示圖像的結束。

在中間有兩個量化表 DQT 對應的標記 FFDB ;

還有圖像大小信息對應的 FFC0

再後面有四個 Haffman 表對應的 FFC4 ;

一般一個 JPG 文件裏會有 2 類 Haffman 表:一個用於 DC 一個用於 AC ,也即實際有 4個表,亮度的 DC,AC 兩個,色度的 DC,AC 兩個。

然後是圖像數據段標記 FFDA;

我們再來看看各個標記的細部,具體分析一下各個部分的含義。

1、圖片的識別信息

上面的內容,在標記 FFE0 後,即爲長度16。然後是5字節的 JFIF 標識符號,說明這是一個 JPEG 壓縮的文件。然後是主/次版本號碼。下一個爲 XY 像素的單位,這裏爲1,表示單位爲點數/英寸。然後是 XY 方向的像素密度,這裏是 96DPI,最後是縮略圖有關信息,這裏爲0。

2、量化表的實例

上面這個內容,FFDB 標記後的長度值爲67,接下來的是 QT 信息,佔一個字節;這裏是0,表示這個 QT 表編號爲0,並且精度是8bit。然後後面就是64個8x8的 QT 表的各個 item 了。

也即第一個 DQT 量化表的內容表示爲十進制是:

這個表即爲 JPEG 亮度量化表。

第二個量化表的內容爲:

這個表的內容即爲 JPEG 色度量化表。

當你打開不同的 JPEG 文件,你會看到這兩個表可能也是會有區別的。這個主要是使用了不同的量化方式的結果。

3、圖像信息段

上面這個內容,FFC0 標記後即是長度,爲17,然後是一個字節的數據精度,通常是爲8,代表樣本位數。接下來是圖片的高度,佔兩字節,這裏即爲8,然後是圖片的寬度,也爲8,這也就是我們定義的8x8的內容。然後是 component 的個數,這裏是3,表示 YUV。接下來是三組數據,每組數據裏,第一個是 component ID,第二個是採樣係數,這裏 Y 的採樣係數爲22,說明垂直是2,水平是2。再後面就是量化表的編號了。

4、Haffman 表的實例

上面這個內容,FFC4 標記後的內容爲數據長度,再接着的1字節爲 Huffman Table 的信息,低4位是 HT ID 號,第5位是 HT 表類型標記,再高三位是爲0。

第一個 DHT 表,00,類型爲 DC table,HT ID 號爲 0;

第二個 DHT 表,10,類型爲 AC table,HT ID 號也爲 0;

第三個 DHT 表,01,類型爲 DC table,HT ID 號爲 1;

第四個 DHT 表,11,類型爲 AC table,HT ID 號爲 1;

即前兩個表爲Y亮度分量的 DC/AC 表,後兩個爲 UV 色度分量的 DC/AC 表。

以第一個表爲例,因爲長度只有 31,那麼 00 後面的 16 字節,即綠色部分:

組號爲 1 的組中,代碼有 0 個;

組號爲 2 的,代碼有 1 個;

組號爲 3 的代碼有 5 個;

組號爲 4/5/6/7/8/9 的代碼各 1 個。

總共 12 個。

再看後續的數據:

00 01 02 03 04 05 06 07 08 09 0A 0B

即對應:

其他未出現的組號,對應的數據未使用到。也就是說前面提到過的範式 Huffman 編碼裏,目前只使用部分數據即可,原因是這個 8x8 的圖像數據很小。

第二個 DHT 表就更復雜些了,長度有 181。

5、圖像數據段

這裏 SOS 段,長度爲 12,後面所含有的 component 數量爲 3 個,也即 Y UV。然後後面是各 component 的編號,及對應所使用的 Huffman 表的 ID 是多少。

在這個段的後面就是所有壓縮後的數據。直到結束的問題,即 FFD9,EOI(End Of Image)。

五、JPEG 壓縮過程的優化

JPEG 在目前的應用範圍是非常廣泛的,各種嵌入式系統中也大量地使用了 JPEG 壓縮,如 IPCAM 攝像頭、數字相機、移動存貯等。在這些領域由於傳輸數據的帶寬限制或者是存貯數據的容量的限制,常常需要使用圖像壓縮技術來將原始大量的圖像數據壓縮後在進行傳輸或存貯,以充分利用帶寬與存貯空間,達到更好的利用效率。這樣,在嵌入系統中,就會使用到 JPEG 壓縮。而且由於嵌入系統的資源有限的特點,在很多情況下,很需要再對 JPEG 編碼壓縮的過程做更進一步的優化,我們這裏詳細討論一下如何實現這些優化。

浮點運算的優化

我們回頭查看一下 JPEG 壓縮中的 DCT 變換過程,公式:

由於公式中有兩個 i/j=0~7 的部分,這樣要獲得一個 DCT 係數,需要做 8 x 8=64 次乘法和 8 x 8=64 次加法, 而完成整個 8 x 8 像素的 DCT 需要 8 x 8 x 8 x 8=4096 次乘法和 8 x 8 x 8 x 8=4096 次加法. 計算量是相當的大。

對於有些無浮點運算的嵌入式系統或無專門的數學運算協處理器的系統,會造成大量的運算,極大地佔用CPU的資源。

上面的公式屬於 DCT 的二維計算方式,經過簡化,可以將其簡化爲兩個一維的公式:

這樣,上面的過程就可以簡化爲分別計算行和列的 DCT 變換。

對於一行來說需要計算的是 (8 x 8) 次乘法和 (8 x 8) 次加法,8 行就是 8 x (8 x 8) 次乘法和 8 x (8 x 8) 次加法,然後列也是相同,那麼總數就爲 2 x (8 x (8 x 8))=1024 次乘法和 2 x (8 x (8 x 8))=1024 次加法, 運算量變爲二維計算的1/4。

但是這樣的運算數量還是太大,還需要進一步優化。

在很多嵌入系統中,很多情況下需要不使用浮點運算,這樣就需要再找出一維 DCT 的一些規律,然後對其進行進一步的優化。

在對一維 DCT 的運算中,還可以分爲奇數列/行和偶數列/行

對上面的處理,就又出現了多種優化:ChenDCT,LeeDCT,AAN 算法和 LLM 算法。

其中 AAN 算法只需要 29 次加法和 5 次乘法。(注意,它是指每次一維運算要 29 次加法和 5 次乘法,一共是需要 2982 次加法和 582 次乘法的)。

其中 Y[0]-Y[7] 都是 18 的矩陣,X[1]-X[7] 也都是 18 的矩陣。

{a, b, c, d, e, f, g} = 1/2 { cos(pi/4), cos(pi/16), cos(pi/8), cos(3pi/16), cos(5pi/16), cos(3pi/8), cos(7pi/16) }

再對上面的含有 pi 的係數進行整數優化,從而避免浮點運算,就會得到:

其中:

3/8=1/4+1/8

5/8=1/2+1/8

7/8=1-1/8

上面的除以 2,除以 8,都可以通過移位來實現,即右移一位和右移三位。即總數爲 30 次加法,12 次移位即可。

這樣就在很大程度上將原本需要使用乘法,浮點運算的過程全部轉換成了簡單的加法和移位處理了,這樣使用數學的方法,用近似的值來完成整個轉換過程,會有很好的性能和處理效果。

在處理上面的數據中,可以使用一些中間變量來記錄中間結果,這樣就可以減少反覆計算中間值,而直接使用已經計算得到了的中間值。

tmp0 = x[0] + x[7];

tmp7 = x[0] - x[7];

tmp1 = x[1] + x[6];

tmp6 = x[1] - x[6];

tmp2 = x[2] + x[5];

tmp5 = x[2] - x[5];

tmp3 = x[3] + x[4];

tmp4 = x[3] - x[4];

tmp10 = tmp0 + tmp3;

tmp13 = tmp0 - tmp3;

tmp11 = tmp1 + tmp2;

tmp12 = tmp1 - tmp2;

/* 對偶數項進行運算 X 0,4,6,2 */

X[0]=tmp1+tmp11;

X[4]=tmp10 /2 - tmp11

X[6]=tmp12-(tmp13/4+ tmp13/8);

X[2]=tmp12/4+tmp12/8-tmp13;

其他的各個值也是類似處理的。

六、JPEG 在本嵌入式 Linux 應用中遇到的問題

在本系統中,提供給用戶一些播放圖片和預覽圖片的功能,在這個過程中就需要使用到對 JPEG 的處理。

1、JPEG 出錯的處理

在對圖片做預覽處理的時候,有些圖片原始尺寸很大,那麼就需要將其轉換成較小的縮略圖,在轉換爲縮略圖進行顯示時,遇到了一個問題,即有時需要顯示的圖片,會導致系統無響應。

後來查找原因,定位到 JPEG 文件的數據不完整,才導致 jpeg decoder 出現無響應。

在前面的部分,有說到 JPEG 文件的格式中,JPEG 結束的標記 EOI (End Of Image) 爲“FFD9”。

如果需要顯示的圖片,在傳輸過程中,或轉換過程中,出現了沒有 EOI 數據,那麼應該在程序中,將其廢棄,避免出現系統無響應。

2、JPEG 解碼的效率優化

在解碼 JPEG 時,可以使用 software decode 或 hardware decode 來處理。Hardware decode 的優點是充分利用 DSP 所提供的硬件解碼功能,其解碼速度會較 software decode 有數量級的提高。但有時使用 hardware decode 有一些限制,如各種 DSP 提供的 SDK 會是直接訪問硬件,將 jpeg 直接輸出到顯示設備,從而會導致 hardware decode 與應用系統集成的麻煩。

而使用 software decode,就能在應用層完全掌握 jpeg decode 的數據緩衝結果,並可做一些圖片的疊加效果或對其進行半透明混合處理,從而會有較高的靈活性。並且使用 decode buffer cache,來將已經解碼的數據進行保存,在 UI 後續的使用中,就可不必反覆去解碼 JPEG 圖片,從而也能有效提高繪圖效率。

七、總結

上面的內容是本人對 JPEG 原理做的一個詳細的實例分析,還介紹了 JPEG 編碼過程中對浮點運算的優化處理,它特別適用於在資源有限的嵌入系統中避免大量的浮點運算。

在對 JPEG 原理做了一個詳細的分析後,大家會對 JPEG 涉及到的各個細節有了一個更加明確的認識。當你自己動手結合 JPEG 編碼過程來分析時,將會有一個清楚的全局觀。

本文結合應用實例,對在嵌入式 Linux 應用中遇到的 JPEG 有關的問題,做了一個說明,大家在自己的設計過程中也可以作爲參考。

現在,你如果再回頭去看 JPEG 的原理,你現在應該能看懂它整個過程的來龍去脈了。

版權申明:
本文轉自https://www.ibm.com/developerworks/cn/linux/l-cn-jpeg/ 版權爲原作者擁有。此次轉載僅作爲學習參考記錄。侵權刪!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章