1 void testVersion()
2 {
3 std::cout << TIFFGetVersion() << endl;
4 }
二. libTiff的数据类型
libtiff通过使用一组C类型定义定义了一个可移植的编程接口。这些定义在<tiffi.h>和<tiffio.h>文件中定义。为了确保代码的可移植性和正确的操作,使用libtiff的应用程序应该使用typedefs并遵循库API的函数原型。
为了处理分段指针问题,libtiff还提供了_TIFFmemcpy、_TIFFmemset和_TIFFmemmove例程,这些例程模拟等效的ANSI C例程,但是只能用于通过_TIFFmalloc和_TIFFrealloc分配内存。
三.内存管理libtiff使用一组自定义函数来管理动态分配的内存。_TIFFmalloc、_TIFFrealloc和_TIFFfree模拟正常的ANSI C例程。要传递到库中的任何动态分配的内存都应该使用这些接口进行分配,以确保具有分段架构的机器上的指针兼容性。(在32位UNIX系统中,这些例程只调用C库中的普通malloc、realloc和自由例程。)
四. 错误处理当从函数调用返回时,libtiff通过返回一个无效/错误的值来处理大多数错误。该库还可以生成各种诊断消息。所有错误消息都被定向到一个全局错误处理例程中,该例程可以通过调用TIFFSetErrorHandler来指定。同样,警告消息被定向到单个处理程序例程,该例程可以通过调用TIFFSetWarningHandler指定
五. 基本文件处理该库是模仿普通的UNIX stdio库建立的。例如,从现有的TIFF图像读取文件必须首先打开:
1 #include "tiffio.h"
2 main()
3 {
4 TIFF* tif = TIFFOpen("foo.tif", "r");
5 ... do stuff ...
6 TIFFClose(tif);
7 }
TIFFOpen返回的句柄是不透明的,即不允许应用程序知道其内容。此文件的所有后续库调用都必须将句柄作为参数传递。
要创建或者覆盖一个已经存在的TIFF文件,需要带有“w”参数:
1 #include "tiffio.h"
2 main()
3 {
4 TIFF* tif = TIFFOpen("foo.tif", "w");
5 ... do stuff ...
6 TIFFClose(tif);
7 }
注意:如果文件已经存在,文件长度会被截断为0
六 TIFF目录TIFF支持在一个文件中存储多个图像。每个图像都有一个相关的数据结构,称为目录(Directory),其中包含关于图像数据的格式和内容的所有信息。文件中的图像通常是相关的,但并不是一定要相关;将彩色图像与黑白图像存储在一起是完全可以的。但是,请注意,虽然图像可能是相关的,但它们的目录是不相关的。也就是说,每个目录都是独立的;它们不需要读取不相关的目录来正确地解释图像的内容。
libtiff提供了几个读取和写入目录的例程。在正常使用中,不需要显式地读取或写入目录:当打开以供读取时,库将自动读取文件中的第一个目录,并且要写入的目录信息将自动累积并在写入时写入(假设调用了TIFFClose或TIFFFlush)。
对于一个打开用于读取TIFFSetDirectory的文件,可以使用例程选择任意目录;目录由编号引用,编号从0开始。否则,TIFFReadDirectory和TIFFWriteDirectory例程可用于对目录的顺序访问。例如,要计算一个文件中目录的数量,可以使用以下代码:
1 int countDirectries(string fileName)
2 {
3
4 TIFF* tif = TIFFOpen(fileName.c_str(), "r");
5 int dircount = 0;
6 if (tif)
7 {
8 do
9 {
10 dircount++;
11
12 } while (TIFFReadDirectory(tif));
13 printf("%d directories in %s\n", dircount, fileName.c_str());
14 TIFFClose(tif);
15 }
16 return dircount;
17
18 }
最后,注意有几个例程用于查询打开文件的目录状态:TIFFCurrentDirectory返回当前目录的索引,TIFFLastDirectory返回当前目录是否是文件中的最后一个目录的指示。还有一个例程TIFFPrintDirectory,可以调用它来打印当前目录内容的格式化描述;详细信息请参阅手册页。
七.TIFF Tags
与图像相关的信息,如图像的宽度和高度、样本数量、方向、比色信息等,都存储在字段或标记中的每个图像目录中。标签由一个数字标识,这个数字通常是在Aldus(现在是Adobe)公司注册的值。但是要注意,有些供应商编写的TIFF图像带有未注册的标记;在这种情况下,解释它们的内容通常是浪费时间。
libtiff一次性读取目录的内容,并将磁盘上的信息转换为适当的内存形式。虽然TIFF规范允许在文件中定义和使用任意一组标记,但库只能理解有限的一组标记。在文件中遇到的任何未知标记都将被忽略。有一种机制可以在不修改库本身的情况下扩展库处理的标记集。
libtiff提供了两个获取和设置标签值的接口:TIFFGetField和TIFFSetField。这些例程使用变量参数列表样式的接口来通过单个函数接口传递不同类型的参数。get接口接受一个或多个指向要返回标记值的内存位置的指针,并根据请求的标记是否在目录中定义,返回1或0。set接口根据引用或值获取标记值。TIFF规范定义了一些标记的默认值。若要获取标记的值,或未定义的标记的默认值,可以使用TIFFGetFieldDefaulted接口。
常用Tag 如下:
1 #define TIFFTAG_SUBFILETYPE 254 /* subfile data descriptor */
2 #define FILETYPE_REDUCEDIMAGE 0x1 /* reduced resolution version */
3 #define FILETYPE_PAGE 0x2 /* one page of many */
4 #define FILETYPE_MASK 0x4 /* transparency mask */
5 #define TIFFTAG_OSUBFILETYPE 255 /* +kind of data in subfile */
6 #define OFILETYPE_IMAGE 1 /* full resolution image data */
7 #define OFILETYPE_REDUCEDIMAGE 2 /* reduced size image data */
8 #define OFILETYPE_PAGE 3 /* one page of many */
9 #define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */
10 #define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */
11 #define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */
12 #define TIFFTAG_COMPRESSION 259 /* data compression technique */
13 #define COMPRESSION_NONE 1 /* dump mode */
14 #define COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */
15 #define COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */
16 #define COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */
17 #define COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */
18 #define COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */
19 #define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */
20 #define COMPRESSION_OJPEG 6 /* !6.0 JPEG */
21 #define COMPRESSION_JPEG 7 /* %JPEG DCT compression */
22 #define COMPRESSION_T85 9 /* !TIFF/FX T.85 JBIG compression */
23 #define COMPRESSION_T43 10 /* !TIFF/FX T.43 colour by layered JBIG compression */
24 #define COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */
25 #define COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */
26 #define COMPRESSION_PACKBITS 32773 /* Macintosh RLE */
27 #define COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */
28 /* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */
29 #define COMPRESSION_IT8CTPAD 32895 /* IT8 CT w/padding */
30 #define COMPRESSION_IT8LW 32896 /* IT8 Linework RLE */
31 #define COMPRESSION_IT8MP 32897 /* IT8 Monochrome picture */
32 #define COMPRESSION_IT8BL 32898 /* IT8 Binary line art */
33 /* compression codes 32908-32911 are reserved for Pixar */
34 #define COMPRESSION_PIXARFILM 32908 /* Pixar companded 10bit LZW */
35 #define COMPRESSION_PIXARLOG 32909 /* Pixar companded 11bit ZIP */
36 #define COMPRESSION_DEFLATE 32946 /* Deflate compression */
37 #define COMPRESSION_ADOBE_DEFLATE 8 /* Deflate compression,
38 as recognized by Adobe */
39 /* compression code 32947 is reserved for Oceana Matrix <dev@oceana.com> */
40 #define COMPRESSION_DCS 32947 /* Kodak DCS encoding */
41 #define COMPRESSION_JBIG 34661 /* ISO JBIG */
42 #define COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */
43 #define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */
44 #define COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */
45 #define COMPRESSION_LZMA 34925 /* LZMA2 */
46 #define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */
47 #define PHOTOMETRIC_MINISWHITE 0 /* min value is white */
48 #define PHOTOMETRIC_MINISBLACK 1 /* min value is black */
49 #define PHOTOMETRIC_RGB 2 /* RGB color model */
50 #define PHOTOMETRIC_PALETTE 3 /* color map indexed */
51 #define PHOTOMETRIC_MASK 4 /* $holdout mask */
52 #define PHOTOMETRIC_SEPARATED 5 /* !color separations */
53 #define PHOTOMETRIC_YCBCR 6 /* !CCIR 601 */
54 #define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */
55 #define PHOTOMETRIC_ICCLAB 9 /* ICC L*a*b* [Adobe TIFF Technote 4] */
56 #define PHOTOMETRIC_ITULAB 10 /* ITU L*a*b* */
57 #define PHOTOMETRIC_CFA 32803 /* color filter array */
58 #define PHOTOMETRIC_LOGL 32844 /* CIE Log2(L) */
59 #define PHOTOMETRIC_LOGLUV 32845 /* CIE Log2(L) (u',v') */
60 #define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */
61 #define THRESHHOLD_BILEVEL 1 /* b&w art scan */
62 #define THRESHHOLD_HALFTONE 2 /* or dithered scan */
63 #define THRESHHOLD_ERRORDIFFUSE 3 /* usually floyd-steinberg */
64 #define TIFFTAG_CELLWIDTH 264 /* +dithering matrix width */
65 #define TIFFTAG_CELLLENGTH 265 /* +dithering matrix height */
66 #define TIFFTAG_FILLORDER 266 /* data order within a byte */
67 #define FILLORDER_MSB2LSB 1 /* most significant -> least */
68 #define FILLORDER_LSB2MSB 2 /* least significant -> most */
69 #define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */
70 #define TIFFTAG_IMAGEDESCRIPTION 270 /* info about image */
71 #define TIFFTAG_MAKE 271 /* scanner manufacturer name */
72 #define TIFFTAG_MODEL 272 /* scanner model name/number */
73 #define TIFFTAG_STRIPOFFSETS 273 /* offsets to data strips */
74 #define TIFFTAG_ORIENTATION 274 /* +image orientation */
75 #define ORIENTATION_TOPLEFT 1 /* row 0 top, col 0 lhs */
76 #define ORIENTATION_TOPRIGHT 2 /* row 0 top, col 0 rhs */
77 #define ORIENTATION_BOTRIGHT 3 /* row 0 bottom, col 0 rhs */
78 #define ORIENTATION_BOTLEFT 4 /* row 0 bottom, col 0 lhs */
79 #define ORIENTATION_LEFTTOP 5 /* row 0 lhs, col 0 top */
80 #define ORIENTATION_RIGHTTOP 6 /* row 0 rhs, col 0 top */
81 #define ORIENTATION_RIGHTBOT 7 /* row 0 rhs, col 0 bottom */
82 #define ORIENTATION_LEFTBOT 8 /* row 0 lhs, col 0 bottom */
83 #define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */
84 #define TIFFTAG_ROWSPERSTRIP 278 /* rows per strip of data */
85 #define TIFFTAG_STRIPBYTECOUNTS 279 /* bytes counts for strips */
86 #define TIFFTAG_MINSAMPLEVALUE 280 /* +minimum sample value */
87 #define TIFFTAG_MAXSAMPLEVALUE 281 /* +maximum sample value */
88 #define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */
89 #define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */
90 #define TIFFTAG_PLANARCONFIG 284 /* storage organization */
91 #define PLANARCONFIG_CONTIG 1 /* single image plane */
92 #define PLANARCONFIG_SEPARATE 2 /* separate planes of data */
93 #define TIFFTAG_PAGENAME 285 /* page name image is from */
94 #define TIFFTAG_XPOSITION 286 /* x page offset of image lhs */
95 #define TIFFTAG_YPOSITION 287 /* y page offset of image lhs */
96 #define TIFFTAG_FREEOFFSETS 288 /* +byte offset to free block */
97 #define TIFFTAG_FREEBYTECOUNTS 289 /* +sizes of free blocks */
98 #define TIFFTAG_GRAYRESPONSEUNIT 290 /* $gray scale curve accuracy */
99
100 ...
101 还有很多,其他见头文件
libtiff支持多种数据压缩方案。在正常操作中,当设置TIFF压缩标记时,会自动使用压缩方案,方法是打开文件进行读取,或者在写入时设置标记。
压缩方案是由称为编解码器的软件模块来实现的,编解码器和编码器例程连接到核心库i/o支持。除了那些与库绑定的编解码器外,还可以使用TIFFRegisterCODEC接口注册信的压缩例程。该接口还可用于覆盖压缩方案的核心库实现。
九. 字节顺序TIFF规范说,而且一直说,正确的TIFF阅读器必须按大端字节顺序和小端字节顺序处理图像。libtiff在这方面是一致的。因此没有意味着迫使一个特定字节顺序的数据写入一个TIFF图像文件(数据写在本机的主机CPU除非附加到现有文件,在这种情况下,它被写在文件)中指定的字节顺序。
十.Data PlacementTIFF规范要求除了8字节头之外的所有信息都可以放在文件的任何地方。特别是,在图像数据本身之后写入目录信息是完全合法的。因此,TIFF天生不适合通过面向流的机制(如UNIX管道)。要求将数据按特定顺序组织到文件中的软件(例如,图像数据之前的目录信息)不支持TIFF。libtiff没有提供控制文件中数据位置的机制;图像数据通常写在目录信息之前。
十一. TIFFRGBAImage 的支持libtiff提供了从TIFF文件读取图像数据的高级接口。这个接口处理各种TIFF文件的数据组织和格式的细节;至少是我们通常会遇到的大部分文件。在默认情况下,图像数据以ABGR像素的形式返回,并打包成32位的单词(每个示例8位)。矩形栅格可以被读取,或者数据可以在中间层次被截取,并以更适合应用程序的格式打包到内存中。该库处理存储在磁盘上的数据格式的所有细节,在大多数情况下,如果需要任何颜色空间转换,则处理:从两层到RGB、灰度到RGB、CMYK到RGB、YCbCr到RGB、16位样本到8位样本、关联/非关联alpha等。
使用这个接口有两种读取图像数据的方法。如果所有的数据都要存储在内存中,并且一次操作,那么可以使用例程TIFFReadRGBAImage:
1 #include "tiffio.h"
2 main(int argc, char* argv[])
3 {
4 TIFF* tif = TIFFOpen(argv[1], "r");
5 if (tif) {
6 uint32 w, h;
7 size_t npixels;
8 uint32* raster;
9
10 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
11 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
12 npixels = w * h;
13 raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
14 if (raster != NULL) {
15 if (TIFFReadRGBAImage(tif, w, h, raster, 0)) {
16 ...process raster data...
17 }
18 _TIFFfree(raster);
19 }
20 TIFFClose(tif);
21 }
22 exit(0);
23 }
注意以上_TIFFmalloc用于为传递给TIFFReadRGBAImage的光栅分配内存;这对于确保在具有分段架构的机器上传递“适当类型的内存”非常重要。
或者,TIFFReadRGBAImage可以替换为一个更低级的接口,该接口允许应用程序对这个读取过程有更多的控制。相当于上述:
1 #include "tiffio.h"
2 main(int argc, char* argv[])
3 {
4 TIFF* tif = TIFFOpen(argv[1], "r");
5 if (tif) {
6 TIFFRGBAImage img;
7 char emsg[1024];
8
9 if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
10 size_t npixels;
11 uint32* raster;
12
13 npixels = img.width * img.height;
14 raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
15 if (raster != NULL) {
16 if (TIFFRGBAImageGet(&img, raster, img.width, img.height)) {
17 ...process raster data...
18 }
19 _TIFFfree(raster);
20 }
21 TIFFRGBAImageEnd(&img);
22 } else
23 TIFFError(argv[1], emsg);
24 TIFFClose(tif);
25 }
26 exit(0);
27 }
说明几点:
彩色TIFF内的颜色顺序为rgb,在BMP内的顺序为bgr,两者需要翻转
黑白tif可调用TIFFSetField(pTif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK/WHITE)来指定0-1为黑、白,不过有些软件不支持。
TIFF内的每行数据为1字节对齐,bmp为4字节对齐 使用jpeg算法压缩时,strip的高度必须为8的倍数。
十二. Scanline-based Image I/O(线状IO)
libtiff提供的最简单的接口是一个面向扫描线的接口,可用于读取以条状方式组织图像数据的TIFF图像(尝试使用此接口读取用tiles编写的数据将产生错误)。扫描线是一个像素高的图像数据行,其宽度是图像的宽度。如果图像数据与打包的样本一起存储,则返回打包的数据;如果数据与分离的样本一起存储,则返回独立样本的数组。scanline-oriented接口的主要限制,除了需要首先识别现有文件有一个合适的组织,是随机存取个人对线只能提供数据没有存储在一个压缩格式时,或者当地带的图像数据的行数设置为1 (RowsPerStrip是其中之一)。
为基于扫描的i/o提供了两个例程:TIFFReadScanline和TIFFWriteScanline。例如,要读取一个假定是条状组织的文件的内容,可以使用以下方法:
1 #include "tiffio.h"
2 main()
3 {
4 TIFF* tif = TIFFOpen("myfile.tif", "r");
5 if (tif) {
6 uint32 imagelength;
7 tdata_t buf;
8 uint32 row;
9
10 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
11 buf = _TIFFmalloc(TIFFScanlineSize(tif));
12 for (row = 0; row < imagelength; row++)
13 TIFFReadScanline(tif, buf, row);
14 _TIFFfree(buf);
15 TIFFClose(tif);
16 }
17 }
TIFFScanlineSize返回解码后的scanline中的字节数,由TIFFReadScanline返回。但是请注意,如果文件是用在不同平面上编写的样本创建的,那么上面的代码将只读取包含每个像素的第一个样本的数据;要处理这两种情况,可以使用以下方法:
1 #include "tiffio.h"
2 main()
3 {
4 TIFF* tif = TIFFOpen("myfile.tif", "r");
5 if (tif) {
6 uint32 imagelength;
7 tdata_t buf;
8 uint32 row;
9
10 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
11 TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &config);
12 buf = _TIFFmalloc(TIFFScanlineSize(tif));
13 if (config == PLANARCONFIG_CONTIG) {
14 for (row = 0; row < imagelength; row++)
15 TIFFReadScanline(tif, buf, row);
16 } else if (config == PLANARCONFIG_SEPARATE) {
17 uint16 s, nsamples;
18
19 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &nsamples);
20 for (s = 0; s < nsamples; s++)
21 for (row = 0; row < imagelength; row++)
22 TIFFReadScanline(tif, buf, row, s);
23 }
24 _TIFFfree(buf);
25 TIFFClose(tif);
26 }
27 }
但是要注意,如果使用以下代码来读取PLANARCONFIG_SEPARATE中的数据,则需要使用以下代码
1 for (row = 0; row < imagelength; row++)
2 for (s = 0; s < nsamples; s++)
3 TIFFReadScanline(tif, buf, row, s);
如果RowsPerStrip不是其中之一,就会出现问题,因为请求扫描线的顺序需要随机访问条带内的数据(条带压缩时,库不支持这种方式)。
十三. Strip-oriented Image I/O(带状IO,图像分为几个横条压缩)库提供的Strip-oriented的接口提供对整个数据Strip的访问。与ScanLine的调用不同,数据可以被读或写压缩或未压缩。在Strip(或Tile)级别访问数据通常是可取的,因为在Strip内随机访问数据没有复杂性。
1 #include "tiffio.h"
2 main()
3 {
4 TIFF* tif = TIFFOpen("myfile.tif", "r");
5 if (tif) {
6 tdata_t buf;
7 tstrip_t strip;
8
9 buf = _TIFFmalloc(TIFFStripSize(tif));
10 for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++)
11 TIFFReadEncodedStrip(tif, strip, buf, (tsize_t) -1);
12 _TIFFfree(buf);
13 TIFFClose(tif);
14 }
15 }
注意如何使用-1大小的Strip;TIFFReadEncodedStrip将在这种情况下计算适当的大小。
上面的代码按照数据物理存储在文件中的顺序读取Strip。如果存在多个样本,并且数据存储在PLANARCONFIG_SEPARATE中,那么将读取包含第一个样本的所有数据带,然后读取第二个样本的数据带,等等。
最后,请注意,图像中的最后一条数据可能比RowsPerStrip标记指定的行更少。读者不应该假定每个解码的条带中包含一组完整的行。
下面是一个如何从文件中读取原始数据的例子:
1 #include "tiffio.h"
2 main()
3 {
4 TIFF* tif = TIFFOpen("myfile.tif", "r");
5 if (tif) {
6 tdata_t buf;
7 tstrip_t strip;
8 uint32* bc;
9 uint32 stripsize;
10
11 TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc);
12 stripsize = bc[0];
13 buf = _TIFFmalloc(stripsize);
14 for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++) {
15 if (bc[strip] > stripsize) {
16 buf = _TIFFrealloc(buf, bc[strip]);
17 stripsize = bc[strip];
18 }
19 TIFFReadRawStrip(tif, strip, buf, bc[strip]);
20 }
21 _TIFFfree(buf);
22 TIFFClose(tif);
23 }
24 }
Tiles数据可以读取和写入的方式类似于Strip。一个图像分解成一组矩形区域(尺寸小于图像的宽度和高度)。所有的瓷砖图像具有相同的大小,且瓷砖的宽度和长度必须是16像素的倍数。瓷砖排列方式为从左到右,自上而下在一个图像。对于scanline,样本可以连续地或单独包装。当分开的时候,所有的瓦片示例中托管的文件。也就是说,以Tile0,Tile1 。。。的顺序排列。(本段的瓷砖就是Tile)
瓦片和条也可以在z维中扩展以形成立方体形状排列。数据卷被组织为“片”。也就是说,一个片的所有数据都是共区的。数据组织在数据块中的卷也可以具有数据块深度,以便数据可以组织在多维数据集中。
tile有两个接口。一个类似扫描线的接口,要读取平铺图像,可以使用以下代码:
1 main()
2 {
3 TIFF* tif = TIFFOpen("myfile.tif", "r");
4 if (tif) {
5 uint32 imageWidth, imageLength;
6 uint32 tileWidth, tileLength;
7 uint32 x, y;
8 tdata_t buf;
9
10 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
11 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
12 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth);
13 TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileLength);
14 buf = _TIFFmalloc(TIFFTileSize(tif));
15 for (y = 0; y < imageLength; y += tileLength)
16 for (x = 0; x < imageWidth; x += tileWidth)
17 TIFFReadTile(tif, buf, x, y, 0);
18 _TIFFfree(buf);
19 TIFFClose(tif);
20 }
21 }
同样,我们假设样品是连续存放的。另外,还提供了到低级数据的直接接口。Tiles可以用TIFFReadEncodedTile或TIFFReadRawTile读取,也可以用TIFFWriteEncodedTile或TIFFWriteRawTile写入。例如,读取图像中的所有块:
1 #include "tiffio.h"
2 main()
3 {
4 TIFF* tif = TIFFOpen("myfile.tif", "r");
5 if (tif) {
6 tdata_t buf;
7 ttile_t tile;
8
9 buf = _TIFFmalloc(TIFFTileSize(tif));
10 for (tile = 0; tile < TIFFNumberOfTiles(tif); tile++)
11 TIFFReadEncodedTile(tif, tile, buf, (tsize_t) -1);
12 _TIFFfree(buf);
13 TIFFClose(tif);
14 }
15 }