TIF图像数据结构(转)
TIF图像数据结构之研究
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位真彩色的图像。
五、获取tif格式图片宽高度的代码
Sub command1__Click()
Dim strFile As String '文件名
Dim strFileType As String 'TIF标记
Dim iffsetIFD As Long '第一个IFD的偏移量
Dim iCountDE As Integer 'DE的数量
Dim lWidth As Long '图像宽度
Dim lHeight As Long '图像高度
Dim Temp1 As Integer, Temp2 As Long, i As Integer, k As Integer
strFile = "D:\1.tif"
Open strFile For Binary As #1
strFileType = String(2, 0)
Get #1, , strFileType '获取TIF标记
If strFileType <> "II" And strFileType <> "MM" Then Close #1: Exit Sub
Get #1, , Temp1 '版本号废弃
Get #1, , iffsetIFD '获取第一个IFD的偏移量
Seek #1, iffsetIFD + 1 '设置下一个读出位置为第一个IFD的偏移量
Get #1, , iCountDE '获取第一个IFD中DE的数量
For i = 1 To iCountDE
Get #1, , Temp1 '获取属性的标签编号
If Temp1 = 256 Then '如果是图像宽
Get #1, , Temp1 '废弃
Get #1, , Temp2 '废弃
Get #1, , lWidth
k = k + 1
ElseIf Temp1 = 257 Then '如果是图像高
Get #1, , Temp1 '废弃
Get #1, , Temp2 '废弃
Get #1, , lHeight
k = k + 1
Else '否则这些数据废弃
Get #1, , Temp1
Get #1, , Temp2
Get #1, , Temp2
End If
If k = 2 Then Exit For
Next i
Close #1
Debug.Print "图像宽:" & lWidth & vbCrLf & "图像高:" & lHeight
End Sub