首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

TIFF文件格式详细说明

2022-01-07 来源:华拓网
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都包含了不同的信息。

3 TIFF,TIFF/EP以及DNG的关系

TIFF/EP的全称是\"Tag Image File Format / Electronic Photography \"。 它是一个名为“Electronic still-picture imaging – Removable memory – Part 2: TIFF/EP image data format”ISO标准, 标准号为ISO 12234-2

DNG(Digital Negative)是Adobe开发的一种开放的raw image file format。 里面使用的tag基本上都定义在TIFF或者TIFF/EP中, 在DNG Sepcification中只是定义或者建议了数据的组织方式,颜色空间的转换等等。

就我个人的理解,这三者之间的关系应该是这样的:

(1) TIFF和DNG同为Specification,分别定义了后缀名为.tif/.tiff和.dng的文件格式 (2) 同时在TIFF Specification也定义个baseline及部分扩展的tag。TIFF/EP则定义并规范了在电子影像中所使用的TAG。

(3) DNG同时与TIFF和TIFF/EP兼容,并包含了EXIF和XMP信息。DNG实际上就是扩张的TIFF, 把DNG的扩展名改成TIF就可以直接预览图片 (4) 虽然版权都归Adobe所有,但都可以无偿使用

在DNG出现以前, 各个数码相机制造商都有自己的格式, 比如Canon(cr2/crw), Nikon(nef), Olympus(orf), Pentex(pef)等等。之所以出现这么多格式,一方面的原因是在这之前没有统一的raw格式, 但更重要的是,各个厂商希望用这个只对自己公开的数据格式来保护自己的私密信息。Adobe推出DNG希望能一统raw的天下。但很遗憾,只有极少的数码制造商响应,比如sony,hasselblad, 目前的结果也仅仅是多了一种raw的格式。 虽然如何, DNG仍然是成功的。由于有很成熟的DNG编解码及转换公司, 很多小厂商乐

于使用DNG作为自己的文件格式。随着时间的推进,迫于消费者的意愿,大的数码厂商被迫支持DNG。 最后DNG统一这个数码raw格式仍然是大势所趋。

4 TIFF的特点

(1)应用广泛。①TIFF可以描述多种类型的图像;②TIFF拥有一系列的压缩方

案可供选择;③TIFF不依赖于具体的硬件;④TIFF是一种可移植的文件格式。

(2)TIFF具有可扩展性。在TIFF 6.0中定义了许多扩展,它们允许TIFF提供以下通用功能:①几种主要的压缩方法;②多种色彩表示方法;③图像质量增强;④特殊图像效果;⑤文档的存储和检索帮助。

(3)格式复杂。TIFF文件的复杂性给它的应用带来了一些问题。一方面,要写一种能够识别所有不同标记的软件非常困难。另一方面,一个TIFF文件可以包含多个图像,每个图像都有自己的IFD和一系列标记,并且采用了多种压缩算法。这样也增加了程序设计的复杂度。

5 TIFF的局限及将来的发展

TIFF的最大局限在于用4byte来表示偏移量,这样导致文件最大只能有4G。 在20年前指定TIFF标准的时候可能觉得4G足够用了。但是现在这确实成了制约TIFF反展的一个瓶颈。 目前BigTIFF已经提出用8个字节来表示偏移量。这样数据量应该足够大了。也许在不久的将来,这会成为新的tiff的baseline

6基本TIFF TAGS

本页主要摘自 http://www.awaresystems.be/imaging/tiff/tifftags/baseline.html。每一个TAG均有原始链接,可以点击查看详细的描述。

这些基本Tag是所有TIFF编解码器必须支持的Tag

码 十进十六名称 简短描述 制码 进制 新的子文件类型标识 LONG 长度为1 用比特来标识图像的类型 Bit0如果是1代表缩略图 Bit1如果是1代表多页图像中的某一页 Bit2如果是1代表它是透明度掩码图像 其余的位数暂时没有定义。与SubfileType的是,此Tag用比特位来区分文件类型而不是用值来区分 子文件类型标识 SHORT 长度为1 1 全分辨率图像 255 00FF SubfileType254 00FE NewSubfileType2 缩小分辨率的图像 3 多页图像的某一页 过时的Tag,已不再使用。 256 257 258 0100 ImageWidth图像宽度 SHORT或者LONG 长度为1 0101 ImageLength图像高度 SHORT或者LONG 长度为1 0102 BitsPerSample每个分量的Bit数 SHORT 长度为SamplesPerPixel 压缩类型 SHORT 长度为1 随着TIFF的不断扩张,目前支持多达几十种的压缩方式。就我个人看来,最需要关注的有以下两个值: 259 0103 CompressionCompression=1: 没有压缩 Compression=7:JPEG压缩。 如果是RGB图像并且SamplesPerPixel=3,则是标准的有损JPEG压缩。如果是CFA图像,则是Lossless JPEG 颜色空间 SHORT 长度为1 0 = WhiteIsZero. 应用于灰度或者二值图像, 0对应最亮灰度. 1 = BlackIsZero. 应用于灰度或者二值图像. 0对应最暗灰度。 0106 PhotometricInterpretation2 = RGB. 正常RGB图像,存储顺序为R,G,B. 3 = Palette color. 索引图像, ColorMap必须定义,SamplesPerPixel必须1. 262 32803 = CFA (Color Filter Array) 263 0107 Threshholding定义了转换成二值图像的阈值,忽略之 The width of the dithering or halftoning matrix used to create a dithered or halftoned bilevel file. The length of the dithering or halftoning matrix used to create a dithered or halftoned bilevel file. 在同一字节中的逻辑顺序。一般不做定义,要定义的话建议用1 264 0108 CellWidth265 0109 CellLength266 270 271 272 273 010A FillOrder010E ImageDescription010F Make字符串, 对图像的描述 字符串, 生产厂商的描述 0110 Model字符串 0111 StripOffsets每个Strip的偏移量 SHORT或者LONG N = StripsPerImage for PlanarConfiguration equal to 1; N = SamplesPerPixel * StripsPerImage for PlanarConfiguration equal to 2 274 0112 OrientationThe orientation of the image with respect to the rows and columns. 277 0115 SamplesPerPixel每个象素的通道数 SHORT 长度为1 每个Strip有多少行 SHORT或者LONG 长度为1。Default是无限大 278 0116 RowsPerStripStripsPerImage = floor ((ImageLength + RowsPerStrip - 1) / RowsPerStrip). 每个Strip的长度 SHORT或者LONG 279 0117 StripByteCountsN = StripsPerImage for PlanarConfiguration equal to 1; N = SamplesPerPixel * StripsPerImage for PlanarConfiguration equal to 2 280 281 0118 MinSampleValue0119 MaxSampleValueThe minimum component value used. The maximum component value used. The number of pixels per ResolutionUnit in the ImageWidth direction. The number of pixels per ResolutionUnit in the ImageLength direction. 282 011A XResolution283 011B YResolution284 288 011C PlanarConfiguration0120 FreeOffsetsHow the components of each pixel are stored. For each string of contiguous unused bytes in a TIFF file, the byte offset of the string. For each string of contiguous unused bytes in a TIFF file, the number of bytes in the string. The precision of the information contained in the GrayResponseCurve. For grayscale data, the optical density of each possible pixel value. The unit of measurement for XResolution and YResolution. Name and version number of the software package(s) used to create the image. Date and time of image creation. Person who created the image. The computer and/or operating system in use at the time of image creation. 调色板 Description of extra components. Copyright notice. 289 0121 FreeByteCounts290 0122 GrayResponseUnit291 0123 GrayResponseCurve296 0128 ResolutionUnit305 0131 Software306 315 316 0132 DateTime013B Artist013C HostComputer320 338 0140 ColorMap0152 ExtraSamples33432 8298 Copyright

解码:

//首先定义一些必须的全局变量和一些有用的函数,主要是读取各种数据类型的函数 short order;

FILE *ifp = ifp = fopen (\"filename.tiff\

ushort CLASS sget2 (uchar *s) {

if (order == 0x4949) /* \"II\" means little-endian */ return s[0] | s[1] << 8;

else /* \"MM\" means big-endian */ return s[0] << 8 | s[1]; }

ushort CLASS get2() {

uchar str[2] = { 0xff,0xff }; fread (str, 1, 2, ifp); return sget2(str); }

unsigned CLASS sget4 (uchar *s) {

if (order == 0x4949)

return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; else

return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; }

#define sget4(s) sget4((uchar *)s) unsigned CLASS get4() {

uchar str[4] = { 0xff,0xff,0xff,0xff }; fread (str, 1, 4, ifp); return sget4(str); }

unsigned CLASS getint (int type) {

return type == 3 ? get2() : get4(); }

float CLASS int_to_float (int i) {

union { int i; float f; } u; u.i = i; return u.f; }

double CLASS getreal (int type) {

union { char c[8]; double d; } u; int i, rev; switch (type) {

case 3: return (unsigned short) get2(); case 4: return (unsigned int) get4(); case 5: u.d = (unsigned int) get4(); return u.d / (unsigned int) get4(); case 8: return (signed short) get2(); case 9: return (signed int) get4(); case 10: u.d = (signed int) get4(); return u.d / (signed int) get4(); case 11: return int_to_float (get4()); case 12:

rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234)); for (i=0; i < 8; i++) u.c[i ^ rev] = fgetc(ifp); return u.d;

default: return fgetc(ifp); } }

//先解IFH,得到order和第一个IFD的偏移量 //然后解IFD

//最后是图像数据

//对于多个IFD,采用同样的处理方法 int CLASS parse_tiff () { int doff;

fseek (ifp, 0, SEEK_SET); order = get2();//\"II\"或者\"MM\" get2();//这个值应该是42, 跳过之 doff = get4();//第一个IFD的偏移量 fseek (ifp, doff, SEEK_SET); parse_tiff_ifd ();

//根据从Tag中得到的值去获取或者解压相应的图像数据 }

int CLASS parse_tiff_ifd () {

entries = get2();

if (entries > 512) return 1; while (entries--) {

//先读取Tag,Type和Count的值

//根据Type和Count确定存储的是值还是位置, }

//获取下一个IFD的偏移量 }

因篇幅问题不能全部显示,请点此查看更多更全内容