1. 程式人生 > 實用技巧 >JPEG/Exif/TIFF格式解讀(1):JEPG圖片壓縮與儲存原理分析

JPEG/Exif/TIFF格式解讀(1):JEPG圖片壓縮與儲存原理分析

JPEG檔案簡介

JPEG的全稱是JointPhotographicExpertsGroup(聯合影象專家小組),它是一種常用的影象儲存格式, jpg/jpeg是24位的影象檔案格式,也是一種高效率的壓縮格式,檔案格式是JPEG(聯合影象專家組)標準的產物,該影象壓縮標準是國際電信聯盟(International Telecommunication Union,ITU)、國際標準化組織(International Organization for Standardization,ISO)和國際電工委員會(International Electrotechnical Commission,IEC)共同制定。JPEG標準正式地稱為ISO/IEC IS(國際標準)10918-1:連續色調靜態影象數字壓縮和編碼(Digital Compression and Coding of Continuous-tone Still Images)和ITU-T建議T.81。

JPEG是第一個國際影象壓縮標準,用於連續色調靜態影象(即包括灰度影象和彩色影象),其最初目的是使用64Kbps的通訊線路傳輸720×576 解析度壓縮後的影象。通過損失極少的解析度,可以將影象所需儲存量減少至原大小的10%。由於其高效的壓縮效率和標準化要求,目前已廣泛用於彩色傳真、靜止影象、電話會議、印刷及新聞圖片的傳送上。但那些被刪除的資料無法在解壓時還原,所以* .jpg/.jpeg檔案並不適合放大觀看,輸出成印刷品時品質也會受到影響。

JPEG檔案格式

JPEG的檔案格式一般有兩種副檔名:.jpg和.jpeg,這兩種副檔名的實質是相同的,我們可以把.jpg的檔案改名為.jpeg,而對檔案本身不會有任何影響。嚴格來講,JPEG的副檔名應該為.jpeg,由於DOS時代的8.3檔名命名原則,就使用了.jpg的副檔名,這種情況類似於.htm和.html的區別。

JPEG標準不指定任何固有的檔案格式。它只定義壓縮位元流的語法。這就產生了一定數量的檔案格式來儲存JPEG壓縮後的影象,例如JPEG檔案交換格式(JPEG File Interchange Format,JFIF),JPEG推廣到TIFF6.0、FlashPix等。但它們中的每一個都不能認為是由國際標準委員會支援的正式定義的國際標準。

JPEG格式可以分為標準JPEG漸進式JPEGJPEG2000三種格式。

標準JPEG:該型別的圖片檔案,在網路上應用較多,只有圖片完全被載入和讀取完畢之後,才能看到圖片的全貌;它是一種很靈活的圖片壓縮方式,使用者可以在壓縮比和圖片品質之間進行權衡。不過,通常來講,其壓縮比在10:1到40:1之間,壓縮比越大,品質就越差,壓縮比越小,品質就越好。JPEG格式壓縮的主要是高頻資訊,對色彩的資訊保留較好

,適合應用於網際網路,可減少影象的傳輸時間,可以支援24bit真彩色,也普遍應用於需要連續色調的影象。JPEG由於可以提供有失真壓縮,因此壓縮比可以達到其他傳統壓縮演算法無法比擬的程度。其壓縮模式有以下幾種:

  1. 順序式編碼(SequentialEncoding)

  2. 遞增式編碼(ProgressiveEncoding)

  3. 無失真編碼(LosslessEncoding)

  4. 階梯式編碼(HierarchicalEncoding)

JPEG的壓縮步驟

  1. 顏色轉換:由於JPEG只支援YUV顏色模式,而不支援RGB顏色模式,所以在將彩色影象進行壓縮之前,必須先對顏色模式進據轉換。轉換完成之後還需要進行資料取樣。一般採用的取樣比例是2:1:1或4:2:2。由於在執行了此項工作之後,每兩行資料只保留一行,因此,取樣後圖像資料量將壓縮為原來的一半。

  2. DCT變換:DCT(DiscreteConsineTransform)是將影象訊號在頻率域上進行變換,分離出高頻和低頻資訊的處理過程。然後再對影象的高頻部分(即影象細節)進行壓縮,以達到壓縮影象資料的目的。首先將影象劃分為多個8*8的矩陣。然後對每一個矩陣作DCT變換(變換公式此略)。變換後得到一個頻率係數矩陣,其中的頻率係數都是浮點數。

  3. 量化:由於在後面編碼過程中使用的碼本都是整數,因此需要對變換後的頻率係數進行量化,將之轉換為整數。由於進行資料量化後,矩陣中的資料都是近似值,和原始影象資料之間有了差異,這一差異是造成影象壓縮後失真的主要原因。

  4. 編碼:編碼採用兩種機制:一是0值的行程長度編碼;二是熵編碼(EntropyCoding)。在JPEG中,採用曲徊序列,即以矩陣對角線的法線方向作“之”字排列矩陣中的元素。這樣做的優點是使得靠近矩陣左上角、值比較大的元素排列在行程的前面,而行程的後面所排列的矩陣元素基本上為0值。行程長度編碼是非常簡單和常用的編碼方式,在此不再贅述。編碼實際上是一種基於統計特性的編碼方法。在JPEG中允許採用HUFFMAN編碼或者算術編碼。

更詳細可以參看《色彩空間RGB/CMYK/HSL/HSB/HSV/Lab/YUV基礎理論及轉換方法:RGB與YUV》、《視訊取樣,量化,編碼,壓縮,解碼相關技術原理學習筆記

Baseline JPEG/基本JPEG:這種型別的JPEG檔案儲存方式是按從上到下的掃描方式,把每一行順序的儲存在JPEG檔案中。開啟這個檔案顯示它的內容時,資料將按照儲存時的順序從上到下一行一行的被顯示出來,直到所有的資料都被讀完,就完成了整張圖片的顯示。這種圖片在web中,如果沒有給圖片指定寬高,會造成重繪。

progressive jpeg/漸進式JPEG:JPEG檔案包含多次掃描,這些掃描順尋的儲存在JPEG檔案中。開啟檔案過程中,會先顯示整個圖片的模糊輪廓,隨著掃描次數的增加,圖片變得越來越清晰。該型別的圖片是對標準JPEG格式的改進,當在網頁上下載漸進式JPEG圖片時,首先呈現圖片的大概外貌,然後再逐漸呈現具體的細節部分,因而被稱之為漸進式JPEG。這種通過HTTP2 多路複用傳遞漸進式JPEG的掃描圖層來提高感知效能和速度指數的方式已經早在2012年被Google的John Mellor注意到了。他一直在實驗SPDY協議,HTTP2的前身。

JPEG2000:一種全新的圖片壓縮發,壓縮品質更好,並且改善了無線傳輸時,因訊號不穩定而造成的馬賽克及位置錯亂等問題。另外,作為JPEG的升級版,JPEG2000的壓縮率比標準JPEG高約30%,同時支援有失真壓縮和無失真壓縮。它還支援漸進式傳輸,即,先傳輸圖片的粗略輪廓,然後,逐步傳輸細節資料,使得圖片由模糊到清晰逐步顯示。此外,JPEG2000還支援感興趣區域,也就是說,可以指定圖片上感興趣區域的壓縮質量,還可以選擇指定的部分先進行解壓。還有個優勢就是,JPEG2000從無失真壓縮到有失真壓縮可以相容

壓縮步驟

由於JPEG的有失真壓縮方式(Lossy mode of operation)並不比其他的壓縮方法更優秀,

因此我們著重來看它的有失真壓縮中最常用的基線JPEG演算法(baseline sequential)。以一幅24位彩色影象為例,JPEG的壓縮步驟分為:

顏色轉換

JPEG支援影象採用任何一個色彩空間,支援1~4個顏色分量。灰度影象顏色分量數為1。RGB、YUV、YCbCr等擁有3種顏色分量。4種顏色分量的例子是青、洋紅、黃和黑(Cyan,Magenta,Yellow,and Black,CMYK)。為了減少色度通道包含的大量的冗餘資訊,本例中採用YCbCr色彩空間。首先需要進行從RGB到YCbCr的色彩空間變換:

  • Y = 0.299000R + 0.587000G + 0.114000B

  • Cb = -0.168736R - 0.331264G + 0.500002B

  • Cr = 0.500000R - 0.418688G - 0.081312B

其中,Y表示亮度分量,Cb和Cr表示藍紅色度分量。

DC電平偏移

最初,在影象中的畫素儲存在無符號的整數中。對於數學計算,在影象中任何變換或數學計算開始之前,根本上是將這些取樣轉換成兩個補碼錶示。DC電平偏移的目的是保證輸入影象的取樣有近似地集中在零附近的動態範圍。DC電平偏移執行的影象取樣只通過無符號數表示。

方法:假設圖片分量的取樣精度為n,那麼分量中的每個畫素值應減去2的(n-1)次冪。

對於影象而言他的取樣由無符號的整數表示,例如CT(X光斷層成像)影象,動態範圍已經集中於零附近,所以不需要DC電平偏移。

子取樣

色彩空間轉換之後,影象的大多數空間資訊包含在亮度分量Y中。色度分量Cb和Cr包含大量冗餘的顏色資訊,所以我們運用子取樣較少色度資料量以在丟失少量資訊的情況下壓縮影象。基線JPEG常用的子取樣格式為4:2:0,同時支援4:2:2和4:4:4顏色格式。

DCT變換

DCT(DiscreteCosineTransform)是將影象訊號在頻率域上進行變換,分離出高頻和低頻資訊的處理過程。然後再對影象的高頻部分(即影象細節)進行壓縮,以達到壓縮影象資料的目的。首先將影象劃分為多個8*8的矩陣。然後對每一個矩陣作DCT變換。變換後得到一個頻率係數矩陣,其中的頻率係數都是浮點數。

量化

由於在後面編碼過程中使用的碼本都是整數,因此需要對變換後的頻率係數進行量化,將之轉換為整數。由於進行資料量化後,矩陣中的資料都是近似值,和原始影象資料之間有了差異,這一差異是造成影象壓縮後失真的主要原因。

在這一過程中,質量因子的選取至為重要。值選得過大,可以大幅度提高壓縮比,但是影象質量就比較差;反之,質量因子越小(最小為1),影象重建質量越好,但是壓縮比越低。對此,ISO已經制定了一組供JPEG程式碼實現者使用的標準量化值。

右圖的兩個量化表的設計是根據由Lohscheller做的心理視覺實驗來確定二維基函式的可見閾值。

編碼

從前面過程我們可以看到,顏色轉換完成到編碼之前,影象並沒有得到進一步的壓縮,DCT變換和量化可以說是為編碼階段做準備。

編碼採用兩種機制:一是0值的行程長度編碼;二是熵編碼(EntropyCoding)。

之字形排序(Zig-zag ordering)

在JPEG中,採用曲徊序列,即以矩陣對角線的法線方向作“之”字排列矩陣中的元素。這樣做的優點是使得靠近矩陣左上角、值比較大的元素排列在行程的前面,而行程的後面所排列的矩陣元素基本上為0值。

使用RLE對交流係數(AC)進行編碼

  • 行程長度編碼是非常簡單和常用的編碼方式,在此不再贅述。

    需要注意的是,AC係數的之字形序列編碼中有兩個特殊符號——(0,0)和(15,0)。第一個特殊符號指的是塊的結束(end-of-block,EOB),用來表明在之字形塊中剩餘的元素都是零。另一個特殊符號是指零遊程長度(zero-run-length,ZRL),用來表明16個零遊程。基線JPEG允許的零遊程最大長度是16個。如果這裡的零超過16個,那麼這個遊程分成幾個長度為16的零遊程。

  • 使用DPCM對直流係數(DC)進行編碼

    DCT係數量化之後,通過差分編碼對量化後的DC係數編碼。當前塊的DC係數減去前個塊的DC係數,然後對其差值進行編碼,如右圖所示。這就利用了鄰接塊DC值之間的空間相關性。

  • 熵編碼:編碼實際上是一種基於統計特性的編碼方法。在JPEG中允許採用HUFFMAN編碼或者算術編碼。而基線JPEG演算法(baseline sequential)採用的是前者。

    經過RLE編碼的AC係數可以對映成兩個標誌(RUNLENGTH,CATEGORY)和(AMPLITUDE),前者採用的是霍夫曼編碼,而後者採用的是VLI編碼。同理經過DPCM編碼的DC係數同樣可以對映成兩個標誌(CATEGORY)和(AMPLITUDE),前者採用霍夫曼編碼,後者採用VLI編碼。

    基線JPEG允許使用4個霍夫曼表,兩個用於AC係數編碼,兩個用於DC係數編碼。

如何識別JEPG檔案的

其實很簡單,就是判斷前面3個位元組是什麼,如果發現是FF D8 FF開始,那就認為它是JEPG圖片。

JPG檔案是由一段段的資料構成的組成的(segment),段的多少和長度並不是一定的。只要包含了足夠的資訊,該JPEG檔案就能夠被開啟。

JPEG格式和標記

JPEG圖片格式組成部分:SOI(檔案頭)+APP0(影象識別資訊)+ DQT(定義量化表)+ SOF0(影象基本資訊)+ DHT(定義Huffman表) + DRI(定義重新開始間隔)+ SOS(掃描行開始)+ EOI(檔案尾)

以16進位制模式開啟JPG檔案,就會發現

JPEG 檔案中有一些形如 0xFF** 這樣的資料,它們被稱為“標誌(Marker)”,它表示 JPEG 資訊資料段。例如 0xFFD8 代表 SOI(Start of image), 0xFFD9 代表 EOI(End of image)。

標誌 0xFFE0~0xFFEF 被稱為 "Application Marker",它們不是解碼 JPEG 檔案必須的,可以被用來儲存配置資訊等。EXIF 也是利用這個標誌段來插入資訊的,具體來說,是 APP1(0xFFE1) Marker。所有的 EXIF 資訊都儲存在該資料段。

------------------
名稱標記碼說明
------------------
SOID8檔案頭
EOID9檔案尾
SOF0C0幀開始(標準JPEG)
SOF1C1同上
DHTC4定義Huffman表(霍夫曼表)
SOSDA掃描行開始
DQTDB定義量化表
DRIDD定義重新開始間隔
APP0E0定義交換格式和影象識別資訊
DNLDC標記碼
COMFE註釋

段型別有30種,但只有10種是必須被所有程式識別的,其它的型別都可以忽略。

JPEG format and Marker

SOI Marker Marker XX size=SSSS Marker YY size=TTTT SOS Marker size=UUUU Image stream EOI Marker
FFD8 FFXX SSSS DDDD...... FFYY TTTT DDDD...... FFDA UUUU DDDD.... I I I I.... FFD9

0xFFE0~0xFFEF之間的標記被叫做 "應用標記", 它們在JPEG影象解碼中不是必須存在的. 它們被使用於使用者的應用程式之中. 例如, 老款的olympus/canon/casio/agfa 數字相機使用 JFIF(JPEG檔案交換格式/JPEG File Interchange Format)來儲存影象. JFIF 使用 APP0(0xFFE0) 標記來插入數字相機的配置資訊資料和縮圖.

Exif也使用應用標記來插入資料, 但是Exif 使用 APP1(0xFFE1)標記來避免與JFIF格式的 衝突. 且每一個 Exif 檔案格式都開始於它, 如

SOI 標記 標記 XX 的大小=SSSS 標記 YY 的大小=TTTT SOS 標記 的大小=UUUU 影象資料流 EOI 標記
FFD8 FFXXlo0p SSSS DDDD...... FFYY TTTT DDDD...... FFDA UUUU DDDD.... I I I I.... FFD9

Exif也使用應用標記來插入資料, 但是Exif 使用 APP1(0xFFE1)標記來避免與JFIF格式的 衝突. 且每一個 Exif 檔案格式都開始於它, 如;

Marker used by Exif

0xFF+Marker Number(1 byte)+Data size(2 bytes)+Data(n bytes)

SOI Marker APP1 Marker APP1 Data Other Marker
FFD8 FFE1 SSSS 457869660000 TTTT...... FFXX SSSS DDDD......

該影象檔案從SOI(0xFFD8) 標記開始, 因此它是一個 JPEG 檔案. 後面馬上跟著 APP1 標記. 而它的所有 Exif資料都被儲存在 APP1 資料域中. 上面的 "SSSS" 這部分表示 APP1 資料域 (Exif data area)的大小. 請注意這裡的大小 "SSSS" 包含描述符本身的大小.

在 "SSSS"後面, 是 APP1 的資料. 其中第一個部分是一個特殊的資料,它用來標識是否是 Exif, 其值是ASCII 字元 "Exif" 和 兩個0x00位元組 的組合字串.

在 APP1 標記域的後面是, 跟隨著其他的 JPEG 標記

exif資料解析

如果圖片圖片是16進位制資料,如下:

FF D8FF E0 00 10 4A 46 49 46 00 01 02 01 00 60 00 60 00 00FF E1 08 32 45 78 69 66 00 00 49 49 10 60 00 60 20 00 ……FFD9

那麼FF D8為SOI標誌位,FF E0為exif檔案起始位,後面四位 為exif marker資訊的長度。取這個長度的資料解析為TIFFdata資料,exif直接解析為字串貌似也沒有問題。

FF D8

FFE000 104A 46 49 46 00 01 02 01 00 60 00 60 00 00 mark0,00 10 =16位

FFE108 3245 78 69 66 00 00 49 4910 60 00 60 20 00 ……mark1,00 10 =2098位

……

Image stream

FFD9

每個段都是由FFxx開頭,其中xx是段的標識,接著就是就是兩位的端長度。後面跟著的就是資料。前面的元資料外讀取完成後,後面的二進位制資料就是圖片資料。

資料大小描述符(2個位元組) 是 "Motorola" 的位元組順序, 資料的低位被存放在高地址,也就是 BigEndian. 請注意上面中的 "資料內容" 中包含他前面的資料大小描述符, 如果下面的是一個標記的話;

這個長度的表示方法是按照高位在前,低位在後的,與 Intel 的表示方法不同。比方說一個段的長度是0x12AB,那麼它會按照0x12,0xAB的順序儲存。但是如果按照Intel的方式:高位在後,低位在前的方式會儲存成0xAB,0x12,而這樣的儲存方法對於JPEG是不對的。這樣的話如果一個程式不認識JPEG檔案某個段,它就可以讀取後兩個位元組,得到這個段的長度,並跳過忽略它。

關於exif資訊解碼,請閱讀《JPEG/Exif/TIFF格式解讀(2):圖片元資料儲存及EXIF詳解

jpeg10中必須的段型別

這裡列舉10種必備的段型別

APP0影象識別資訊

-------------------------------------------------
名稱位元組數值說明
-------------------------------------------------
段標識1FF
段型別1E0
段長度20010如果有RGB縮圖就=16+3n
  (以下為段內容)
交換格式54A46494600“JFIF”的ASCII碼
主版本號1
次版本號1
密度單位10=無單位;1=點數/英寸;2=點數/釐米
X畫素密度2水平方向的密度
Y畫素密度2垂直方向的密度
縮圖X畫素1縮圖水平畫素數目
縮圖Y畫素1縮圖垂直畫素數目
(如果“縮圖X畫素”和“縮圖Y畫素”的值均>0,那麼才有下面的資料)
RGB縮圖3×nn=縮圖畫素總數=縮圖X畫素×縮圖Y畫素

說明:

  • JFIF是JPEG File Interchange Forma的縮寫,即JPEG檔案交換格式,另外還有TIFF等格式,很少用

  • “如果有RGB縮圖就=16+3n”是什麼意思呢?比如說“縮圖X畫素”和“縮圖Y畫素”的值均為48,就表示有一個48×48畫素的縮圖(n=48×48),縮圖是24位真彩點陣圖,用3個位元組來表示一個畫素,所以共佔用3n個位元組。但大多數JPG檔案都沒有這個“雞肋”縮圖。

DQT定義量化表

--------------------------------------------------------------------------
名稱位元組數值說明
--------------------------------------------------------------------------
段標識1FF
段型別1DB
段長度243其值=3+n(當只有一個QT時)
(以下為段內容)
QT資訊10-3位:QT號
4-7位:QT精度(0=8bit,1位元組;否則=16bit,2位元組)
QTnn=64×QT精度的位元組數

說明:

  • JPEG檔案一般有2個DQT段,為Y值(亮度)定義1個, 為C值(色度)定義1個。

  • 一個DQT段可以包含多個QT, 每個都有自己的資訊位元組

參考資料:

圖片檔案Exif資訊詳細說明 blog.sina.com.cn/s/blog_651251e60102uz3d.html#AboutExif

影象Exif資訊 元資料(Metadata) https://www.jianshu.com/p/a6d67df60e7e

關於圖片檔案旋轉JPEG與EXIF資訊https://blog.csdn.net/yulimin/article/details/102827865

https://www.media.mit.edu/pia/Research/deepview/exif.html

https://baike.baidu.com/item/Exif/422825?fr=aladdin

讀取JPG圖片的Exif屬性(一) - Exif資訊簡介https://blog.csdn.net/fioletfly/article/details/53605959

讀取JPG圖片的Exif屬性(二) - C程式碼實現 https://blog.csdn.net/fioletfly/article/details/54094940

讀取JPG圖片的Exif屬性(三) - Exif屬性讀取GPS資訊程式碼(C/C++實現)https://blog.csdn.net/fioletfly/article/details/54133422

在jpg圖片新增Exif資訊的C程式實現https://blog.csdn.net/psy6653/article/details/79658144

JPEG新增EXIF https://blog.csdn.net/weixin_43549602/article/details/84654965

jpeg圖片格式詳解https://blog.csdn.net/yun_hen/article/details/78135122

壓縮演算法——JPEG2000 編解碼原理https://blog.csdn.net/ytang_/article/details/76571635

PNG、JPEG、BMP等幾種圖片格式詳解 https://www.jianshu.com/p/f5557c0e689e

使用HTTP2和漸進式JPEG圖片更快的載入影象 https://www.zcfy.cc/article/performance-calendar-raquo-even-faster-images-using-http2-and-progressive-jpegs-2216.html

轉載本站文章《JPEG/Exif/TIFF格式解讀(1):JEPG圖片壓縮與儲存原理分析》,
請註明出處:https://www.zhoulujun.cn/html/theory/multimedia/CG-CV-IP/8396.html