【TIFF】四.翻译一下libtiff的手册

目录

 

一 如何获取当前libtiff的版本号

二. libTiff的数据类型

三.内存管理

四. 错误处理

五. 基本文件处理

六 TIFF目录

七.TIFF Tags

八. TIFF 压缩模式

九. 字节顺序

十.Data Placement

十一. TIFFRGBAImage 的支持

十二. Scanline-based Image I/O(线状IO)

十三. Strip-oriented Image I/O(带状IO,图像分为几个横条压缩)

十四. Tile-oriented Image I/O(类似地板砖形状的图像IO)


一 如何获取当前libtiff的版本号

void testVersion()
{
	std::cout << TIFFGetVersion() << endl;
}

二. 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图像读取文件必须首先打开:

#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("foo.tif", "r");
    ... do stuff ...
    TIFFClose(tif);
}

TIFFOpen返回的句柄是不透明的,即不允许应用程序知道其内容。此文件的所有后续库调用都必须将句柄作为参数传递。

要创建或者覆盖一个已经存在的TIFF文件,需要带有“w”参数:

#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("foo.tif", "w");
    ... do stuff ...
    TIFFClose(tif);
}

注意:如果文件已经存在,文件长度会被截断为0

六 TIFF目录

TIFF支持在一个文件中存储多个图像。每个图像都有一个相关的数据结构,称为目录(Directory),其中包含关于图像数据的格式和内容的所有信息。文件中的图像通常是相关的,但并不是一定要相关;将彩色图像与黑白图像存储在一起是完全可以的。但是,请注意,虽然图像可能是相关的,但它们的目录是不相关的。也就是说,每个目录都是独立的;它们不需要读取不相关的目录来正确地解释图像的内容。
 

libtiff提供了几个读取和写入目录的例程。在正常使用中,不需要显式地读取或写入目录:当打开以供读取时,库将自动读取文件中的第一个目录,并且要写入的目录信息将自动累积并在写入时写入(假设调用了TIFFClose或TIFFFlush)。

对于一个打开用于读取TIFFSetDirectory的文件,可以使用例程选择任意目录;目录由编号引用,编号从0开始。否则,TIFFReadDirectory和TIFFWriteDirectory例程可用于对目录的顺序访问。例如,要计算一个文件中目录的数量,可以使用以下代码:

int countDirectries(string fileName)
{
	
	TIFF* tif = TIFFOpen(fileName.c_str(), "r");
	int dircount = 0;
	if (tif) 
	{
		do 
		{
			dircount++;
			
		} while (TIFFReadDirectory(tif));
		printf("%d directories in %s\n", dircount, fileName.c_str());
		TIFFClose(tif);
	}
	return dircount;

}

最后,注意有几个例程用于查询打开文件的目录状态:TIFFCurrentDirectory返回当前目录的索引,TIFFLastDirectory返回当前目录是否是文件中的最后一个目录的指示。还有一个例程TIFFPrintDirectory,可以调用它来打印当前目录内容的格式化描述;详细信息请参阅手册页。

 

七.TIFF Tags

与图像相关的信息,如图像的宽度和高度、样本数量、方向、比色信息等,都存储在字段或标记中的每个图像目录中。标签由一个数字标识,这个数字通常是在Aldus(现在是Adobe)公司注册的值。但是要注意,有些供应商编写的TIFF图像带有未注册的标记;在这种情况下,解释它们的内容通常是浪费时间。

libtiff一次性读取目录的内容,并将磁盘上的信息转换为适当的内存形式。虽然TIFF规范允许在文件中定义和使用任意一组标记,但库只能理解有限的一组标记。在文件中遇到的任何未知标记都将被忽略。有一种机制可以在不修改库本身的情况下扩展库处理的标记集。

libtiff提供了两个获取和设置标签值的接口:TIFFGetField和TIFFSetField。这些例程使用变量参数列表样式的接口来通过单个函数接口传递不同类型的参数。get接口接受一个或多个指向要返回标记值的内存位置的指针,并根据请求的标记是否在目录中定义,返回1或0。set接口根据引用或值获取标记值。TIFF规范定义了一些标记的默认值。若要获取标记的值,或未定义的标记的默认值,可以使用TIFFGetFieldDefaulted接口。

常用Tag 如下:

#define	TIFFTAG_SUBFILETYPE		254	/* subfile data descriptor */
#define	    FILETYPE_REDUCEDIMAGE	0x1	/* reduced resolution version */
#define	    FILETYPE_PAGE		0x2	/* one page of many */
#define	    FILETYPE_MASK		0x4	/* transparency mask */
#define	TIFFTAG_OSUBFILETYPE		255	/* +kind of data in subfile */
#define	    OFILETYPE_IMAGE		1	/* full resolution image data */
#define	    OFILETYPE_REDUCEDIMAGE	2	/* reduced size image data */
#define	    OFILETYPE_PAGE		3	/* one page of many */
#define	TIFFTAG_IMAGEWIDTH		256	/* image width in pixels */
#define	TIFFTAG_IMAGELENGTH		257	/* image height in pixels */
#define	TIFFTAG_BITSPERSAMPLE		258	/* bits per channel (sample) */
#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 */
/* compression code 32947 is reserved for Oceana Matrix <dev@oceana.com> */
#define     COMPRESSION_DCS             32947   /* Kodak DCS encoding */
#define	    COMPRESSION_JBIG		34661	/* ISO JBIG */
#define     COMPRESSION_SGILOG		34676	/* SGI Log Luminance RLE */
#define     COMPRESSION_SGILOG24	34677	/* SGI Log 24-bit packed */
#define     COMPRESSION_JP2000          34712   /* Leadtools JPEG2000 */
#define	    COMPRESSION_LZMA		34925	/* LZMA2 */
#define	TIFFTAG_PHOTOMETRIC		262	/* photometric interpretation */
#define	    PHOTOMETRIC_MINISWHITE	0	/* min value is white */
#define	    PHOTOMETRIC_MINISBLACK	1	/* min value is black */
#define	    PHOTOMETRIC_RGB		2	/* RGB color model */
#define	    PHOTOMETRIC_PALETTE		3	/* color map indexed */
#define	    PHOTOMETRIC_MASK		4	/* $holdout mask */
#define	    PHOTOMETRIC_SEPARATED	5	/* !color separations */
#define	    PHOTOMETRIC_YCBCR		6	/* !CCIR 601 */
#define	    PHOTOMETRIC_CIELAB		8	/* !1976 CIE L*a*b* */
#define	    PHOTOMETRIC_ICCLAB		9	/* ICC L*a*b* [Adobe TIFF Technote 4] */
#define	    PHOTOMETRIC_ITULAB		10	/* ITU L*a*b* */
#define	    PHOTOMETRIC_CFA		32803	/* color filter array */
#define     PHOTOMETRIC_LOGL		32844	/* CIE Log2(L) */
#define     PHOTOMETRIC_LOGLUV		32845	/* CIE Log2(L) (u',v') */
#define	TIFFTAG_THRESHHOLDING		263	/* +thresholding used on data */
#define	    THRESHHOLD_BILEVEL		1	/* b&w art scan */
#define	    THRESHHOLD_HALFTONE		2	/* or dithered scan */
#define	    THRESHHOLD_ERRORDIFFUSE	3	/* usually floyd-steinberg */
#define	TIFFTAG_CELLWIDTH		264	/* +dithering matrix width */
#define	TIFFTAG_CELLLENGTH		265	/* +dithering matrix height */
#define	TIFFTAG_FILLORDER		266	/* data order within a byte */
#define	    FILLORDER_MSB2LSB		1	/* most significant -> least */
#define	    FILLORDER_LSB2MSB		2	/* least significant -> most */
#define	TIFFTAG_DOCUMENTNAME		269	/* name of doc. image is from */
#define	TIFFTAG_IMAGEDESCRIPTION	270	/* info about image */
#define	TIFFTAG_MAKE			271	/* scanner manufacturer name */
#define	TIFFTAG_MODEL			272	/* scanner model name/number */
#define	TIFFTAG_STRIPOFFSETS		273	/* offsets to data strips */
#define	TIFFTAG_ORIENTATION		274	/* +image orientation */
#define	    ORIENTATION_TOPLEFT		1	/* row 0 top, col 0 lhs */
#define	    ORIENTATION_TOPRIGHT	2	/* row 0 top, col 0 rhs */
#define	    ORIENTATION_BOTRIGHT	3	/* row 0 bottom, col 0 rhs */
#define	    ORIENTATION_BOTLEFT		4	/* row 0 bottom, col 0 lhs */
#define	    ORIENTATION_LEFTTOP		5	/* row 0 lhs, col 0 top */
#define	    ORIENTATION_RIGHTTOP	6	/* row 0 rhs, col 0 top */
#define	    ORIENTATION_RIGHTBOT	7	/* row 0 rhs, col 0 bottom */
#define	    ORIENTATION_LEFTBOT		8	/* row 0 lhs, col 0 bottom */
#define	TIFFTAG_SAMPLESPERPIXEL		277	/* samples per pixel */
#define	TIFFTAG_ROWSPERSTRIP		278	/* rows per strip of data */
#define	TIFFTAG_STRIPBYTECOUNTS		279	/* bytes counts for strips */
#define	TIFFTAG_MINSAMPLEVALUE		280	/* +minimum sample value */
#define	TIFFTAG_MAXSAMPLEVALUE		281	/* +maximum sample value */
#define	TIFFTAG_XRESOLUTION		282	/* pixels/resolution in x */
#define	TIFFTAG_YRESOLUTION		283	/* pixels/resolution in y */
#define	TIFFTAG_PLANARCONFIG		284	/* storage organization */
#define	    PLANARCONFIG_CONTIG		1	/* single image plane */
#define	    PLANARCONFIG_SEPARATE	2	/* separate planes of data */
#define	TIFFTAG_PAGENAME		285	/* page name image is from */
#define	TIFFTAG_XPOSITION		286	/* x page offset of image lhs */
#define	TIFFTAG_YPOSITION		287	/* y page offset of image lhs */
#define	TIFFTAG_FREEOFFSETS		288	/* +byte offset to free block */
#define	TIFFTAG_FREEBYTECOUNTS		289	/* +sizes of free blocks */
#define	TIFFTAG_GRAYRESPONSEUNIT	290	/* $gray scale curve accuracy */

... 
还有很多,其他见头文件

八. TIFF 压缩模式

libtiff支持多种数据压缩方案。在正常操作中,当设置TIFF压缩标记时,会自动使用压缩方案,方法是打开文件进行读取,或者在写入时设置标记。

压缩方案是由称为编解码器的软件模块来实现的,编解码器和编码器例程连接到核心库i/o支持。除了那些与库绑定的编解码器外,还可以使用TIFFRegisterCODEC接口注册信的压缩例程。该接口还可用于覆盖压缩方案的核心库实现。

九. 字节顺序

TIFF规范说,而且一直说,正确的TIFF阅读器必须按大端字节顺序和小端字节顺序处理图像。libtiff在这方面是一致的。因此没有意味着迫使一个特定字节顺序的数据写入一个TIFF图像文件(数据写在本机的主机CPU除非附加到现有文件,在这种情况下,它被写在文件)中指定的字节顺序。

十.Data Placement

TIFF规范要求除了8字节头之外的所有信息都可以放在文件的任何地方。特别是,在图像数据本身之后写入目录信息是完全合法的。因此,TIFF天生不适合通过面向流的机制(如UNIX管道)。要求将数据按特定顺序组织到文件中的软件(例如,图像数据之前的目录信息)不支持TIFF。libtiff没有提供控制文件中数据位置的机制;图像数据通常写在目录信息之前。

十一. TIFFRGBAImage 的支持

libtiff提供了从TIFF文件读取图像数据的高级接口。这个接口处理各种TIFF文件的数据组织和格式的细节;至少是我们通常会遇到的大部分文件。在默认情况下,图像数据以ABGR像素的形式返回,并打包成32位的单词(每个示例8位)。矩形栅格可以被读取,或者数据可以在中间层次被截取,并以更适合应用程序的格式打包到内存中。该库处理存储在磁盘上的数据格式的所有细节,在大多数情况下,如果需要任何颜色空间转换,则处理:从两层到RGB、灰度到RGB、CMYK到RGB、YCbCr到RGB、16位样本到8位样本、关联/非关联alpha等。

使用这个接口有两种读取图像数据的方法。如果所有的数据都要存储在内存中,并且一次操作,那么可以使用例程TIFFReadRGBAImage:

#include "tiffio.h"
main(int argc, char* argv[])
{
    TIFF* tif = TIFFOpen(argv[1], "r");
    if (tif) {
	uint32 w, h;
	size_t npixels;
	uint32* raster;

	TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
	TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
	npixels = w * h;
	raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
	if (raster != NULL) {
	    if (TIFFReadRGBAImage(tif, w, h, raster, 0)) {
		...process raster data...
	    }
	    _TIFFfree(raster);
	}
	TIFFClose(tif);
    }
    exit(0);
}

注意以上_TIFFmalloc用于为传递给TIFFReadRGBAImage的光栅分配内存;这对于确保在具有分段架构的机器上传递“适当类型的内存”非常重要。

或者,TIFFReadRGBAImage可以替换为一个更低级的接口,该接口允许应用程序对这个读取过程有更多的控制。相当于上述:

#include "tiffio.h"
main(int argc, char* argv[])
{
    TIFF* tif = TIFFOpen(argv[1], "r");
    if (tif) {
	TIFFRGBAImage img;
	char emsg[1024];

	if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
	    size_t npixels;
	    uint32* raster;

	    npixels = img.width * img.height;
	    raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
	    if (raster != NULL) {
		if (TIFFRGBAImageGet(&img, raster, img.width, img.height)) {
		    ...process raster data...
		}
		_TIFFfree(raster);
	    }
	    TIFFRGBAImageEnd(&img);
	} else
	    TIFFError(argv[1], emsg);
	TIFFClose(tif);
    }
    exit(0);
}

说明几点:

彩色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。例如,要读取一个假定是条状组织的文件的内容,可以使用以下方法:

#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
	uint32 imagelength;
	tdata_t buf;
	uint32 row;

	TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
	buf = _TIFFmalloc(TIFFScanlineSize(tif));
	for (row = 0; row < imagelength; row++)
	    TIFFReadScanline(tif, buf, row);
	_TIFFfree(buf);
	TIFFClose(tif);
    }
}

TIFFScanlineSize返回解码后的scanline中的字节数,由TIFFReadScanline返回。但是请注意,如果文件是用在不同平面上编写的样本创建的,那么上面的代码将只读取包含每个像素的第一个样本的数据;要处理这两种情况,可以使用以下方法:

#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
	uint32 imagelength;
	tdata_t buf;
	uint32 row;

	TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
	TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &config);
	buf = _TIFFmalloc(TIFFScanlineSize(tif));
	if (config == PLANARCONFIG_CONTIG) {
	    for (row = 0; row < imagelength; row++)
		TIFFReadScanline(tif, buf, row);
	} else if (config == PLANARCONFIG_SEPARATE) {
	    uint16 s, nsamples;

	    TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &nsamples);
	    for (s = 0; s < nsamples; s++)
		for (row = 0; row < imagelength; row++)
		    TIFFReadScanline(tif, buf, row, s);
	}
	_TIFFfree(buf);
	TIFFClose(tif);
    }
}

但是要注意,如果使用以下代码来读取PLANARCONFIG_SEPARATE中的数据,则需要使用以下代码

for (row = 0; row < imagelength; row++)
		for (s = 0; s < nsamples; s++)
		    TIFFReadScanline(tif, buf, row, s);

如果RowsPerStrip不是其中之一,就会出现问题,因为请求扫描线的顺序需要随机访问条带内的数据(条带压缩时,库不支持这种方式)。

十三. Strip-oriented Image I/O(带状IO,图像分为几个横条压缩)

库提供的Strip-oriented的接口提供对整个数据Strip的访问。与ScanLine的调用不同,数据可以被读或写压缩或未压缩。在Strip(或Tile)级别访问数据通常是可取的,因为在Strip内随机访问数据没有复杂性。

#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
	tdata_t buf;
	tstrip_t strip;

	buf = _TIFFmalloc(TIFFStripSize(tif));
	for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++)
		TIFFReadEncodedStrip(tif, strip, buf, (tsize_t) -1);
	_TIFFfree(buf);
	TIFFClose(tif);
    }
}

注意如何使用-1大小的Strip;TIFFReadEncodedStrip将在这种情况下计算适当的大小。

上面的代码按照数据物理存储在文件中的顺序读取Strip。如果存在多个样本,并且数据存储在PLANARCONFIG_SEPARATE中,那么将读取包含第一个样本的所有数据带,然后读取第二个样本的数据带,等等。

最后,请注意,图像中的最后一条数据可能比RowsPerStrip标记指定的行更少。读者不应该假定每个解码的条带中包含一组完整的行。

下面是一个如何从文件中读取原始数据的例子:

#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
	tdata_t buf;
	tstrip_t strip;
	uint32* bc;
	uint32 stripsize;

	TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &bc);
	stripsize = bc[0];
	buf = _TIFFmalloc(stripsize);
	for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++) {
		if (bc[strip] > stripsize) {
			buf = _TIFFrealloc(buf, bc[strip]);
			stripsize = bc[strip];
		}
		TIFFReadRawStrip(tif, strip, buf, bc[strip]);
	}
	_TIFFfree(buf);
	TIFFClose(tif);
    }
}

十四. Tile-oriented Image I/O(类似地板砖形状的图像IO)

Tiles数据可以读取和写入的方式类似于Strip。一个图像分解成一组矩形区域(尺寸小于图像的宽度和高度)。所有的瓷砖图像具有相同的大小,且瓷砖的宽度和长度必须是16像素的倍数。瓷砖排列方式为从左到右,自上而下在一个图像。对于scanline,样本可以连续地或单独包装。当分开的时候,所有的瓦片示例中托管的文件。也就是说,以Tile0,Tile1 。。。的顺序排列。(本段的瓷砖就是Tile)

瓦片和条也可以在z维中扩展以形成立方体形状排列。数据卷被组织为“片”。也就是说,一个片的所有数据都是共区的。数据组织在数据块中的卷也可以具有数据块深度,以便数据可以组织在多维数据集中。

tile有两个接口。一个类似扫描线的接口,要读取平铺图像,可以使用以下代码:

main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
	uint32 imageWidth, imageLength;
	uint32 tileWidth, tileLength;
	uint32 x, y;
	tdata_t buf;

	TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
	TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
	TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth);
	TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileLength);
	buf = _TIFFmalloc(TIFFTileSize(tif));
	for (y = 0; y < imageLength; y += tileLength)
	    for (x = 0; x < imageWidth; x += tileWidth)
		TIFFReadTile(tif, buf, x, y, 0);
	_TIFFfree(buf);
	TIFFClose(tif);
    }
}

同样,我们假设样品是连续存放的。另外,还提供了到低级数据的直接接口。Tiles可以用TIFFReadEncodedTile或TIFFReadRawTile读取,也可以用TIFFWriteEncodedTile或TIFFWriteRawTile写入。例如,读取图像中的所有块:

#include "tiffio.h"
main()
{
    TIFF* tif = TIFFOpen("myfile.tif", "r");
    if (tif) {
	tdata_t buf;
	ttile_t tile;

	buf = _TIFFmalloc(TIFFTileSize(tif));
	for (tile = 0; tile < TIFFNumberOfTiles(tif); tile++)
		TIFFReadEncodedTile(tif, tile, buf, (tsize_t) -1);
	_TIFFfree(buf);
	TIFFClose(tif);
    }
}

英文链接:http://www.libtiff.org/libtiff.html

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用libtiff将CMYK张分色图合并成一张TIFF的步骤: 1. 打开每个CMYK分色图并读取它们的图像数据。您可以使用libtiffTIFFOpen和TIFFReadRGBAImage函数来实现。 2. 创建一个新的TIFF文件并使用libtiffTIFFSetField函数设置必要的标签,如图像宽度、高度、位深度和颜色模式。对于CMYK图像,您需要设置TIFFTAG_PHOTOMETRIC标签为PHOTOMETRIC_SEPARATED,TIFFTAG_INKSET标签为INKSET_CMYK和TIFFTAG_SAMPLESPERPIXEL标签为4。 3. 将CMYK分色图的数据写入新的TIFF文件。您可以使用libtiffTIFFWriteScanline函数将每个分色图的扫描线写入新的TIFF文件。 4. 关闭所有文件并释放所有资源。 以下是一个示例代码,它将张CMYK分色图合并成一张TIFF: ``` #include <stdio.h> #include <stdlib.h> #include <tiffio.h> int main() { // Open the four CMYK separation files TIFF* cyan = TIFFOpen("cyan.tif", "r"); TIFF* magenta = TIFFOpen("magenta.tif", "r"); TIFF* yellow = TIFFOpen("yellow.tif", "r"); TIFF* black = TIFFOpen("black.tif", "r"); // Read image data from each file uint32 width, height; TIFFGetField(cyan, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(cyan, TIFFTAG_IMAGELENGTH, &height); uint32* cdata = (uint32*)malloc(width * height * sizeof(uint32)); TIFFReadRGBAImage(cyan, width, height, cdata, 0); uint32* mdata = (uint32*)malloc(width * height * sizeof(uint32)); TIFFReadRGBAImage(magenta, width, height, mdata, 0); uint32* ydata = (uint32*)malloc(width * height * sizeof(uint32)); TIFFReadRGBAImage(yellow, width, height, ydata, 0); uint32* kdata = (uint32*)malloc(width * height * sizeof(uint32)); TIFFReadRGBAImage(black, width, height, kdata, 0); // Create a new TIFF file and set necessary tags TIFF* output = TIFFOpen("output.tif", "w"); TIFFSetField(output, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(output, TIFFTAG_IMAGELENGTH, height); TIFFSetField(output, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED); TIFFSetField(output, TIFFTAG_INKSET, INKSET_CMYK); TIFFSetField(output, TIFFTAG_SAMPLESPERPIXEL, 4); // Write image data to the new TIFF file for (uint32 row = 0; row < height; row++) { uint32* scanline = (uint32*)malloc(width * sizeof(uint32)); for (uint32 col = 0; col < width; col++) { uint32 c = (cdata[row * width + col] >> 24) & 0xff; uint32 m = (mdata[row * width + col] >> 24) & 0xff; uint32 y = (ydata[row * width + col] >> 24) & 0xff; uint32 k = (kdata[row * width + col] >> 24) & 0xff; scanline[col] = (k << 24) | (y << 16) | (m << 8) | c; } TIFFWriteScanline(output, scanline, row); free(scanline); } // Close all files and free all resources TIFFClose(cyan); TIFFClose(magenta); TIFFClose(yellow); TIFFClose(black); TIFFClose(output); free(cdata); free(mdata); free(ydata); free(kdata); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值