1 什么是TIFF?
TIFF是Tagged Image File Format的縮寫。在現在的標准中,只有TIFF存在, 其他的提法已經舍棄不用了。做為一種標記語言,TIFF與其他文件格式最大的不同在於除了圖像數據,它還可以記錄很多圖像的其他信息。它記錄圖像數據的方式也比較靈活, 理論上來說, 任何其他的圖像格式都能為TIFF所用, 嵌入到TIFF里面。比如JPEG, Lossless JPEG, JPEG2000和任意數據寬度的原始無壓縮數據都可以方便的嵌入到TIFF中去。由於它的可擴展性, TIFF在數字影響、遙感、醫學等領域中得到了廣泛的應用。TIFF文件的后綴是.tif或者.tiff
2 TIFF文件結構
TIFF文件中的三個關鍵詞是:圖像文件頭Image File Header(IFH), 圖像文件目錄Image File Directory(IFD)和目錄項Directory Entry(DE)。每一幅圖像是以8字節的IFH開始的, 這個IFH指向了第一個IFD。IFD包含了圖像的各種信息, 同時也包含了一個指向實際圖像數據的指針。
IFH的構成:
Byte 0-1: 字節順序標志位, 值為II或者MM。II表示小字節在前, 又稱為little-endian。MM表示大字節在前,又成為big-endian。
Byte 2-3: TIFF的標志位,一般都是42
Byte 4-7: 第一個IFD的偏移量。可以在任意位置, 但必須是在一個字的邊界,也就是說必須是2的整數倍。
IFD的構成(0代表此IFD的起始位置):
Byte 0-1: 表示此IFD包含了多少個DE,假設數目為n
Byte 2-(n*12+1): n個DE
Byte (n*12+2)-(n*12+5): 下一個IFD的偏移量,如果沒有則置為0
DE的構成:
Byte 0-1: 此TAG的唯一標識
Byte 2-3: 數據類型。
Byte 4-7: 數量。通過類型和數量可以確定存儲此TAG的數據需要占據的字節數
Byte 8-11: 如果占用的字節數少於4, 則數據直接存於此。 如果超過4個,則這里存放的是指向實際數據的指針
可以用以下的圖來表示(圖來自http://www.cppblog.com/windcsn/archive/2009/03/12/1158.html)
在TIFF6.0中,定義了12種數據類型,分別是:
1 = BYTE 8-bit unsigned integer.
2 = ASCII 8-bit byte that contains a 7-bit ASCII code; the last byte
must be NUL (binary zero).
3 = SHORT 16-bit (2-byte) unsigned integer.
4 = LONG 32-bit (4-byte) unsigned integer.
5 = RATIONAL Two LONGs: the first represents the numerator
6 = SBYTE An 8-bit signed (twos-complement) integer.
7 = UNDEFINED An 8-bit byte that may contain anything, depending on
the definition of the field.
8 = SSHORT A 16-bit (2-byte) signed (twos-complement) integer.
9 = SLONG A 32-bit (4-byte) signed (twos-complement) integer.
10 = SRATIONAL Two SLONG’s: the first represents the numerator of a
fraction, the second the denominator.
11 = FLOAT Single precision (4-byte) IEEE format.
12 = DOUBLE Double precision (8-byte) IEEE format.
-個TIFF文件可能包含多個IFD,每一個IFD都是一個子文件。Baseline解碼器只要求解第一個IFD所對應的圖像數據。擴展的TIFF圖像經常包含多個IFD,每一個IFD都包含了不同的信息。
TIF圖一般由三個部分組成:文件頭(簡稱IFH)、文件目錄(簡稱IFD)、圖像數據。
一、圖像文件頭(Image File Header)
IFH數據結構包含3個成員共計8個字節(見表一):
表一 IFH結構描述
------------------------------------------------------------
名稱 字節數 數據類型 說明
------------------------------------------------------------
Byteorder 2 Integer TIF標記,其值為4D4D或4949
Version 2 Integer 版本號,其值恆為2A00
Offset to first IFD 4 Long 第一個IFD的偏移量
------------------------------------------------------------
表一說明
1.Byteorder:可能是H4D4D或H4949,H4D4D表示該圖是摩托羅拉整數格式,H4949表示該圖是Intel整數格式。
2.Version:總是H2A00,它可能是tif文件的版本,也可能用於進一步校驗該文件是否為TIF格式。
3.Offset to first IFD:第一個IFD相對文件開始處的偏移量(因為可能會有多個順序排列的IFD)。
IFD數據結構並不一定緊跟在IFH后面,相反,它常常位於第三部分圖像數據的后面,即TIF圖像文件的一般組織形式是:IFH——圖像數據——IFD。
二、圖像文件目錄(Image File Directory)
IFD是TIF圖像文件中重要的數據結構,它包含了三個成員。由於一個TIF文件中可以有多個圖像,而一個IFD只標識一個圖像的所有屬性(有的文章把“屬性”稱之為“標簽”),所以,一個TIF文件中有幾個圖像,就會有幾個IFD。IFD的結構見表二:
表二 IFD結構描述
-----------------------------------------------------------------
名稱 字節數 數據類型 說明
-----------------------------------------------------------------
Directory Entry Count 2 Integer 本IFD中DE的數量
Directory Entry(1) 12 簡稱DE,中文譯義“目錄項”
Directory Entry(2) 12
……
Directory Entry(N) 12
Offset to next IFD 4 Long 下一個IFD的偏移量
-----------------------------------------------------------------
表二說明
1.Directory Entry Count:指出在該IFD中DE的個數;
2.Directory Entry:共12個字節,結構見表三。需要指出的是,DE的個數是不定的,因為每個DE只標識了圖像的一個屬性,那么這幅圖像有N個屬性就會有N個DE,用戶甚至可添加自定義的標記屬性,這就是為什么稱TIF格式文件為“可擴充標記的文件”的原因。
3.Offset to next IFD Or NULL:下一個IFD相對於文件開始處的位置,這是一個鏈式構成。如果該數字為0,表示已經是最后一個IFD。當然,如果該TIF文件只包含了一幅圖像,那么就只有一個IFD,顯然這個偏移量也會等於0。
表三 DE結構描述
--------------------------------------------------
名稱 字節數 數據類型 說明
--------------------------------------------------
tag 2 Integer 本屬性的標簽編號
type 2 Integer 本屬性值的數據類型
length 4 Long 該類型數據的數量
valueOffset 4 Long 屬性值的存放偏移量
--------------------------------------------------
表三說明
由DE標識的圖像屬性有:圖像的大小、分辨率、是否壓縮、像素的行列數、顏色深度(單色、16色、256色、真彩色)等等。其中:
①tag:是該屬性的標簽編號(TagID),在圖像文件目錄中,它是按照升序排列的(但不一定是連續的)。這些編號在TIF格式官方白皮書中可以查到相應的含義,但遺憾的是,我們到哪兒可以找到官方白皮書呢?所以,筆者只能把網上能找得到資料(再結合自己的實驗結果)羅列出來,見表四。
②type:表示該屬性數據的類型,一般認為TIF官方指定的有5種數據類型(但也有說12種數據類型的)。見表五。
③length:該種類型的數據的個數,而不是某個數據的長度。
④valueOffset:是tagID代表的變量值相對文件開始處的偏移量,但如果變量值占用的空間不多於4個字節(例如只有1個Integer類型的值),那么該值就直接存放在valueOffset中,沒必要再另外指向一個地方了。
表四 DE中標簽編號的含義
-------------------------------------------------------------------------
TagID 屬性名稱 type 說明
-------------------------------------------------------------------------
0100 圖像寬 0003
0101 圖像高 0003
0102 顏色深度 0003 值=1為單色,=4為16色,=8為256色。
如果該類型數據個數>2個,說明是真彩圖像
0103 圖像數據是否壓縮 0003 值=05表示壓縮
0106 圖像是否采用反色顯示0003 值=01表示反色,否則表示不反色
0111 圖像掃描線偏移量 0004 圖像數據起始字節相對於文件開始處的位置
0116 圖像掃描線的數量 0004 表示圖像有幾行掃描線,實際上等於圖像高度
0117 圖像數據字節總數 0003 如果不是偶數,那么實際存放時會在后面加0
011A 水平分辯率偏移量 0005 常用計量單位是:像素/英寸
011B 垂直分辯率 偏移量 0005 常用計量單位是:像素/英寸
0131 生成該圖像的軟件名 0002 文本類型
0132 生成該圖像的時間 0002 文本類型
0140 調色板偏移量 0003 256色和16色圖像才有此屬性,而且有連續2個
調色板,但屬性的length值只表示出1個調色板
-------------------------------------------------------------------------
表四說明
①“水平(垂直)分辯率”是分數型的屬性,其值要占用8個字節,所以在valueOffset中存放的肯定是它的具體數值的偏移量,而不是數值本身。
②“生成圖像的軟件名稱”和“生成圖像的時間”這兩個字符型屬性,它們的值所占用的空間也會大於4字節,所以在valueOffset中存放的也是它們的值的偏移量,而不是值本身。
③“圖像數據字節總數”一般是個偶數,如果是奇數,那么實際存放時會在后面加一個0,但這個0不會計算在字節總數之內。
表五 DE中的數據類型
--------------------------------------------------------------------
type值 數據類型 說明
--------------------------------------------------------------------
0001 Byte
0002 Ascii 文本類型,7位Ascii碼加1位二進制0
0003 Integer
0004 Long
0005 RATIONAL 分數類型,由兩個Long組成,第1個是分子,第2個是分母
--------------------------------------------------------------------
三、圖像數據。這些數據可能是壓縮的,也可能是未壓縮的。如果經過壓縮,那么壓縮算法又有許多種,所以,圖像數據是TIF文件中最為復雜的部分,暫還沒有哪個軟件能譯出所有的壓縮算法。
四、一個 Tif 文件的實例
讓我們自己動手做一個實驗,以加深理性認識。
用系統自帶的畫圖程序新建一個17*15的白色圖像,另存為TIF文件,它的全部數據如下(因設備差異你的數據也許會有些微不同):
0000: 49 49 2A 00 4E 00 00 00 80 3F E0 50 38 24 16 0D
0010: 07 84 42 61 50 B8 64 36 1D 0F 88 44 62 51 38 A4
0020: 56 2D 17 8C 46 63 51 B8 E4 76 3D 1F 90 48 64 52
0030: 39 24 96 4D 18 80 80 00 60 00 00 00 01 00 00 00
0040: 60 00 00 00 01 00 00 00 08 00 08 00 08 00 0F 00
0050: FE 00 04 00 01 00 00 00 00 00 00 00 00 01 03 00
0060: 01 00 00 00 11 00 00 00 01 01 03 00 01 00 00 00
0070: 0F 00 00 00 02 01 03 00 03 00 00 00 48 00 00 00
0080: 03 01 03 00 01 00 00 00 05 00 00 00 06 01 03 00
0090: 01 00 00 00 02 00 00 00 11 01 04 00 01 00 00 00
00A0: 08 00 00 00 15 01 03 00 01 00 00 00 03 00 00 00
00B0: 16 01 04 00 01 00 00 00 0F 00 00 00 17 01 04 00
00C0: 01 00 00 00 2F 00 00 00 1A 01 05 00 01 00 00 00
00D0: 38 00 00 00 1B 01 05 00 01 00 00 00 40 00 00 00
00E0: 1C 01 03 00 01 00 00 00 01 00 00 00 28 01 03 00
00F0: 01 00 00 00 02 00 00 00 3D 01 03 00 01 00 00 00
0100: 01 00 00 00 00 00 00 00
簡要分析(請注意轉換16進制數據時,低位在前,高位在后):
0000-0007:文件頭,可以看出,該圖是Intel整數格式,第一個IFD的偏移量為4E。
0008-0037:圖像數據。注意最后那個0是補加的,它沒有統計在“圖像數據字節總數”屬性值中。
0038-003F:水平分辯率值。
0040-0047:垂直分辯率值。
0048-004D:顏色深度值。
004E-0107:第一個IFD。Directory Entry Count的值(004E-004F)為F,表示這個IFD中有15個DE,每個DE占用12字節,15個DE共占用180字節,加上Directory Entry Count占用的2字節,再加上
Offset to next IFD占用的4字節,這個IFD共占用186字節,換算為16進制就是BA,所以,它的數據結束於0107。Offset to next IFD的值(最后4個字節)均為0,表示整幅圖像文件只有這一個IFD。其中15個DE的描述見表六。
表六 一個Tif文件實例的DE描述
-------------------------------------------------------------------------
順號 偏移量 TagID Type length valueOffset 說明
--------------------------------------------------------------------------
1 0050 00FE Long 1 00 未知屬性值=0
2 005C 0100 Integer 1 11 圖像寬為17像素(10進制)
3 0068 0101 Integer 1 0F 圖像高為15像素(10進制)
4 0074 0102 Integer 3 48 圖像為真彩色,其值存放在48-4D
5 0080 0103 Integer 1 05 圖像數據是壓縮的
6 008C 0106 Integer 1 02 圖像不反色顯示
7 0098 0111 Long 1 08 圖像數據起始字節為8
8 00A4 0115 Integer 1 03 未知屬性值=3
9 00B0 0116 Long 1 0F 圖像掃描線有15行
10 00BC 0117 Long 1 2F 圖像共有47個字節的壓縮數據
11 00C8 011A RATIONAL 1 38 水平分辯率存放在38-3F
12 00D4 011B RATIONAL 1 40 垂直分辯率存放在40-47
13 00E0 011C Integer 1 01 未知屬性值=1
14 00EC 0128 Integer 1 02 未知屬性值=2
15 00F8 013D Integer 1 01 未知屬性值=1
--------------------------------------------------------------------------
表六說明
①水平分辯率值存放在0038-003F,占用8個字節,這8個字節是:60 00 00 00 01 00 00 00。由於它是分數類型,前4個字節是分子,其值為60000000,轉換為10進制就是96,后4個字節是分母,其值是10000000,轉換為10進制就是1,所以,分數值是:96/1,它表示每英寸96像素。
②垂直水平分辯率值存放在0040-0047,請參照①進行分析。
③顏色深度屬性,它有3個Integer類型的值,共計6字節,所以valueOffset中存放的也是其值的偏移量。它的屬性值存放在0048-004D,3個整形數據值都為8,表示這是一幅24位真彩色的圖像。