(文章還剩實踐部分沒寫,答辯過后補上...)
JPEG文件在當下數(shù)字化生活中是無處不在的榨馁,但是在熟悉的JPEG面紗背后森篷,隱藏著一些算法薛耻,它們?nèi)コ巳祟愌壑袩o法察覺到的細節(jié)营罢。這產(chǎn)生了最高的視覺質(zhì)量與最小的文件大小。讓我們來看看這一算法饼齿。
引言
我們發(fā)送圖片給朋友的時候饲漾,并不需要擔心哪個設備或者瀏覽器或者操作系統(tǒng)的兼容性,我們只是把圖片"發(fā)出去"缕溉。但是就像網(wǎng)絡傳輸一樣考传,只是傳輸卻沒有其他的措施會造成兼容性極差,所以需要一種協(xié)議或者一種標準证鸥。于是一組人在1992年創(chuàng)建了JPEG僚楞,一種數(shù)字圖像壓縮的標準。任何曾經(jīng)使用過互聯(lián)網(wǎng)的人都可能看到過JPEG編碼的圖像枉层。它是迄今為止最普遍的編碼泉褐、發(fā)送和存儲圖像的方式。從網(wǎng)頁到電子郵件到社交媒體鸟蜡,JPEG每天被使用數(shù)十億次-幾乎每次我們在網(wǎng)上查看或發(fā)送圖片膜赃。沒有JPEG,網(wǎng)絡就會少一點色彩并且慢很多揉忘。
所以這篇文章里將介紹一下關于如何將存儲在計算機上的壓縮數(shù)據(jù)轉(zhuǎn)換為顯示在屏幕上的圖像跳座。當然此文首先會對該文進行部分翻譯、然后結(jié)合MROS大神寫的一個JPEG教程進行講解泣矛,當然其中會加上自己的理解進行整理和驗證疲眷。如果能夠真正理解圖像的壓縮步驟,感覺對之后的圖像處理這一部分的學習也是有幫助的您朽。
開始
首先雙手奉上女神的照片:
接下來我們就拿這張圖片作為例子來講解咪橙,如果我們用文字編輯器打開圖片就會發(fā)現(xiàn)是一堆亂碼:
因為這是文字編輯器不能識別的格式,用文字編輯器打開圖片,既讓計算機感到疑惑同時也不能讓我們得到正確的可視結(jié)果美侦。因為我們的打開方式不正確,我們?nèi)绻斫釰PEG圖像是如何解碼的魂奥,我們需要查看原始流菠剩,即查看二進制數(shù)據(jù)〕苊海可以利用專門查看hex編碼的編輯器來查看:
我們現(xiàn)在隨意修改其中的一些數(shù)字具壮,可以發(fā)現(xiàn)有些數(shù)字的更改是無傷大雅的,但是有一些數(shù)字一旦修改可能會損壞整個圖像哈蝇,或者造成圖像顏色和位置發(fā)生變動棺妓。
很難通過這樣的方式來解釋如何從這些字節(jié)中重建圖像,因為jpeg壓縮實際上是由三種不同的壓縮技術組成的炮赦,它們被應用在連續(xù)的層中怜跑。我們將分別查看每一層壓縮,以解開我們正在看到的神秘行為吠勘。
JPEG壓縮的三層
1.色度次采樣(Chrominance Subsampling)
2.離散余弦變換(Discrete Cosine Transform & Quantization)
3.掃描寬度性芬、霍夫曼編碼(Run-length,Delta&Huffman Encoding)
首先我們需要了解這種壓縮的規(guī)模,請注意上面的圖像是使用確切的79剧防,819個數(shù)字表示的植锉,大約是79千字節(jié)。如果沒有壓縮存儲峭拘,則每個像素需要三個數(shù)字-每個紅色俊庇、綠色和藍色組件都需要一個數(shù)字。這意味著總共有917鸡挠,700個數(shù)字辉饱,約917千字節(jié)。使用jpeg壓縮宵凌,結(jié)果文件要小十倍以上鞋囊!而jpeg被稱為有損壓縮技術,圖像由于壓縮而改變并丟失了一些細節(jié)
Chrominance Subsampling
現(xiàn)在破譯要簡單一些瞎惫。這幾乎是一個簡單的顏色列表溜腐,每個字節(jié)只改變一個像素,但它已經(jīng)幾乎是未壓縮圖像的兩倍(對于這個較小的大小瓜喇,大約是300 kb)挺益。可以看出乘寒,這些數(shù)字并不代表標準的紅色望众、綠色和藍色組件,因為用0替換所有數(shù)字會使圖像變成綠色(而不是黑色)。這是因為這些字節(jié)表示圖像的y(亮度)烂翰、cb(相對藍度)和cr(相對紅度)夯缺。為什么不直接用RGB呢?畢竟甘耿,這就是大多數(shù)現(xiàn)代屏幕的工作原理踊兜。您的顯示器可以通過打開每個像素的不同強度的紅色、綠色和藍色燈來顯示任何顏色佳恬。白色是通過打開顯示的捏境。
這也和人類眼睛的工作原理非常相似。我們眼中的顏色受體被稱為“錐”毁葱,分為三種類型垫言,每種類型對紅色、綠色或藍色都很敏感倾剿。我們眼中的另一種感受器-棒筷频,只能檢測到亮度的變化,但它們要敏感得多柱告。我們的眼睛里有大約1.2億根棒狀物截驮。
這意味著我們的眼睛在檢測亮度變化方面比在檢測顏色變化方面要好得多。如果我們能把顏色和亮度分開际度,我們就可以在沒有人注意到的情況下去除一點顏色葵袭。色度次采樣是以比亮度分量更低的分辨率來表示圖像的顏色分量的過程。在上面的例子中乖菱,每個像素都有一個y分量坡锡,而每個由四個像素組成的離散組正好有一個CB和一個cr分量。因此窒所,圖像中包含的顏色信息只有最初的四分之一鹉勒。這就是為什么從上面的編輯器中刪除一個數(shù)字完全破壞了顏色。在這里吵取,組件存儲為y cbcr禽额。刪除第一個數(shù)字將使CB值被解釋為y,cr被解釋為CB皮官,并創(chuàng)建一個波動效應脯倒,在圖像中翻轉(zhuǎn)所有顏色。
Discrete Cosine Transform & Quantization
這一層壓縮很大程度上是jpeg的定義特性捺氢。在將顏色轉(zhuǎn)換為ycbcr之后藻丢,組件將被單獨壓縮,因此我們可以在本文的其余部分只關注y分量摄乒。下面是應用這個層的y組件的字節(jié)悠反。
離散余弦變換是將圖像分解成8x8塊并將每個塊轉(zhuǎn)換成這64個系數(shù)的組合的過程残黑。
如果我們并不是對8*8
像素點而是對整個獨享進行離散余弦變換,得到的就為上圖斋否。并且可以不斷刪除結(jié)尾處的數(shù)據(jù)梨水,但是一旦變更開頭處的數(shù)據(jù),就會造成肉眼可見的亮度變化茵臭。原因是開頭處為圖像的低頻變化冰木,結(jié)尾處為高頻變化。
Run-Length, Delta & Huffman Encoding
run-length encoding是用三個bytes去指定顏色笼恰,還有一個byte去指定有多少個像素有這個顏色。
delta-encoding是記錄變化量而不是原值歇终,比如說存儲值為12 13 14 13 2
社证,則就可以表示為:12 1 1 -1 -1
。每個DCT塊中的第一個值稱為dc值评凝,每個dc值相對于前面的dc值進行增量編碼追葡。因此,改變第一個塊的亮度將影響圖像中的所有塊奕短。
JPEG解碼流程
正如前面所說的一樣宜肉,JPEG是一個標準,而不是單單一個算法翎碑。包含了多種壓縮算法以及編碼方式谬返,也就是說兩張jpeg圖片之后使用的算法可能完全不同。
如果用壓縮算法進行區(qū)分的話日杈,可以分為sequential遣铝、progressive、hierarchical和lossless莉擒,其中sequential會從上至下解碼:
progressive則會在解碼過程中酿炸,從模糊逐步變得清晰:
除了壓縮算法,還有編碼方式不同:霍夫曼編碼涨冀、算術編碼填硕。除了壓縮算法和編碼方式,還有數(shù)據(jù)的粒度鹿鳖,可以理解為精度扁眯。先介紹所有JPEG規(guī)范組合中最簡單的一種:baseline,它使用的壓縮算法為sequential栓辜,編碼方式采用的為霍夫曼編碼恋拍,精度為8bit。而JPEG的編碼與解碼過程可以由下圖表示:
其中藕甩,DCT變換以及霍夫曼編碼都是完全可逆的運算恃慧,如果只有這兩個步驟菊匿,呢么得到的圖片就是無損的形用。但是為了進一步提高壓縮俠侶,baseline方法會拋棄掉一些"精細結(jié)構"概作,就像語音識別時會去掉音高等精細結(jié)構而只是保存采樣數(shù)據(jù)一樣。而從圖中可以看出將顏色從RGB空間轉(zhuǎn)換成YCbCr空間后降采樣 以及 在DCT變換后的量化數(shù)據(jù)都是去掉這些精細結(jié)構默怨。
一些概念
降采樣
縮小圖像(降采樣)的目的主要有兩個:1.使得圖像符合顯示區(qū)域的大醒堕拧;2.生成對應圖像的縮略圖匙睹。原理是這樣的:對于一幅圖像尺寸為M*N
愚屁,對其進行s倍 的下采樣,即得到 儲存的分辨率圖像痕檬。如果考慮是矩陣形式的圖像霎槐,就是把原始圖像
窗口內(nèi)的圖像變成一個像素,這個像素點就是窗口內(nèi)所有像素的均值
范式霍夫曼編碼
左邊就是霍夫曼樹梦谜,讓所有節(jié)點維持高度不變丘跌,但盡量往右移動,得到了右圖唁桩。由于兩棵樹的葉子節(jié)點高度相等闭树,它們的壓縮率是完全相等的。我們用左側(cè)這棵樹來記錄編碼信息荒澡,需要把整棵樹的結(jié)構都記錄下來报辱;但如果使用的是右側(cè)的樹,只需要記錄在高度h時有幾個葉子幾點仰猖,就能夠完全復原出右側(cè)的霍夫曼樹捏肢,所以范式霍夫曼樹能夠減少存儲編碼信息的空間用量。這個特性可以用于加速解碼饥侵。
例如用0b0代表A鸵赫,0b10代表B,0b11代表C躏升,則AABCAAA壓縮為0b001011000.
YCbCr色彩空間
RGB辩棒、YUV和YCbCr都是人為規(guī)定的色彩模型或顏色空間(有時也叫彩色系統(tǒng)或彩色空間)。它的用途是在某些標準下用通撑蚴瑁可接受的方式對彩色加以描述一睁。本質(zhì)上,色彩模型是坐標系統(tǒng)和子空間的闡述佃却。
其中RGB是我們常見的紅藍綠者吁,依據(jù)人眼識別的顏色定義出的空間。但是RGB的細節(jié)很難進行數(shù)字化的調(diào)整饲帅,它將色調(diào)复凳、亮度瘤泪、飽和度三個量放在一起表示。是最通用的面向硬件的彩色模型育八。該模型用于彩色監(jiān)視器和一大類彩色視頻攝像对途。每個像素點需要8bits*3 = 24bits
而YUV空間中,每一個顏色有一個亮度信號Y和兩個色度信號U和V髓棋,亮度信號時強度的感覺实檀,和色度信號斷開,這樣的話強度就能夠在不影響顏色的情況下改變按声。YUV使用RGB的信息膳犹,如果只有Y信號分量而沒有U、V分量签则,那么這樣表示的圖像就是黑白灰度圖像镣奋。彩色電視采用YUV空間正是為了用亮度信號Y解決彩色電視機與黑白電視機的兼容問題,使黑白電視機也能接收彩色電視信號怀愧。
YUV和RGB的轉(zhuǎn)換:
Y = 0.299 R + 0.587 G + 0.114 B
U = -0.1687 R - 0.3313 G + 0.5 B + 128
V = 0.5 R - 0.4187 G - 0.0813 B + 128
R = Y + 1.402 (V-128)
G= Y - 0.34414 (U-128) - 0.71414 (V-128)
B= Y + 1.772 (U-128)
YCbCr 其實是YUV經(jīng)過縮放和偏移的翻版。其中Y與YUV 中的Y含義一致,Cb,Cr 同樣都指色彩余赢,只是在表示方法上不同而已芯义。YCbCr其中Y是指亮度分量,Cb指藍色色度分量妻柒,而Cr指紅色色度分量扛拨。JPEG、MPEG均采用此格式举塔。
YCbCr與RGB的相互轉(zhuǎn)換
Y=0.299R+0.587G+0.114B
Cb=0.564(B-Y)
Cr=0.713(R-Y)
R=Y+1.402Cr
G=Y-0.344Cb-0.714Cr
B=Y+1.772Cb
YCbCr 有許多取樣格式绑警,主要的采樣格式有YCbCr 4:2:0、YCbCr 4:2:2央渣、YCbCr 4:1:1和 YCbCr 4:4:4计盒。其中YCbCr 4:1:1 比較常用,其含義為:每個點保存一個 8bit 的亮度值(也就是Y值)芽丹,每 2x2 個點保存一個 Cr 和Cb 值北启,圖像在肉眼中的感覺不會起太大的變化。所以拔第,原來用 RGB(R,G,B 都是 8bit unsigned) 模型咕村,每個點需要 8x3=24 bits(如下圖第一個圖). 而僅需要 8+(8/4)+(8/4)=12bits,平均每個點占12bits蚊俺。這樣就把圖像的數(shù)據(jù)壓縮了一半懈涛。
再來具體解釋一下主要的采樣格式:
(1)YUV 4:4:4
YUV三個信道的抽樣率相同,因此在生成的圖像里泳猬,每個象素的三個分量信息完整(每個分量通常8比特)批钠,經(jīng)過8比特量化之后宇植,未經(jīng)壓縮的每個像素占用3個字節(jié)。
下面的四個像素為: [Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的碼流為: Y0 U0 V0 Y1 U1 V1 Y2 U2 V2 Y3 U3 V3
(2)YUV 4:2:2
每個色差信道的抽樣率是亮度信道的一半价匠,所以水平方向的色度抽樣率只是4:4:4的一半当纱。對非壓縮的8比特量化的圖像來說,每個由兩個水平方向相鄰的像素組成的宏像素需要占用4字節(jié)內(nèi)存踩窖。
下面的四個像素為:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的碼流為: Y0 U0 Y1 V1 Y2 U2 Y3 V3
映射出像素點為:[Y0 U0 V1] [Y1 U0 V1] [Y2 U2 V3] [Y3 U2 V3]
(3)YUV 4:1:1
4:1:1的色度抽樣坡氯,是在水平方向上對色度進行4:1抽樣。對于低端用戶和消費類產(chǎn)品這仍然是可以接受的洋腮。對非壓縮的8比特量化的視頻來說箫柳,每個由4個水平方向相鄰的像素組成的宏像素需要占用6字節(jié)內(nèi)存
下面的四個像素為:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3]
存放的碼流為: Y0 U0 Y1 Y2 V2 Y3
映射出像素點為:[Y0 U0 V2] [Y1 U0 V2] [Y2 U0 V2] [Y3 U0 V2]
(4)YUV 4:2:0
4:2:0并不意味著只有Y,Cb而沒有Cr分量。它指得是對每行掃描線來說啥供,只有一種色度分量以2:1的抽樣率存儲悯恍。相鄰的掃描行存儲不同的色度分量,也就是說伙狐,如果一行是4:2:0的話涮毫,下一行就是4:0:2,再下一行是4:2:0...以此類推贷屎。對每個色度分量來說罢防,水平方向和豎直方向的抽樣率都是2:1,所以可以說色度的抽樣率是4:1唉侄。對非壓縮的8比特量化的視頻來說咒吐,每個由2x2個2行2列相鄰的像素組成的宏像素需要占用6字節(jié)內(nèi)存。
下面八個像素為:[Y0 U0 V0] [Y1 U1 V1] [Y2 U2 V2] [Y3 U3 V3] [Y5 U5 V5] [Y6 U6 V6] [Y7U7 V7] [Y8 U8 V8]
存放的碼流為:Y0 U0 Y1 Y2 U2 Y3
Y5 V5 Y6 Y7 V7 Y8
映射出的像素點為:[Y0 U0 V5] [Y1 U0 V5] [Y2 U2 V7] [Y3 U2 V7] [Y5 U0 V5] [Y6 U0 V5] [Y7U2 V7] [Y8 U2 V7]
讀取區(qū)段
JPEG壓縮文件可能是由以下幾個區(qū)段組成的:
除此之外属划,我們需要在JPEG開始和結(jié)尾處加上"文件開始"和"文件結(jié)束"標記恬叹,并且采用何種算法會和降采樣在同一個區(qū)段;壓縮圖像數(shù)據(jù)會前準一個SOS區(qū)段同眯,告知解碼器接下來該如何讀取绽昼。綜上可以將JPEG壓縮文件表示為:
在一個JPEG文件中,一定會出現(xiàn)SOF0
须蜗、SOF1
....SOF16
其中一個區(qū)段绪励,如果出現(xiàn)的是SOF0
就說明使用的為baseline。DQT和DHT都可能不止一個:
區(qū)段名稱 | 標記碼 | 有無數(shù)據(jù) |
---|---|---|
SOI | 0xFFD8 | NO |
EOI | 0xFFD9 | NO |
DQT | 0xFFDB | YES |
DHT | 0xFFC4 | YES |
SOF0 | 0xFFC0 | YES |
SOS | 0xFFDA | YES |
如果圖像信息里包含了0xff怎么辦唠粥?所以在規(guī)定壓縮圖像時會在0xff后加上一個0x00的字節(jié)疏魏,檢測時如果遇到0xff00直接跳過就行了。而又因為這里一個碼有2個字節(jié)晤愧,所以在寫程序是可以兩個字節(jié)兩個字節(jié)的讀大莫。
而在baseline中,文件開頭官份、文件結(jié)尾只厘、JFIF特有資訊實際上都已經(jīng)確定了烙丛,所以接下來只需要確定量化表(DQT)、霍夫曼表羔味、壓縮數(shù)據(jù)河咽、SOF0和SOS就行了,一步一步來赋元。
讀取DQT
一個DQT里最多可能有4個量化表忘蟹,所以量化表的存放在不同程序下可能會使用不同的方式下面是一個量化表的內(nèi)容:
代號 | 大小 | 描述 |
---|---|---|
① | 1 byte | 高 4 bits 表示每個量化值的大小,0 代表 1 byte搁凸,1 代表 2 bytes 低 4 buts 表示本量化表的 id 媚值, id 可爲 0, 1, 2, 3 |
② | 64 或 128 byte | 64 個 1 或 2 bytes 的量化值,是 1 byte 還是 2 bytes 取決於 ① 的高 4 bits |
讀取霍夫曼編碼表
代號 | 大小 | 描述 |
---|---|---|
① | 1 byte | 高 4 bits 代表本表是直流還是交流护糖, 0 是直流褥芒, 1 是交流 低 4 bits 代表是 0 號表還是 1 號表, 0 是 0 號 嫡良, 1 是 1 號 |
② | 16 bytes | 第 n 個 byte 代表高度爲 n 時锰扶,霍夫曼樹有幾個葉子節(jié)點 |
③ | 葉子節(jié)點數(shù)量bytes | 代表葉子節(jié)點所對應的信源符號,葉子從低到高寝受,從左到右 |
紅色就是直流1號少辣,紫色部分就為形成的范式霍夫曼樹的葉節(jié)點數(shù)目,葉子節(jié)點應該有2+2+5+1+5+1=16羡蛾,所以綠色部分應該有16個數(shù)值代表葉子節(jié)點上對應的信源符號;如果不足16個數(shù)值锨亏,說明這個DHT區(qū)段可能包含多個霍夫曼表痴怨,在下一個霍夫曼表中繼續(xù)讀取。
讀取SOF0區(qū)段
SOF0區(qū)段記錄了圖片寬高以及各個顏色分量的信息器予,有了這些數(shù)據(jù)我們才能夠讀取SOS段中的壓縮圖像數(shù)據(jù)浪藻,不過先看SOF0區(qū)段:
代號 | 大小 | 描述 | 備註 |
---|---|---|---|
① | 1 byte | 精度 | baseline 流程的精度固定爲 8 ,也就是說用 1 byte 來存取色彩空間的數(shù)值即可 |
② | 2 bytes | 圖片高度 | |
③ | 2 bytes | 圖片寬度 | |
④ | 1 byte | 有幾個顏色分量 | JFIF 規(guī)定顏色空間爲 YCbCr 因此顏色分量數(shù)量固定爲 3 |
⑤ | 9 bytes | 各個顏色分量的詳細資訊 | 見下一張表 |
上表中的5是下表重復三次乾翔,因為需要分別描述3個顏色分量的信息:
代號 | 大小 | 描述 | 備註 |
---|---|---|---|
① | 1 byte | 顏色分量 id | 1 表示 Y 爱葵, 2 表示 Cb , 3 表示 Cr |
② | 1 byte | 採樣率 | 高 4 bit 代表水平採樣率 反浓,低 4 bit 代表垂直採樣率萌丈。採樣率可以是 1, 2, 3, 4 |
③ | 1 byte | 量化表 id | 最後解碼時,要選擇哪一個量化表對該顏色分量進行量化 |
讀取SOS區(qū)段
代號 | 大小 | 描述 | 備註 |
---|---|---|---|
① | 1 byte | 有幾個顏色分量 | |
② | 2 * 3 bytes | 顏色分量對應的霍夫曼表 | 每個顏色分量佔用 2 bytes 雷则, 見下一張表 |
③ | 3 bytes | baseline 流程用不到 | 在 baseline 流程固定爲 0x003F00 |
② 的內(nèi)容爲下表重重復3 次:
代號 | 大小 | 描述 | 備註 |
---|---|---|---|
① | 1 byte | 顏色分量 id | 1 表示 Y辆雾,2 表示 Cb,3 表示 Cr |
② | 1 byte | 對應的霍夫曼表 id | 高 4 bit 代表直流(DC)霍夫曼表月劈,低 4 bit 代表交流(AC)霍夫曼表 |
讀取壓縮圖像數(shù)據(jù)
數(shù)據(jù)流切割來看度迂,可以看成一個接一個的 MCU 串:
[MCU1], [MCU2], [MCU3], [MCU4], ....
而一個 MCU 又可以進一步切割成(假設 Y 水平藤乙、垂直採樣率爲 2 ,Cb, Cr 水平惭墓、垂直採樣率爲 1)不同顏色分量的串連坛梁,以 Y -> Cb -> Cr 的順序:
[Y1, Y2, Y3, Y4, Cb1, Cr1]
這裏的 Y1, Y2, .... Cr1 ,都是一個 8 * 8 的 block 了腊凶,所以之後我們只要瞭解一個 block 如何讀取划咐,就大功告成了。
讀取一個block
每個block都是8*8
的吭狡,最左上角的數(shù)值就是直流變量尖殃,要使用直流霍夫曼表來解碼,而與下的63個數(shù)值為交流變量划煮。
JPEG分塊機制
因為再sequential算法中送丰,是從上至下邊收數(shù)據(jù)邊進行解碼的,所以說明JPEG文件必然是分塊進行壓縮的弛秋,因為不需要知道所有的數(shù)據(jù)就已經(jīng)可以開始解碼:
MCU是最小編碼單元Minimum Coded Unit的縮寫(通信協(xié)議上某一層上所能通過的最大數(shù)據(jù)包大小的概念為MTU)器躏。MCU的寬高并不固定為16px也不一定是正方形,而是取決于顏色分量的采樣率蟹略。
JPEG使用的為YCbCr色彩空間登失,采樣圖如上。每個顏色分量的最基本單元是block挖炬,一個block的寬揽浙、高固定為8*8
:
MCU的寬 = 8 * 最高水平采樣率
MCU的高 = 8 * 最高垂直采樣率
Cb、Cr的最左上角對應到了MCU的左上4個px:
MCU從左到右意敛、再從上到下:
一個顏色分量內(nèi)部各個block的順序一樣是從左到右馅巷、從上到下:
MCU、顏色分量草姻、block關系
讀取圖像壓縮數(shù)據(jù)時钓猬,需要先讀取MCU信息,在讀取MCU時又需要讀取block的信息撩独。
解碼 decode!
由于已經(jīng)將JPEG文件的所有區(qū)段全部讀取出來了敞曹,接下來就是簡單的轉(zhuǎn)換,就能夠還原為原始圖像數(shù)據(jù)综膀,接下來將按照步驟來依次轉(zhuǎn)換澳迫。
反量化
從DQT區(qū)段中已經(jīng)讀出了量化表,在SOF0區(qū)段中也知道了各個顏色分量所對應的量化表id剧劝,一個block和一個量化表都是8*8
纲刀,將它們對應的位置相乘就完成這個轉(zhuǎn)換了。
反zigzag
zigzag時,會將一個block以下圖的順序重新排列:
反zigzag就是要將這個過程逆轉(zhuǎn)過來進行還原
反向DCT變換
升采樣與YCbCr轉(zhuǎn)RGB顏色空間
照著公式來變換即可示绊。
最后將圖像的各個MCU拼接起來就可以得到原圖了锭部。
一個實例
下面給出一個將JPEG文件轉(zhuǎn)換成bmp文件的程序:https://github.com/MROS/jpeg_decoder/blob/master/main.cpp