1+1=10

记记笔记,放松一下...

图像格式tiff小记

一个很古老,很简单 的图像格式;同时又是存在各种扩展,又超级复杂的图像格式。

TIFF(Tag Image File Format)是用于存储位图图像的计算机文件格式,在印刷行业和摄影界等很流行。它被扫描仪、传真机、文字处理、光学字符识别、桌面出版系统、图像处理、页面布局等程序广泛的支持。

TIFF格式由Aldus公司创建,最新版本(Tiff 6.0)发布于1992年。1994年Adobe Systems收购Aldus。

TIFF、PNG、JEPG是三种支持(deep-color)的图像格式。

Tiff 6.0 规格书

Tiff6.0 规格书包含下列部分:

  • Part1: 基线TIFF (Baseline TIFF)
  • Part2: TIFF扩展 (TIFF Extensions)
  • Part3: 附件 (Appendices)

基线TIFF(Baseline TIFF)

  • 多页面或子文件(Multiple subfiles)
    • 每个TIFF文件可以包含多页图像(multi-page images)
    • 每一个图像需要一个IFD(Image File Directory)
    • 每个IFD定义一个子文件(subfile)。
  • 带(Strips)
    • 一个图像可以有多个带(Strip)构成。
    • 每一个带由一行或多行图像数据构成,每个带可以使用不同的压缩算法。
    • 如果没有Strip的标记,认为图像只有一个Strip构成。
  • 压缩(Compression)
    • 1 无压缩 (默认)
    • 2 CCITT Group 3 1(只用于二值图像)
    • 32773 PackBits Compression
  • 图像类型
    • 二值图像 bilevel
    • 灰度图像 grayscale
    • 调色板 pallette-color
    • 真彩图像 RGB full-color
  • 字节序
    • "II"(Intel byte ordering)小端
    • "MM"(Motoroia byte ordering)大端
  • 其他字段(Other TIFF fields)
    • 规范中没有的字段,Reader需要能处理并忽略

TIFF扩展(TIFF Extensions)

引入更多的图像类型(CMYK、YCbCr、HalftoneHints、Tiled、CIELab)和压缩格式(CCITT T.4 bilevel、CCITT T.6 bilevel、LZW、JPEG);引入SUBIFD标签支持图像树(Image Trees);私有Tag。

  • Image Trees
    • SUBIFD 用于标记子IFD
  • Tiled
    • 一个TIFF图像可以有多个大小相同的图像平铺构成,类似于Strips。
    • Baseline Reader不要求读Tiled图像。
  • Private tags
    • 32768~64999和65536及以上 的Tag 是私有的,仅对个人或组织有意义,但是需要向Adobe申请,由Adobe进行分配,以避免冲突。(TIFF/EP定义的一些新标签位于该段)
    • 65000~65535的Tag,可以复用,无需注册登记
  • Private IFD
    • 如果需要10个以上的私有Tag,考虑使用私有IFD
    • 定义一个类型为LONG或IFD类型的私有Tag,其值作为offset指向其他区域(该区域怎么用是完全自由的)。

压缩格式

关注 LZW JPEG ZIP

  • LZW 之所以不再TIFF6.0 BaseLine里面,是因为当时有专利。(2003年过期)
  • LZW 对16位深度的图像,压缩效果很不好,甚至比压缩前体积更大。
  • JPEG: TIFF 6.0引入的 "6"(老的,libtiff对其支持也不好); TIFF Technical Note#2 引入的 “7”(新的,也在TIFF/EP中使用)
  • ZIP(Deflate/Inflate) 放气充气,值为“8”:TIFF Technical Note#2引入
  • ZIP(Deflate/Inflate),值为32946:存在时间更早,“8”和它通用
    • Photoshop可以读,但写时使用"8"??(Fix me!!)

TIFF/EP

TIFF/EP(Tag Image File Format/Electronic Photography) 是数码图像文件的国际标准 ISO 12234-2 。文件后缀名也是 .tiff 或 .tif。该标准发布于2001年。

Adobe 的 DNG 格式基于 TIFF/EP 标准(兼容)。

当前数码相机保存图片的工业标准是 Exif/DCF。

与TIFF6.0、EXIF的关系

  • TIFF/EP遵守 TIFF6.0 的标准,并使用和TIFF6.0同样的文件头。
    • 但是它定义了一些放置到第一个IFD中的标签(TAG),并忽略了不少TIFF6.0中的标签。
    • TIFF/EP不允许缺省值,所有的值必须显式设置。
  • TIFF/EP和Exif标准有一些显著的区别。
    • Exif标准中位于 Exif Sub-IFD 的标签现在直接位于第一个 IFD中。
    • Exif IFD Sub-IFD,互操作的 Sub-IFD以及MakerNode都被省略。
    • TIFF/EP 定义了一个处理缩微图的方法。该方法不同于Exif标准中的方法。
    • TIFF/EP 重新定义了一些 Exif标准中定义的标签。

压缩格式

TIFF/EP可以存储无压缩格式,或者JPEG基线DCT-Based有损压缩。TIFF/EP允许使用其他的格式,但不强制要求Reader能读。

不同于TIFF6.0中,压缩格式默认是无压缩,可以省略Tag(259),TIFF/EP必须通过Tag来指定,不能省略。

缩微图必须是无压缩的,即:IFD的Tag(259)值必须是1。(当主图像采用JPEG压缩或其他压缩格式时,必须存在缩微图,且需要在第一个IFD中,以便与TIFF6.0BaseLine Reader兼容)

DNG(Digital Negative)

文件后缀: .dng

DNG是TIFF 6.0格式的扩展,并且与TIFF/EP兼容。一个DNG文件同时遵守DNG规范和TIFF/EP标准是可行的(不强制要求)。

  • DNG建议使用SubIFD树(见TIFF/EP中描述)。SubIFD链(chain)不被支持。
  • DNG建议第一个IFD中包含一个低分辨率的缩微图(如TIFF/EP规范所描述),但不强制。

对Reader、Writer的要求

Reader

  • Reader必须能处理多页的TIFF文件,但不强制要求Baseline Reader读第一个IFD之后的任何一个IFD(换言之,大量的Baseline Reader可能只读第一个IFD)。
  • Reader必须支持BaseLine中的三种压缩方式(无压缩、CCITT Group3 1、PackBits Compression)。注:TIFF/EP的Reader必须支持(无压缩、JPEG压缩)。
  • Reader必须能读取大端和小端的TIFF图像
  • Reader必须准备好处理并能忽略不认识(TIFF规范中未定义)的Tag
  • Reader不能拒绝读取可选Field(比如Make、Model、DateTime等)不存在的TIFF文件。
  • Reader必须能读取缺省Field存在和不存在的情况。
  • Reader应当跳过不认识的字段类型(比如不排除以后会有新的类型)的Field
  • TIFF可能包含新的Pixel类型,如果字段SampleFormat存在且其值不为1,BaseLine Reader需要结束读流程。
  • TIFF中的单像素可能包含超出我们想象的通道,BaseLine Reader需要借助SmaplesPrePixel和BitsPreSample字段的值优雅地跳过它们。

Writer

  • 缺省的Field,可写可不写。
  • TIFF6.0要求:如果TIFF中有多个页面,第一个必须是全分辨率图像,后续的图像(比如缩减分辨率图像)可以按任何顺序。对这些图像,Reader需要遍历相应的IFD来决定如何处理
    • 但是TIFF/EP 以及DNG都建议在IFD0中放置缩微图。
  • TIFF6.0要求:任何引用都不能在多处出现。

TIFF格式

TIFF文件结构

TIFF是图像文件格式,它以一个8字节的文件头开始的,文件头指向一个IFD(Image File Directory),IFD包含图像的信息,以及一个指向真实数据的指针。

Tiff File Structure

文件头

文件头固定占用8个字节。

偏移(offset) 数据类型(DataType) 值(Value)
0 Word 字节序指示:"II"代表小端,"MM"代表大端。影响所有的16位或32位整数
2 Word 版本号 (始终是 42)
4 Unsigned Long 第一个 IFD 的偏移值,偏移值总是相对于TIFF文件的,本文件的第一个字节偏移值是0。

注:TIFF/EP标准建议判断版本时使用 VERSION >= 42,而不是VERSION==42

IFD(Image File Directory)

一个TIFF文件至少包含一个IFD。

偏移(offset) 数据类型(DataType) 值(Value)
0 Word 本IFD中的Tag数
2+x*12 Tag structure Tag data
2+(本IFD中Tag数)*12 Unsigned Long 下一个IFD在文件内的偏移值, 如果没有则为0。

一个IFD中至少包含一个DE(Directory entry),最多包含65535个?所有的Tag需要按升序排序。每一个Tag精确占12个字节。

IFD Entry(Tag)

TIFF field:包含Tag和其值的逻辑实体(entry)。每一个Field都有一个关联的Count,也就是说所有的Field都是一个一维的数组,即使是大多数Field只包含一个值。

偏移(offset) 数据类型(DataType) 值(Value)
0 Word Tag标识
2 Word Tag数据的数据类型
4 Unsigned Long 值的个数(注意,不是字节数,比如单个SHORT,是1不是2)
8 - Tag数据或数据在文件内的偏移值

如果 数据大小*个数 <=4,则可以直接存储(小于4,则左对齐,存在低位),反之则需要在其他地方存储,此处只存储偏移值。

注意: * 偏移值不能认为是LONG类型 * TIFF标准禁止在Tag数据中包含偏移值,标准中定义的(TileOffsets、StripOffsets、...)除外。

数据类型

类型 描述
1=BYTE 8位无符号数
2=ASCII 7位的ASCII码,最后一个字节需要是NUL。(可以包含多个字符串,每个都以NUL结束,COUNT是指所有字节数)
3=SHORT 16位无符号数
4=LONG 32位无符号数
5=RATIONAL 两个LONG,前者分子后者分母
6=SBYTE 8位有符号数
7=UNDEFINED 8位字节,可以存储任何东西
8=SSHORT 16位有符号数
9=SLONG 32位有符号数
10=SRATIONAL 两个SLONG,前者分子后者分母
11=FLOAT 单精度浮点(32位)
12=DOUBLE 双精度浮点(64位)
13=IFD 32位无符号数,是指向IFD的offset值(Adobe Thchnology Note)
16=LONG8 BigTIFF 64位无符号数
17=SLONG8 BigTIFF 64位有符号数
18=IFD8 BigTIFF 64位无符号数,是指向IFD的offset值

如果Reader遇到不认识的TYPE,要跳过该Tag。

一些可选Field

描述性的:

Tag名称 Dec Hex 数据类型 说明
Artist 315 13B ASCII - 图像创建者(某些老TIFF用于存放版权说明)。系统登录用户
Copyright 33432 8298 ASCII - 版权说明
DateTime 306 132 ASCII YYYY:MM:DD HH:MM:SS 包含NUL在内,共20字节,TIFF/EP下强制存在
HostComputer 316 13C ASCII - 图像创建时的计算机或操作系统
ImageDescription 270 10E ASCII - 图像的主题,比如"1988 company picnic"
Make 271 10F ASCII - 创建图像的工具(比如扫描仪)制造商。聚束SEM具体名字
Model 272 110 ASCII - 工具(比如扫描仪)的Model名或数字。聚束SEM型号
Software 305 131 ASCII - 创建图像的软件名字或版本号。聚束SEM控制软件名字
TIFF扩展 DocumentName 269 10D ASCII - 文档名,本TIFF通过扫描哪个文件得到的
TIFF扩展 PageName 285 11D ASCII - 页面名,通过扫描那个页面得到
TIFF扩展 PageNumber 297 129 SHORT 页号,总页数 两个数字

有其他意义的:

Tag名称 Dec Hex 数据类型 说明
NewSubfileType 254 FE LONG - Bit0为1表示是分辨率缩减的图像,Bit1为1表示多页图像中单独1页,Bit2为1表示是另一个图像透明度掩码。默认值为0
Orientation 274 112 SHORT - Baseline Tiff下取值范围1~8,默认值为1
PlanarConfiguration 284 11C SHORT 1或2 像素存储格式:块(Chunky)或面(Planar),默认1
TIFF/EP SubIFDs 330 14A LONG - 指向各个子IFD的文件偏移量,由Adobe公司定义
TIFF/EP TimeZoneOffset 34858 882A SSHORT - 1~2个有符号short,第二个数表示是设置哪个DateTime的时区
DNG DNGPrivateData 50740 C634 BYTE - 必须以一个NUL结尾的ASCII字符串(制造商名字)开头,之后的数据必须是自包含的,且需要与字节序无关。(自由写私有数据)

不建议用:

Tag名称 Dec Hex 数据类型 说明
SubfileType 255 FF LONG - 废弃,建议使用NewSubfileType

图像数据

灰度图像

对于灰度图像(Grayscale Image),以下Field是必须的

Tag名称 Dec Hex 数据类型 说明
ImageWidth 256 100 SHORT or LONG - 图像列数,单扫描线中的像素数
ImageLength 257 101 SHORT or LONG - 图像行数,有时用扫描线数(scanlines)描述
BitsPerSample 258 102 SHORT 4 or 8 聚束只使用常规的8位
Compression 259 103 SHORT 1 or 32773 聚束只使用无压缩的1
PhotometricInterpretation 262 106 SHORT 0 or 1 0: 灰度最小值0表示白色;1:灰度最小值0表示黑色
StripOffsets 273 111 SHORT or LONG - 每个带(strip)在的文件中的偏移值,各个带不一定是顺序存储,不能做顺序存储的假定!!!
RowsPerStrip 278 116 SHORT or LONG - 每个带(strip)中的图像行数(最后一个带除外,最后一个带可能小于该数值)
StripByteCounts 279 117 LONG or SHORT - 每个带(strip)!!压缩后!!的字节数,TIFF/EP要求每个Strip压缩的大小不大于64k
XResolution 282 11A RATIONAL - ImageWidth方向(一般水平方向),单位ResolutionUnit中的像素点数,这种值对布局排版等有意义,对图像编辑程序没多大意义。
YResolution 283 11B RATIONAL - ImageLength方向(一般竖直方向),单位ResolutionUnit中的像素点数
ResolutionUnit 296 128 SHORT 1 or 2 or 3 分别:无绝对测量单位,英寸,厘米。
TIFF/EP PlanarConfiguration 284 11C SHORT 1或2 像素存储格式:块(Chunky)或面(Planar)
TIFF/EP NewSubfileType 254 FE LONG 0或1 1代表缩微图,否则是0
TIFF/EP SamplesPerPixel 277 115 SHORT 1 每个像素的通道数
TIFF/EP StandardID 37298 9216 BYTE 1 0 0 0 4个8位无符号数字

TIFF/EP要求,IFD0中必须存在下列Field

Tag名称 Dec Hex 数据类型 说明
TIFF/EP DateTime 306 132 ASCII YYYY:MM:DD HH:MM:SS 包含NUL在内,共20字节,文件的上次修改值
TIFF/EP DateTimeOriginal 36867 9003 ASCII YYYY:MM:DD HH:MM:SS 包含NUL在内,共20字节,文件创建后不能再修改该值
TIFF/EP Make 271 10F ASCII - 创建图像的工具(比如扫描仪)制造商。聚束SEM具体名字,可以为空“”
TIFF/EP Model 272 110 ASCII - 工具(比如扫描仪)的Model名或数字。聚束SEM型号,可以为空“”
TIFF/EP Software 305 131 ASCII - 创建图像的软件名字或版本号。聚束SEM控制软件名字,可以为空“”
TIFF/EP ImageDescription 270 10E ASCII - 图像的主题,比如"1988 company picnic",可以为空“”
TIFF/EP Copyright 33432 8298 ASCII - 版权说明,可以为空“”

【Tiff扩展】如果使用Tile而不是Strip方式的话,StripOffsets、RowsPreStrip和StripByteCount被相应的Tile字段取代,Strip不是必须的。

索引图像

对于调色板索引图像,和灰度图像相比,PhotometricInterpretation和SamplesPerPixel取值不一样,并多一个ColorMap。

Tag名称 Dec Hex 数据类型 说明
PhotometricInterpretation 262 106 SHORT 3 使用调色板颜色
ColorMap 320 140 SHORT - 对于8为深度图像,这是一个3*(2^8)的数组,颜色按照R、G、B排列
TIFF/EP SamplesPerPixel 277 115 SHORT 3 每个像素的通道数

真彩图像

对于真彩色图像,和灰度图像相比,BitsPerSample、SamplesPrePixel和PhotometricInterpretation取值不一样。

Tag名称 Dec Hex 数据类型 说明
BitsPerSample 258 102 SHORT 8,8,8 每一个通道都是8位深度(Baseline Tiff)
PhotometricInterpretation 262 106 SHORT 2 使用R G B 颜色
SamplesPerPixel 277 115 SHORT 3 or more 每个像素的通道数,没有额外的采样通道的话,正常是3。TIFF6.0要求

平铺(Tile)

在Baseline Tiff 6.0中,图像数据使用Strip方式。如果支持Tiff 6.0扩展的话,图像数据可以使用Strip或Tile方式(在一个图像中,只能二选一)。

Tag名称 Dec Hex 数据类型 说明
TIFF扩展 TileWidth 322 142 SHORT or LONG - Title块的宽度,如和ImageWidth不是整数倍关系,后面的数据需要填补(Padding)
TIFF扩展 TileLengh 323 143 SHORT or LONG - Tile块的长度,如和ImageLength不是整数倍关系,后面的数据需要填补(Padding)
TIFF扩展 TileOffsets 324 144 LONG - 各个Tile数据在文件中的偏移值
TIFF扩展 TileByteCounts 325 145 SHORT or LONG - 一个Tile中的字节数(压缩后)

TIff6.0要求:TileWidth和TileLength 必须是16的整数倍。Tile不一定的正方的,建议 的 TileWidth 与 TileLength 乘积位于 4K~32K。(也就是64x64,256x128,个人感觉有点小,所以不接受它的建议)

Strips模式下,Tiff6.0建议每个strip的大小不超过8K。如果单行超过8K,那么rowsperstrip建议用1.

了解术语:TilesAcross、TilesDown、TilesPerImage

1
2
3
TilesAcross = (ImageWidth + TileWidth - 1) / TileWidth
TilesDown = (ImageLength + TileLength - 1) / TileLength
TilesPerImage = TilesAcross * TilesDown

缩微图(Thumbnail)

TIFF/EP 引入缩微图支持。通过SubIFDs和NewSubFileType标签,IFD变成树型(tree)结构而不再是链式(chain)结构。

TIFF IFD Tree

对缩微图IFD,TIFF/EP要求: * NewSubFileType 取值必须是1(DNG除了主缩微图外,允许使用替代的缩微图,取值 10001.H)。 * PhotometricInterpretation 取值仅限于1,2,6 * Compression 取值必须是1 * 缩微图大小不超过宽度和高度(256x256),必须使用Strip方式

  • 当主图像采用JPEG压缩或其他压缩格式时,TIFF/EP 要求:必须存在缩微图,且需要在IFD0中。(以便兼容Baseline Reader)
  • 当主图像数据比较大时,TIFF/EP建议:使用缩微图,且放置在IFD0中。(以便图像快速打开)

LibTiff 库

官网:http://simplesystems.org/libtiff/

  • 老的官网: http://www.libtiff.org/ 【被劫持】

包含非常老的信息,有些信息是错误的。

  • 老的官网:http://remotesensing.org/libtiff/ 【失去控制】

从2003年起作为官网,但2016年维护者失去控制。

文件打开

1
2
3
4
TIFFOpen()
TIFFOpenW()
TIFFdOpen()
TIFFClientOpen()

前三个是第四个的马甲(注:Qt的Tiff插件,直接使用的第四个来对接QIODevice)。

打开模式:

  • r:读
  • w:写
  • a:追加
  • 4:配合w,写传统TIFF
  • 8:配合w,写BigTIFF
  • M:只读时启用内存映射文件
  • m:禁用内存映射文件

其他选项,l、b、L、B、H、C、c 估计我们以后也不会使用的。

有这么一个说法,默认写入文件时,先写传统的TIFF头,但是给BigTiff头留出空间,当后期发现文件大于4G时,将头重写为BigTiff头,其他IFD的字段根据状况也进行重写,但是数据位置不动(来自 bigtiff.ofg)。

IFD

读IFD

1
int TIFFReadDirectory(TIFF *tif)
  • 读文件中的下一个IFD,并将其设为当前IFD
  • 对于多页的tiff文件,只调用这一个函数就够了。
  • ‘r’模式调用TIFFOpen()打开文件时,会自动调用该函数。

写IFD

1
2
3
int TIFFWriteDirectory(TIFF *tif)
int TIFFRewriteDirectory(TIFF *tif)
int TIFFCheckpointDirectory(TIFF *tif)
  • TIFFWriteDirectory()
    • 写入当前IFD的内容到文件中,同时为创建下一个IFD做好准备【内部调用了TIFFCreateDirectory()】。
    • 正常写入多页的tiff文件时,只调用这个函数就足够了。
    • 写模式下如IFD有修改,文件关闭【TIFFClose】或刷新【TIFFFlush】时,会自动调用该函数。
  • TIFFReWriteDirectory()
    • 对于之前已经写入的IFD,将其从chain中断开。
    • 在文件尾部追加新的IFD,将其加入chian链中(效果上替换了老的IFD,但没有覆盖)。
  • TIFFCheckpointDirectory()
    • 将当前IFD内容写入到文件中,但是不释放内存中的数据结构。这样可以持续追加Strip或Tile数据
    • 当文件完成时,调用TIFFWriteDirectory()完成写入。
    • 【尽量不要用这个东西】

切换IFD

设置当前的IFD

1
2
int TIFFSetDirectory(TIFF *tif, tdir_t dirnum)
int TIFFSetSubDirectory(TIFF *tif, uint64 diroff)

前者使用dirnum【从0开始】,后者使用偏移值【这对subIFD很有用】。

前者需要从头遍历,也就是后者效率更高。

移除IFD

将指定的IFD从chain链中移除

1
int TIFFUnlinkDirectory(TIFF* tif, uint16 dirn)

Tag

获取或写入Field,通过如下2个函数。

  • TIFFGetField()
  • TIFFSetField()

有些Field有默认值,通过如下成员获取

  • TIFFGetFieldDefaulted()

注意事项

对XResolution 和 YResolution,其类型为Rational,但是set时需要使用一个double,get时需要使用float*

需要传入指针类型时,可以传入空指针,这样get内部会分配内存,在文件close时释放。

TIFFField

每一个内置的Tag/Field都有一个这样的结构体。有的Tag可以使用不同的数据类型,每一个数据类型都有这样的一个结构体。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
struct _TIFFField {
    uint32 field_tag;                       /* field's tag */
    short field_readcount;                  /* read count/TIFF_VARIABLE/TIFF_SPP */
    short field_writecount;                 /* write count/TIFF_VARIABLE */
    TIFFDataType field_type;                /* type of associated data */
    uint32 reserved;                        /* reserved for future extension */
    TIFFSetGetFieldType set_field_type;     /* type to be passed to TIFFSetField */
    TIFFSetGetFieldType get_field_type;     /* type to be passed to TIFFGetField */
    unsigned short field_bit;               /* bit in fieldsset bit vector */
    unsigned char field_oktochange;         /* if true, can change while writing */
    unsigned char field_passcount;          /* if true, pass dir count on set */
    char* field_name;                       /* ASCII name */
    TIFFFieldArray* field_subfields;        /* if field points to child ifds, child ifd field definition array */
};

注:一些老的资料可能会介绍TIFFFieldInfo,这个Info已经废弃,不建议使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
typedef struct {
  ttag_t    field_tag;          /* field's tag */
  short     field_readcount;    /* read count/TIFF_VARIABLE/TIFF_SPP */
  short     field_writecount;   /* write count/TIFF_VARIABLE */
  TIFFDataType field_type;      /* type of associated data */
  unsigned short field_bit;     /* bit in fieldsset bit vector */
  unsigned char field_oktochange;/* if true, can change while writing */
  unsigned char field_passcount;/* if true, pass dir count on set */
  char  *field_name;        /* ASCII name */
} TIFFFieldInfo;

int TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], uint32 n)

非内置的Tag

libTiff遇到位置的tag时,会自动注册这个Tag。可以通过下列函数来读取这些Tag

1
2
3
const TIFFField* TIFFFindField(TIFF *, uint32, TIFFDataType);
const TIFFField* TIFFFieldWithTag(TIFF*, uint32);
const TIFFField* TIFFFieldWithName(TIFF*, const char *);

但是,如果应用程序需要定义自己的Tag来存储TIFF标准之外的信息(读和写)...

读写图像数据

  • 高层接口:TIFFReadRGBAImage() 或 TIFFRGBAImageGet()
  • 简单接口:TIFF{Read/Write}Sanline()
    • 不能用于tile模式
  • Strip接口:TIFF{Read/Write}{Encoded/Raw}Strip()
  • Tile接口:TIFF{Read/Write}Tile()、TIFF{Read/Write}{Encoded/Raw}Tile()

目前只考虑PLANARCONFIG_CONTIG,只考虑 索引、灰度 图像

Tile接口

1
TIFFWriteTile(TIFF* tif, void* buf, uint32 x, uint32 y, uint32 z, uint16 s)

内部调用

1
TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)

压缩格式

我们关注 1、5、7、8

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#define TIFFTAG_COMPRESSION     259 /* data compression technique */
#define     COMPRESSION_NONE        1   /* dump mode */
#define     COMPRESSION_CCITTRLE    2   /* CCITT modified Huffman RLE */
#define     COMPRESSION_CCITTFAX3   3   /* CCITT Group 3 fax encoding */
#define     COMPRESSION_CCITT_T4        3       /* CCITT T.4 (TIFF 6 name) */
#define     COMPRESSION_CCITTFAX4   4   /* CCITT Group 4 fax encoding */
#define     COMPRESSION_CCITT_T6        4       /* CCITT T.6 (TIFF 6 name) */
#define     COMPRESSION_LZW     5       /* Lempel-Ziv  & Welch */
#define     COMPRESSION_OJPEG       6   /* !6.0 JPEG */
#define     COMPRESSION_JPEG        7   /* %JPEG DCT compression */
#define     COMPRESSION_T85         9   /* !TIFF/FX T.85 JBIG compression */
#define     COMPRESSION_T43         10  /* !TIFF/FX T.43 colour by layered JBIG compression */
#define     COMPRESSION_NEXT        32766   /* NeXT 2-bit RLE */
#define     COMPRESSION_CCITTRLEW   32771   /* #1 w/ word alignment */
#define     COMPRESSION_PACKBITS    32773   /* Macintosh RLE */
#define     COMPRESSION_THUNDERSCAN 32809   /* ThunderScan RLE */
/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */
#define     COMPRESSION_IT8CTPAD    32895   /* IT8 CT w/padding */
#define     COMPRESSION_IT8LW       32896   /* IT8 Linework RLE */
#define     COMPRESSION_IT8MP       32897   /* IT8 Monochrome picture */
#define     COMPRESSION_IT8BL       32898   /* IT8 Binary line art */
/* compression codes 32908-32911 are reserved for Pixar */
#define     COMPRESSION_PIXARFILM   32908   /* Pixar companded 10bit LZW */
#define     COMPRESSION_PIXARLOG    32909   /* Pixar companded 11bit ZIP */
#define     COMPRESSION_DEFLATE     32946   /* Deflate compression */
#define     COMPRESSION_ADOBE_DEFLATE   8       /* Deflate compression,
                           as recognized by Adobe */

GeoTiff

GeoTiff文件是一个标准的TIFF6.0文件,它使用了一些私有的Tag,对Tag值的含义做了新的规定(格式)。

Tag名称 Dec Hex 数据类型 说明
ModelPixelScaleTag 33550 830E DOUBLE - 3个
INGR Packet Data Tag 33918 847E SHORT - 多个
ModelTiepointTag 33922 8482 DOUBLE - -
GeoKeyDirectoryTag 34735 87AF SHORT - 4个以上,别名ProjectionInfoTag,CoordSystemInfoTag
GeoDoubleParamsTag 34736 87B1 DOUBLE - -
GeoAsciiParamsTag 34737 87B2 ASCII - -

其中:

GeoAsciiParamsTag = first_value|second_value|...|

注:33918~33922 这5个私有Tag是“Intergraph's Private TIFF Tags”,是Aldus(现在的Adobe)授权给Intergraph使用的。但是TIFF任何正式的文档中没有提这个事情。

BigTiff

Tiff使用32位的偏移值,,文件最大支持到4G。BigTiff是TIFF的一个变体,它使用64位的偏移值。

  • LibTiff4.0支持 BigTiff。
  • Matlab支持 BigTiff。

链接:

  • https://www.awaresystems.be/imaging/tiff/bigtiff.html
  • http://www.bigtiff.org/

格式

如前所述,为了支持大偏移量,bigtiff引入三种新的tag类型

类型 描述
16=LONG8 BigTIFF 64位无符号数
17=SLONG8 BigTIFF 64位有符号数
18=IFD8 BigTIFF 64位无符号数,是指向IFD的offset值

文件头

偏移 数据类型
0 Word 字节序指示符
2 Word 版本(始终是43),不同于TIFF6.0的42
4 Word 必须是8
6 Word 必须是0
8 Unsigned 8Byte 指向IFD0

IFD

偏移 数据类型
0 Unsigned 8Byte Tag个数
8+x*20 Tag 结构 Tag数据
8+(IFD中Tag数)*20 LONG8 指向下一个Tag的偏移值,或者0

TAG Field

偏移 数据类型
0 Word Tag
2 Word Tag数据类型
4 Unsigned Long 个数
12 - 8字节,数据或偏移值

软件

Photoshop

Pyramin

Photoshop 保存Tiff图像时,有一个“存储图像金字塔(Save Image Pyramin)”选项。勾选该选项,保存出来的图像会包含SUBIFDS。

Photoshop CS6 存储图像金字塔时,其指向的IFD格式和普通的IFD不一样,无法直接解析。是否是Bug?? 更老的Photoshop使用过其他的方式,非SUBIFD??

  • LIBTIFF邮件列表: https://www.asmail.be/msg0055058889.html

Photoshop实现:IFD0 的SUBIFD中包含一个offset值,指向其第一个子IFD,第一个子IFD的offset指向第二个子IFD,依次类推。(而不是通过SUBIFD一次定义多个子IFD的offset值,libtiff中是这种实现)

缩微图

存储在私有tag中:Photoshop(34377)

https://www.awaresystems.be/imaging/tiff/tifftags/docs/photoshopthumbnail.html

ImageMagick

ImageMagick使用 .ptif 和 .ptiff 作为 Pyramid-encoded TIFF文件的后缀。其内容是普通chain风格的多个页面,每个页面的NewSubFileType都是2。

Qt 图像

在Qt中, QPixmap 宽和高都不能超过32768,QImage的大小没有限制,字节数<INT最大值即可。QImageReader可以设置setAllocationLimit。

参考

  • https://en.wikipedia.org/wiki/TIFF
  • https://en.wikipedia.org/wiki/Libtiff
  • https://en.wikipedia.org/wiki/TIFF/EP
  • https://en.wikipedia.org/wiki/Digital_Negative
  • https://www.awaresystems.be/imaging/tiff/tifftags.html
  • https://stackoverflow.com/questions/11959617/in-a-tiff-create-a-sub-ifd-with-thumbnail-libtiff
  • http://www.simplesystems.org/libtiff/libtiff.html
  • http://www.simplesystems.org/libtiff/addingtags.html
  • https://www.awaresystems.be/imaging/tiff/tifftags/docs/intergraph.html
  • http://www.bigtiff.org/
  • https://www.awaresystems.be/imaging/tiff/tifftags/docs/photoshopthumbnail.html
  • Adobe Photoshop File Formats Specification
  • 2012.06.06 05:05 "Custom and EXIF directory read/write", by Frank Warmerdam
  • http://maptools-org.996276.n3.nabble.com/Creating-private-IFD-td13645.html
  • http://maptools-org.996276.n3.nabble.com/Custom-and-EXIF-directory-read-write-td3290.html
  • http://maptools-org.996276.n3.nabble.com/help-writing-thumbnails-to-TIFF-file-td3824.html
  • https://gis.stackexchange.com/questions/206509/how-are-geotiff-pyramids-overviews-standardised
  • Explain Image File Formats (ques10.com)

Tools