JPEG格式和標(biāo)志
JPEG文件都是以十六進制的 0xFFD8 開始烁涌,以 0xFFD9 結(jié)束袖牙。在JPEG數(shù)據(jù)中续滋,0xFF** 這樣的數(shù)據(jù)被用作標(biāo)志,表示JPEG信息數(shù)據(jù)段谜悟。0xFFD8表示SOI(Start Of Image 圖像的開始)话肖,以0xFFD9 表示EOI(End of Image 圖像結(jié)束)。這兩個特殊的標(biāo)志沒有附加的數(shù)據(jù)葡幸,而其他標(biāo)志都在標(biāo)志后面帶有附加的數(shù)據(jù)最筒。
0xFF + 標(biāo)志數(shù)字(1字節(jié)) + 數(shù)據(jù)大小(2字節(jié)) + 數(shù)據(jù)(n字節(jié))
數(shù)據(jù)大小(2字節(jié)) : 是大端順序表示,從高字節(jié)開始蔚叨。
0xFFC1 00 0C
表示標(biāo)志 0xFFC1 有0x000C(12)個字節(jié)數(shù)據(jù)床蜘,但是數(shù)據(jù)的大小"12"也包含了記錄數(shù)據(jù)大小的字節(jié)辙培,所以在0x000C后面只有10個字節(jié)的數(shù)據(jù)量。
在JPEG格式中邢锯,一些標(biāo)志描述數(shù)據(jù)后扬蕊,跟著的是SOS(Start Of Stream 數(shù)據(jù)流開始) 標(biāo)志。在SOS標(biāo)志后弹囚,就是JPEG圖像流厨相,知道EOI標(biāo)志終結(jié)。格式如下所示:
Exif中使用的標(biāo)志
從0xFFE0 ~ 0xFFEF 的標(biāo)志是“應(yīng)用程序標(biāo)志”鸥鹉,在解碼JPEG圖像的時候不是必須使用的蛮穿。這些標(biāo)志被用在用戶應(yīng)用中。
Exif也使用應(yīng)用程序標(biāo)志來插入數(shù)據(jù)毁渗,但是Exif使用APP1(0xFFE1)標(biāo)志以避免和JFIF格式?jīng)_突践磅。
JFIF是JPEG檔案交換格式,數(shù)碼相機會用這個格式來存儲照片灸异。每個EXIF格式都是從下面格式開始的:
從SOI(0xFFD8) 標(biāo)志開始府适,因此是一個JPEG文件。后面跟著一個APP1標(biāo)志肺樟。所有的Exif數(shù)據(jù)都儲存在APP1數(shù)據(jù)區(qū)中檐春。
上面的SSSS 部分表示APP1 數(shù)據(jù)大小,這個大小是包括SSSS本身的么伯。
APP1 數(shù)據(jù)從 SSSS 后開始疟暖,第一部分是特殊數(shù)據(jù),使用ASCII字符"Exif"和兩個字節(jié)的0x00田柔,它定義了是否使用Exif俐巴。
在APP1標(biāo)志數(shù)據(jù)之后,是其他JPEG標(biāo)志硬爆。
Exif數(shù)據(jù)結(jié)構(gòu)采用的是Intel 的小端字節(jié)順序方案欣舵,且包含JPEG格式的縮略圖∽嚎模總體上缘圈,Exif數(shù)據(jù)是從ASCII字符Exif和2個字節(jié)0x00開始,后面就是Exif的數(shù)據(jù)了袜蚕。
Exif 使用TIFF格式來存儲數(shù)據(jù)准验,TIFF 格式請參考官方文檔:
https://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf
如果不是adobe的partner,應(yīng)該打不開上面的網(wǎng)址廷没。不過本人已經(jīng)備份了一份tiff6 的pdf文檔在github糊饱,地址如下:
https://github.com/CainKernel/tiff6.git
下面我們介紹一下TIFF格式。
TIFF數(shù)據(jù)格式
TIFF數(shù)據(jù)格式是一種3級體系結(jié)構(gòu)颠黎,從高到低一次為 文件頭IFH(Image File Header)另锋,一個或多個IFD(Image File Directory)的包含標(biāo)記指針的目錄和數(shù)據(jù)滞项,一個文件中可以包含多個IFD,每個IFD對應(yīng)一個圖像夭坪。
+------------------------------------------------------------------------------+
| TIFF Structure |
| IFH |
| +------------------+ |
| | II/MM | |
| +------------------+ |
| | 42 | IFD |
| +------------------+ +------------------+ |
| | Next IFD Address |--->| IFD Entry Num | |
| +------------------+ +------------------+ |
| | IFD Entry 1 | |
| +------------------+ |
| | IFD Entry 2 | |
| +------------------+ |
| | | IFD |
| +------------------+ +------------------+ |
| IFD Entry | Next IFD Address |--->| IFD Entry Num | |
| +---------+ +------------------+ +------------------+ |
| | Tag | | IFD Entry 1 | |
| +---------+ +------------------+ |
| | Type | | IFD Entry 2 | |
| +---------+ +------------------+ |
| | Count | | | |
| +---------+ +------------------+ |
| | Offset |--->Value | Next IFD Address |--->NULL |
| +---------+ +------------------+ |
| |
+------------------------------------------------------------------------------+
TIFF圖像基本信息
基本信息包括大小文判、顏色模型(黑白圖像、灰度圖像室梅、調(diào)色板圖像戏仓、真彩色等)、每個像素的大小和單位等信息
每個圖像必須包含的標(biāo)簽有(含壓縮類型):
ImageWidth 256 SHORT or LONG
ImageLength 257 SHORT or LONG
XResolution 282 RATIONAL
YResolution 283 RATIONAL
ResolutionUnit 128 SHORT 1, 2 or 3
Compression 259 SHORT 1, 2 or 32773
其中顏色模型由幾個標(biāo)簽組合判斷:
PhotometricInterpretation 262 106 SHORT 0/1/2/3
BitsPerSample 258 SHORT 4 or 8
SamplesPerPixel 277 SHORT default(1)
ColorMap 320 SHORT 3 * (2**BitsPerSample)
色彩模型:
TIFF基礎(chǔ)部分定義了4中色彩模型亡鼠,不討論掩碼圖像和擴展色彩模型赏殃,主要有:二值圖像、灰度圖像间涵、調(diào)色板圖像仁热、真彩色圖像
二值圖像(Bilevel Image)
如果沒有BitsPerSample 則為二值圖
顏色模型 PhotometricInterpretation 必須為0或1
壓縮類型 Compression 1,2,32773勾哩,支持Huffman編碼
灰度圖(GrayScale Image)
有BitsPerSample抗蠢,且PhotometricInterpretation 為0或1
壓縮類型 Compression 1 或 32773,不支持Huffman編碼
調(diào)色板圖像(Palette-color Image)
PhotometricInterpretation 為3
必須包含ColorMap
BitsPerSample 為 4 或 8
Compression 為 1 或 32773思劳, 不支持Huffman編碼
真彩色圖像(RGB Full Image)
PhotometricInterpretation 為 2
必須包含SamplesPerPixel 波段數(shù)信息迅矛,值為3
BitsPerSample 必須為 8, 8, 8
沒有ColorMap
Compression 為 1 或 32773,不支持Huffman編碼
其他模型
TIFF的擴展特性中還包含CMYK 和 YCbCr等其他色彩模型
詳細信息請參考TIFF6.0規(guī)范潜叛。
條帶和分片
其中數(shù)據(jù)組織方式有條帶和分片兩種诬乞,默認為條帶方式存儲
條帶圖像必要的標(biāo)簽
RowsPerStrip 278 SHORT or LONG
StripOffsets 273 SHORT or LONG
StripByteCounts 279 SHORT or LONG
RowPerStrip 缺省值為 2^32 - 1,圖像將只有一個條帶
如果條帶數(shù)據(jù)不足钠导,末尾并不需要數(shù)據(jù)填充
分片圖像必要的標(biāo)簽:
TileWidth 322 SHORT or LONG
TileLength 323 SHORT or LONG
TileOffsets 324 SHORT or LONG
TileByteCounts 325 SHORT or LONG
每個片的大小必須是16的倍數(shù),每個片的長和寬可以不同
如果片數(shù)據(jù)不足的話森瘪,需要填充(填充數(shù)據(jù)沒有要求)
位平面
位平面由PlanarConfiguration 標(biāo)簽確定牡属,缺省時為1表示按像素組織(RGBRGB)
當(dāng)PlanarConfiguration 為2 時,為按通道存儲(RRGGBB)
當(dāng)只有1通道(SamplesPerPixel)時扼睬,位平面信息可以忽略
壓縮方式
壓縮方式由Compression 標(biāo)簽確定
基本算法:
1 = No compression
2 = CCITT modified Huffman RLE
32773 = PackBits compression, aka Macintosh RLE
擴展特性:
3 = CCITT Group 3 fax encoding
4 = CCITT Group 4 fax encoding
5 = LZW
6 = JPEG ('old-style' JPEG, later overriden in Technote2)
7 = JPEG ('new-style' JPEG)
8 = Deflate ('Adobe-style')
常見標(biāo)簽:
ImageDescription 270 ASCII
CellLength 265 SHORT
CellWidth 264 SHORT
Software 305 ASCII
DateTime 306 ASCII
Artist 315 ASCII
HostComputer 316 ASCII
Copyright 33432 ASCII
空閑空間
當(dāng)創(chuàng)建或更新TIFF文件時逮栅,文件中會有一些空閑的空間(類似malloc、free導(dǎo)致的內(nèi)存碎片)
TIFF規(guī)范中有FreeByteCounts 和 FreeOffsets 兩個標(biāo)簽用于記錄文件中的空閑空間
但是由于不同標(biāo)簽之間的弱引用關(guān)系窗宇,F(xiàn)reeByteCounts 和 FreeOffsets 記錄的信息可能并不可靠措伐,因此不能完全依賴這個信息。
忽略特性
文件中包含多個圖像(多IFD)
擴展的壓縮算法
擴展的色彩模型
多通道數(shù)大于4
文件實例
TIFF6.0文件規(guī)范中的二值圖像片段:
Header:
0000 Byte Order 4D4D
0002 42 002A
0004 1st IFD offset 00000014
IFD:
0014 Number of Directory Entries 000C
0016 NewSubfileType 00FE 0004 00000001 000000000022 ImageWidth 0100 0004 00000001 000007D0
002E ImageLength 0101 0004 00000001 00000BB8
003A Compression 0103 0003 00000001 8005 00000046 PhotometricInterpretation 0106 0003 00000001 0001 00000052 StripOffsets 0111 0004 000000BC 000000B6
005E RowsPerStrip 0116 0004 00000001 00000010006A StripByteCounts 0117 0003 000000BC 000003A6
0076 XResolution 011A 0005 00000001 000006960082 YResolution 011B 0005 00000001 0000069E
008E Software 0131 0002 0000000E 000006A6
009A DateTime 0132 0002 00000014 000006B6
00A6 Next IFD offset 00000000
Values longer than 4 bytes:
00B6 StripOffsets Offset0, Offset1, ... Offset187
03A6 StripByteCounts Count0, Count1, ... Count187
0696 XResolution 0000012C 00000001069E YResolution 0000012C 0000000106A6 Software “PageMaker 4.0”
06B6 DateTime “1988:02:18 13:59:59”
Image Data:
00000700 Compressed data for strip 10
xxxxxxxx Compressed data for strip 179
xxxxxxxx Compressed data for strip 53
xxxxxxxx Compressed data for strip 160
介紹了TIFF的基本格式后军俊,我們來看看Exif的數(shù)據(jù)結(jié)構(gòu)侥加, Exif 的數(shù)據(jù)結(jié)構(gòu)如下:
TIFF頭格式(IFH, Image File Header)
對于II (0x4949)格式,字節(jié)順序總是從低字節(jié)到高字節(jié)排序的粪躬,也就是小端存儲担败。
對于MM(0x4D4D)格式昔穴,字節(jié)順序總是從高字節(jié)到低字節(jié)排序的,也就是大端存儲提前。
雖然JPEG值采用大端字節(jié)順序存儲吗货,但Exif允許采用兩種方式存儲
接下來是42(0x2A)固定值,小端存儲的話狈网,則是 0x49492A00宙搬,大端存儲的話,0x4D4D002A
TIFF頭格式的最后4個字節(jié)表示第一個IFD的偏移量拓哺。通常是0x00000008勇垛,因為TIFF 的頭格式IFH占用了8個字節(jié)。
故TIFF頭格式的IFH格式為:
0x4949 2A00 0800 0000 (小端存儲) 或者 0x4D4D 002A 0000 0008(大端存儲)
文中的數(shù)據(jù)指針Offset最大對應(yīng)4個字節(jié)拓售,因此一個文件不能超過4GB窥摄。如果單張圖片要超過4G,則需要使用BigTiff格式础淤,請自行查閱相關(guān)資料崭放,這里不做介紹。
TIFF 圖像文件目錄(IFD, Image File Directory)
IFD 包含圖像信息數(shù)據(jù)鸽凶。開始兩個字節(jié)(EEEE)表示這個IFD所包含的目錄實體數(shù)量币砂。
然后緊跟著實體對象(每個實體12個字節(jié))。
最后一個目錄實體后面有一個4字節(jié)大小的數(shù)據(jù)玻侥,表示偏移量决摧,如果是0x00000000,則表示這個IFD是最后一個IFD凑兰。
數(shù)據(jù)格式
數(shù)據(jù)格式(上表中的FFFF)如下表所定義的一樣掌桩。
rational 表示一個分數(shù),它包含兩個signed/unsigned long integer值且第一個為分子姑食,第二個為分母
你可以用組成元素的字節(jié)數(shù)的值(Bytes/component)乘以存儲在NNNNNNNN區(qū)域中的組成元素的數(shù)量得到總長度波岛。
如果這個總長度小于4個字節(jié),那么DDDDDDDD中的是這個標(biāo)簽(Tag)的值音半,如果總長度大于等于4個字節(jié)则拷,DDDDDDDDD是數(shù)據(jù)存儲地址的偏移量
IFD數(shù)據(jù)結(jié)構(gòu)
在Exif格式中,第一個IFD 是IFD0(主圖像的IFD)曹鸠,連接IFD1(縮略圖IFD)后IFD鏈終止煌茬。帶式IFD0/IFD1 不包含想快門速度,焦距等任何數(shù)碼相機信息彻桃。
IFD0總是包含特殊的標(biāo)簽(Tag)Exif的偏移量(0x8769)坛善,它說明Exif SubIFD 的偏移量,SubIFD 包含數(shù)碼相機的信息。
Exif格式的擴展方案(Exif2.1/DCF)中浑吟,Exif SubIFD 包含了特殊標(biāo)簽 —— Exif互用偏移量(Exif Interoperability Offset)(0xA005),它指向互用的IFD笙纤。
在DCF(數(shù)碼相機格式)規(guī)范中,這個標(biāo)簽是必須且子IFD 和 IFD1 都可以使用互用的IFD组力。通常只有主圖像帶有這個標(biāo)簽省容。
一些數(shù)碼相機使用IFD數(shù)據(jù)格式來表示制造商數(shù)據(jù) —— 制造商特殊的神秘數(shù)字區(qū)。
IFD數(shù)據(jù)結(jié)構(gòu)例子:
假設(shè)下面數(shù)據(jù)是TIFF數(shù)據(jù)的第一部分:
0x0000 : 4949 2A00 0800 0000 0200 1A01 0500 0100
0x0010 : 0000 2600 0000 6987 0400 0100 0000 1102
0x0020 : 0000 4000 0000 4800 0000 0100 0000
開頭兩個字節(jié)為 II燎字, 小端存儲順序腥椒。
地址0x0004 ~ 0x0007 是 0x0800 0000, IFD 從地址 0x0008 開始
地址0x0008 ~ 0x0009 是 0x0200,實際值為2候衍,表示 IFD0 有兩個目錄實體
地址0x000a ~ 0x000b 是 0x1A01笼蛛,表示這是一個水平分辨率(XResolution)(0x011A) 標(biāo)簽,它包含了圖像的水平分辨率
地址0x000c ~ 0x000d 是 0x0500蛉鹿,這個值表示的格式是無符號分數(shù)(0x0005滨砍,對應(yīng)上面數(shù)據(jù)格式表格中的5),無符號分數(shù)的尺寸是8個字節(jié)妖异。
地址0x000e ~ 0x0011 是 0x01000000惋戏,組成的元素數(shù)量是1,無符號分數(shù)的尺寸是8個字節(jié)他膳,故所有數(shù)據(jù)總長度為1 x 8 = 8 字節(jié)响逢。
地址0x0012 ~ 0x0015 是 0x26000000,水平分辨率(XResolution)的數(shù)據(jù)存儲在0x0026位置
地址0x0016 ~ 0x0017 是 0x6987棕孙,下一個標(biāo)簽是Exif偏移(ExifOffset)(0x8769)舔亭。它的值是Exif SubIFD 的偏移量
地址0x0018 ~ 0x0019 是 0x0400,數(shù)據(jù)格式是0x0004蟀俊,對于數(shù)據(jù)格式表中的無符號長整形unsigned long
地址0x001a ~ 0x001d 是 0x01000000钦铺,組成元素數(shù)量是1,因此數(shù)據(jù)總長度為4字節(jié)
地址0x001e ~ 0x0021 是 0x11020000肢预,表示Exif SubIFD 從 0x0211開始
地址0x0022 ~ 0x0025 是 0x40000000矛洞,表示下一個IFD從0x0040開始
// 水平分辨率數(shù)據(jù)存儲的位置
地址0x0026 ~ 0x0029 是 0x48000000,分子是72(0x0048)
地址0x002a ~ 0x002d 是 0x01000000误甚,分母是1(0x0001),因此水平分辨率(XResolution)是72/1
縮略圖
Exif格式包含圖像的縮略圖谱净∫ぐ睿縮略圖通常在IFD1 后面,共有3中格式的縮略圖: JPEG格式(JPEG 使用YCbCr)壕探,RGB TIFF格式冈钦,YCbCr TIFF 格式。
Eif2.1 或者更高版本是推薦使用JPEG格式和160x120 的縮略圖李请。而DCF規(guī)范則必須使用JPEG格式和160x120的縮略圖
JPEG格式縮略圖
如果IFD1中壓縮(Compression)(0x0103)標(biāo)簽的值為6瞧筛,那么縮略圖是JPEG格式厉熟。大多數(shù)的Exif圖像使用JPEG格式的縮略圖。
在這些圖像中较幌,你可以在IFD1中JpegIFOffset(0x0201)標(biāo)簽中揍瑟,以及JpegIFByteCount(0x0202)標(biāo)簽中分別獲得縮略圖的偏移量和大小。
其數(shù)據(jù)格式為普通的JPEG格式乍炉,從0xFFD8開始绢片,到0xFFD9結(jié)束。
TIFF格式縮略圖
如果IFD1 中壓縮(Compression)(0x0103)標(biāo)簽值為1岛琼, 那么縮略圖是非壓縮的(TIFF格式)底循。
縮略圖的起點數(shù)據(jù)在StripOffset(0x0111)標(biāo)簽,縮略圖大小則是StripByeCounts(0x0117)標(biāo)簽的和
如果采用了TIFF格式縮略圖槐瑞,IFD1 標(biāo)簽中的PhotometricInterpretation(0x0106)的值為2熙涤,則縮略圖采用RGB格式。
如果壓縮標(biāo)簽的值為2困檩, 則縮略圖采用YCbCr格式祠挫。