JGP是如何工作的
原文鏈接:https://medium.freecodecamp.com/how-jpg-works-a4dbd2316f35#.iog01x8kp
JPG如何工作的
JPG文件格式對于圖片壓縮是最令人印象深刻的技術進步之一,并在1992年登上了舞臺。從那之后,它成為互聯網上代表圖片質量的技術標桿。這是很好的理由。然而JPG背后的很多技術卻異常復雜,需要完全理解人眼如何調節對顏色和邊界的感知。
因為我有些東西(你也是,如果你讀到這篇文章),我想解釋JPG編碼是如何工作的,這樣我們可以更好地理解如何生存更小的JPG文件。
要點
JPG壓縮機制分為幾個階段。下圖從高層表述了這些階段,后面我將逐個講解。
色彩空間轉換
有損數據壓縮的一個關鍵原則是人類的傳感器不像計算系統那樣精確。科學來說,人眼只有分辨大約1千萬種不同顏色的能力。然而,有許多因素會影響人眼感知顏色;完美的突出顏色錯覺,或者這件攪亂因特網的禮服。要點就是,相對于要識別的顏色,人眼可以很好的被操縱。
質量是有損壓縮效果的一種形式,然而JPG使用另一個方法進行:顏色模型。一個顏色空間代表一組顏色,它的顏色模型代表數學公式如何標示顏色(三原色RGB,四分色CMYK)。
這個過程的強大之處就是,你可以從一個色彩模型轉換成另一個,意味著你可以用給定顏色的數學表達式得到一組完全不同的數值。
例如,下面指定的顏色,分別代表RGB和CMYK色彩模型,人眼看到的是相同的顏色,但是可以由不同的數值集標示。
JPG從RGB轉換成Y,Cb,Cr色彩模型;模型由亮度(Y),色度藍(Cb),色度紅(Cr)組成。原因是,心里視覺試驗(大腦如何處理眼睛看到的信息)表明人眼對亮度比色度更敏感,這意味著我們可以忽略在色度上的較大變化而不影響我們識別圖像。因此,人眼收到信息之前,我們可以積極的改變CbCr通道信息。
下采樣
YCbCr色彩空間的一個有趣的結果是,得到的Cb/Cr信道有較少的細粒度細節;它們包含的信息比Y信道少。
其結果是,JPG算法調整了Cb和Cr信道信息,壓縮到原始大小的?(注意,有一些如何做到的細節,我這里不介紹…),被稱為下采樣。
這里需要注意的是下采樣是有損壓縮處理(不能恢復確切的原始色彩,但是非常接近),但對人類視覺皮層的可視化組件的整體影響是最小的。亮度(Y)是其中有趣的部分,因為我們只下采樣CbCr信道,視覺系統的影響較低。
圖像分成8x8的像素塊
從現在起,JPG所有的操作都基于8x8的像素塊。這樣做是因為我們通常期望在8x8塊上沒有很多變化,即使在很復雜的圖片中,在局部地區也有一些自相似性。我們將在之后的壓縮處理利用這種自相似性。
這點上值得注意的是,我們要介紹JPG編碼的常見”神器”之一。“色彩滲透”是沿著鋒利邊緣的顏色可以”滲透”到另一邊。這是因為色度通道,它代表像素的顏色,平均到單個顏色需要4個像素1塊,有些塊跨越了鋒利邊緣。
離散余弦變換
到現在,事情已經相當簡單。色彩空間,下采樣,和分塊在圖像壓縮領域都是簡單的部分。但是現在… 現在真正的數學開始了。
DCT變化的關鍵部分是,它假定任何數字信號都可以使用余弦函數組合來重建。
例如,我們有下圖:
你可以看到它實際上是cos(x)+cos(2x)+cos(4x)的和
可能更好的顯示是,真實的圖片解碼,給定在2D空間的一些列余弦函數。為了證明這一點,我展現了護糧網最驚人的GIF之一:在2D空間使用余弦函數編碼n8x8像素塊:
這里看到的是一張圖片(最左邊的面板)的重建。每一幀,我們使用一個新的基準值(右側面板),并乘一個權重值(右側面板文字)來生成圖片(中間面板)的貢獻。
如你所見,通過帶權重的不同余弦值相加,我們重建了原始圖像(相當完美…)
這是離散余弦變化如何工作的基礎背景。核心就是任何8x8塊都可以由一組權重余弦變化的和代表,在不同頻率。整個事件的技巧就是搞清楚要用那些余弦輸入,以及它們的權重。
原來“使用那些余弦”的問題相當簡單;大量計算后,選出一組余弦值來生成最接近的值,它們是基礎函數并在下圖中顯示。
至于“應當如何權重起來”的問題,簡單的(HA!)套用這個公式。
我就不介紹這些值的含義了,你可以在維基上查看它們。
這個矩陣,G,代表用來重建圖像(在動畫右側上方的小十進制數)的基礎權重。基本上,每個基礎余弦值,我們都與這個矩陣中的權重相乘,并相加整個值,之后得到最終的圖像。
到這里,我們不在處理色彩空間了,而是直接操作G矩陣(基準權重),之后所有的壓縮都直接基于這個矩陣。
這里的問題是我們現在將字節對齊的整數轉換為實數。這樣實際上膨脹了我們的信息(從1個字節到一個浮點數(4個字節))。為了解決這個問題,并開始生成更顯著的壓縮,我們進入量化階段。
量化
因此,我們不想壓縮浮點數據。這將膨脹我們的數據流,而且是低效的。為此,我們要找到一個方法將權重矩陣轉化成范圍在[0,255]的值。直截了當來說,我們可以這樣處理,找到矩陣中的最大/最小值 (分別是-415.38, 和77.13) ,將每個值除這個跨度來得到[0,1]區間的值,之后乘255的得到最終結果。
例如: [34.12- -415.38] / [77.13?—?-415.38] *255= 232
這個方法可行,但代價是顯著的精度減少。這個縮放將產生不均勻分布的值,其結果是圖像的顯著視覺損失。
相反,JPG采取了不同的路線。不同于使用矩陣中值的范圍作為它的縮放值,取而代之,使用了一個量化因素的預處理矩陣。這些QF不需要作為流的一部分,而是作為編碼器本身的一部分。
這個例子展示了量化因子矩陣的常用用法,
現在我們使用Q和G矩陣,來計算量化DCT協同矩陣:
例如,使用G[0,0]=?415.37和 Q[0,0]=16值:
最終結果矩陣:
看看矩陣變得更加簡單了——它現在包含大量的0或小整數,使得它更容易壓縮了。
簡單些,我們對Y,CbCr信道分別應用和各過程,因此我們需要兩個不同的矩陣:一個用于Y,另一個用于C信道:
圖像量化壓縮有兩種重要的方式:1,限制權重的有效范圍,減少代表它們所需的位數。2,許多權重變成相同的數字或者0,從而提高第三部的壓縮,熵代碼。
這樣量化是JPEG產品的主要來源。因為圖片的右下角趨向于最大的量化因數,JPEG產品趨向于圖片重組。通過修改JPEG的”質量級別”,提升或降低,就可以直接控制量化因子的矩陣(我們會在一分鐘內解釋)。
壓縮
現在,我們回到整數世界,并且可以對數據塊進一步應用有損壓縮。當看到我們的轉化數據時,你會發現一些有趣的事情:
當你從左上移動到右下,0值出現的頻率增加了。這看起來像首先懷疑是一個運行長度編碼。但是這里行主序和列主序并不理想,因為這些0交織運行,而不是將它們打包到一起。
相反,我們從左上角開始,按照對角線之字形遍歷矩陣,來回移動直到右下角。
亮度矩陣的結果,順序如下:
?26,?3,0,?3,?2,?6,2,?4,1,?3,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
一旦數據變成這種格式,接下來的步驟就簡單了:順序執行RLE,然后對結果執行統計編碼(霍夫曼/算數/ANS)。
咚!數據塊現在是JPG編碼了。
理解質量參數
現在,你理解了如何真正的創建JPG文件,這值得重新審視質量參數的概念,從Photoshop里導出JPG圖像時就會遇到。
這個參數,稱為q,是個從1到100的整數。可以認為q是圖像質量的衡量:q值越高,相應的圖像質量越高,文件大小越大。
質量值用在量化階段,來縮放合適的量化因子。因此對于每個基準權重,量化階段現在類似于
round\(Gi,k/alpha?Qi,k\)alpha符號作為質量參數的結果。
alpha或者Q[x,y]增加(記住alpha值越大對應的質量參數q越小),更多的信息會丟失,文件大小將減小。
因此,如果想以更高的視覺假象成本得到更小的文件,可以在導出階段設置更低的質量值。
注意上圖,在最低質量圖片中,我們如何看待阻塞階段還有量化階段的清晰痕跡。
可能更重要的是質量參數變化依賴于圖像。因為每個圖片是唯一的且呈現出不同類型的可視產品,Q值也是唯一的。
結論
當你理解JPG算法是如何工作的,幾件事就變得明顯了:
如果你想自己玩轉這一切,這一切可以瘋狂的整合到一個大約1000行的文件。
嘿!
希望知道如何是你的JPG文件更小?
希望知道PNG文件如何工作的,或者使它們更小?
希望有更多的數據壓縮?買我的書!
總結
- 上一篇: 淘客基地公众号系统更新至v1.2.3版本
- 下一篇: 开关电源三大拓扑之 Boost 电源中P