Using The TIFF Library — LibTIFF 4.6.0 documentation (2024)

libtiff is a set of C functions (a library) that supportthe manipulation of TIFF image files.The library requires an ANSI C compilation environment for buildingand presumes an ANSI C environment for use.

libtiffprovides interfaces to image data at several layers of abstraction (and cost).At the highest level image data can be read into an 8-bit/sample,ABGR pixel raster format without regard for the underlying data organization,colorspace, or compression scheme. Below this high-level interfacethe library provides scanline-, strip-, and tile-oriented interfaces thatreturn data decompressed but otherwise untransformed. These interfacesrequire that the application first identify the organization of storeddata and select either a strip-based or tile-based API for manipulatingdata. At the lowest level the libraryprovides access to the raw uncompressed strips or tiles,returning the data exactly as it appears in the file.

The material presented in this chapter is a basic introductionto the capabilities of the library; it is not an attempt to describeeverything a developer needs to know about the library or about TIFF.Detailed information on the interfaces to the library are given inthe TIFF Functions Overview that accompany this software.An alphabetic list of all the public functions with a brief description can be found at List of routines

Warning

The following hyperlink does no more work, at least no libtiff introduction:

Michael Still has also written a useful introduction to libtiff for theIBM DeveloperWorks site available athttp://www.ibm.com/developerworks/linux/library/l-libtiff.

How to tell which version you have

The software version can be found by looking at the file namedVERSIONthat is located at the top of the source tree; the precise alpha numberis given in the file dist/tiff.alpha.If you have need to refer to thisspecific software, you should identify it as:

TIFF <version> <alpha>

where <version> is whatever you get fromcat VERSION and <alpha> iswhat you get from cat dist/tiff.alpha.

Within an application that uses libtiff the TIFFGetVersion()routine will return a pointer to a string that contains software versioninformation.The library include file <tiffio.h> contains a C pre-processordefine TIFFLIB_VERSION that can be used to check libraryversion compatibility at compile time.

Library Datatypes

libtiff defines a portable programming interface through theuse of a set of C type definitions.These definitions, defined in in the files tiff.h andtiffio.h,isolate the libtiff API from the characteristicsof the underlying machine.To insure portable code and correct operation, applications that uselibtiff should use the typedefs and follow the functionprototypes for the library API.

Memory Management

libtiff uses a machine-specific set of routines for managingdynamically allocated memory._TIFFmalloc(), _TIFFrealloc(), and _TIFFfree()mimic the normal ANSI C routines.Any dynamically allocated memory that is to be passed into the libraryshould be allocated using these interfaces in order to insure pointercompatibility on machines with a segmented architecture.(On 32-bit UNIX systems these routines just call the normal malloc(),realloc(), and free() routines in the C library.)

To deal with segmented pointer issues libtiff also provides_TIFFmemcpy(), _TIFFmemset(), and _TIFFmemcmp()routines that mimic the equivalent ANSI C routines, but that areintended for use with memory allocated through _TIFFmalloc()and _TIFFrealloc().

With libtiff 4.5 a method was introduced to limit the internalmemory allocation that functions are allowed to request per call(see TIFFOpenOptionsSetMaxSingleMemAlloc() and TIFFOpenExt()).

With libtiff 4.6.1 a method was introduced to limit the internalcumulated memory allocation that functions are allowed to request for a givenTIFF handle(see TIFFOpenOptionsSetMaxCumulatedMemAlloc() and TIFFOpenExt()).

Error Handling

libtiff handles most errors by returning an invalid/erroneousvalue when returning from a function call.Various diagnostic messages may also be generated by the library.All error messages are directed to a single global error handlerroutine that can be specified with a call to TIFFSetErrorHandler().Likewise warning messages are directed to a single handler routinethat can be specified with a call to TIFFSetWarningHandler()

Further application-specific and per-TIFF handle (re-entrant) error handlerand warning handler can be set. Please refer to TIFFErrorand TIFFOpenOptions.

Basic File Handling

The library is modeled after the normal UNIX stdio library.For example, to read from an existing TIFF image thefile must first be opened:

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

The handle returned by TIFFOpen() is opaque, that isthe application is not permitted to know about its contents.All subsequent library calls for this file must pass the handleas an argument.

To create or overwrite a TIFF image the file is also opened, but witha "w" argument:

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

If the file already exists it is first truncated to zero length.

Warning

Unlike the stdio library TIFF image files may not beopened for both reading and writing;there is no support for altering the contents of a TIFF file.

libtiff buffers much information associated with writing avalid TIFF image. Consequently, when writing a TIFF image it is necessaryto always call TIFFClose() or TIFFFlush() to flush anybuffered information to a file. Note that if you call TIFFClose()you do not need to call TIFFFlush().

Warning

In order to prevent out-of-memory issues when opening a TIFF fileTIFFOpenExt() can be used and then the maximum single memorylimit in bytes that libtiff internal memory allocation functionsare allowed to request per call can be set withTIFFOpenOptionsSetMaxSingleMemAlloc().

Example

tmsize_t limit = (256 * 1024 * 1024);TIFFOpenOptions *opts = TIFFOpenOptionsAlloc();TIFFOpenOptionsSetMaxSingleMemAlloc(opts, limit);TIFF *tif = TIFFOpenExt("foo.tif", "w", opts);TIFFOpenOptionsFree(opts);/* ... go on here ... */

TIFF Directories

TIFF supports the storage of multiple images in a single file.Each image has an associated data structure termed a directorythat houses all the information about the format and content of theimage data.Images in a file are usually related but they do not need to be; itis perfectly alright to store a color image together with a black andwhite image.Note however that while images may be related their directories arenot.That is, each directory stands on its own; there is no need to readan unrelated directory in order to properly interpret the contentsof an image.

libtiff provides several routines for reading and writingdirectories. In normal use there is no need to explicitlyread or write a directory: the library automatically reads the firstdirectory in a file when opened for reading, and directory informationto be written is automatically accumulated and written when writing(assuming TIFFClose() or TIFFFlush() are called).

For a file open for reading the TIFFSetDirectory() routine canbe used to select an arbitrary directory; directories are referenced bynumber with the numbering starting at 0. Otherwise theTIFFReadDirectory() and TIFFWriteDirectory() routines canbe used for sequential access to directories.For example, to count the number of directories in a file the followingcode might be used:

#include "tiffio.h"main(int argc, char* argv[]){ TIFF* tif = TIFFOpen(argv[1], "r"); if (tif) { int dircount = 0; do { dircount++; } while (TIFFReadDirectory(tif)); printf("%d directories in %s\n", dircount, argv[1]); TIFFClose(tif); } exit(0);}

Finally, note that there are several routines for querying thedirectory status of an open file:TIFFCurrentDirectory() returns the index of the currentdirectory andTIFFLastDirectory() returns an indication of whether thecurrent directory is the last directory in a file.There is also a routine, TIFFPrintDirectory(), that canbe called to print a formatted description of the contents ofthe current directory; consult the manual page for complete details.

TIFF Tags

Image-related information such as the image width and height, numberof samples, orientation, colorimetric information, etc.are stored in each imagedirectory in fields or tags.Tags are identified by a number that is usually a value registeredwith the Aldus (now Adobe) Corporation.Beware however that some vendors writeTIFF images with tags that are unregistered; in this case interpretingtheir contents is usually a waste of time.

libtiff reads the contents of a directory all at onceand converts the on-disk information to an appropriate in-memoryform. While the TIFF specification permits an arbitrary set oftags to be defined and used in a file, the library only understandsa limited set of tags.Any unknown tags that are encountered in a file are ignored.There is a mechanism to extend the set of tags the library handleswithout modifying the library itself;this is described in Defining New TIFF Tags.

libtiff provides two interfaces for getting and setting tagvalues: TIFFGetField() and TIFFSetField().These routines use a variable argument list-style interface to passparameters of different type through a single function interface.The get interface takes one or more pointers to memory locationswhere the tag values are to be returned and also returns one orzero according to whether the requested tag is defined in the directory.The set interface takes the tag values either by-reference orby-value.The TIFF specification definesdefault values for some tags.To get the value of a tag, or its default value if it is undefined,the TIFFGetFieldDefaulted() interface may be used.

The manual pages for the tag get and set routines specify the exact data typesand calling conventions required for each tag supported by the library.

TIFF Compression Schemes

libtiff includes support for a wide variety ofdata compression schemes.In normal operation a compression scheme is automatically used whenthe TIFF Compression tag is set, either by opening a filefor reading, or by setting the tag when writing.

Compression schemes are implemented by software modules termed codecsthat implement decoder and encoder routines that hook into thecore library i/o support.Codecs other than those bundled with the library can be registeredfor use with the TIFFRegisterCODEC() routine.This interface can also be used to override the core-libraryimplementation for a compression scheme.

Byte Order

The TIFF specification says, and has always said, thata correct TIFFreader must handle images in big-endian and little-endian byte order.libtiff conforms in this respect.Consequently there is no means to force a specificbyte order for the data written to a TIFF image file (data iswritten in the native order of the host CPU unless appending toan existing file, in which case it is written in the byte orderspecified in the file).

Data Placement

The TIFF specification requires that all information except an8-byte header can be placed anywhere in a file.In particular, it is perfectly legitimate for directory informationto be written after the image data itself.Consequently TIFF is inherently not suitable for passing through astream-oriented mechanism such as UNIX pipes.Software that require that data be organized in a file in a particularorder (e.g. directory information before image data) does notcorrectly support TIFF.libtiff provides no mechanism for controlling the placementof data in a file; image data is typically written before directoryinformation.

TIFFRGBAImage Support

libtiff provides a high-level interface for reading imagedata from a TIFF file. This interface handles the details ofdata organization and format for a wide variety of TIFF files;at least the large majority of those files that one would normallyencounter. Image data is, by default, returned as ABGRpixels packed into 32-bit words (8 bits per sample). Rectangularrasters can be read or data can be intercepted at an intermediatelevel and packed into memory in a format more suitable to theapplication.The library handles all the details of the format of data stored ondisk and, in most cases, if any colorspace conversions are required:bilevel to RGB, greyscale to RGB, CMYK to RGB, YCbCr to RGB, 16-bitsamples to 8-bit samples, associated/unassociated alpha, etc.

There are two ways to read image data using this interface. Ifall the data is to be stored in memory and manipulated at once,then the routine TIFFReadRGBAImage() can be used:

#include "tiffio.h"main(int argc, char* argv[]){ TIFF* tif = TIFFOpen(argv[1], "r"); if (tif) { uint32_t w, h; size_t npixels; uint32_t* raster; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); npixels = w * h; raster = (uint32_t*) _TIFFmalloc(npixels * sizeof (uint32_t)); if (raster != NULL) { if (TIFFReadRGBAImage(tif, w, h, raster, 0)) { ...process raster data... } _TIFFfree(raster); } TIFFClose(tif); } exit(0);}

Note above that _TIFFmalloc() is used to allocate memory forthe raster passed to TIFFReadRGBAImage(); this is importantto insure the "appropriate type of memory" is passed on machineswith segmented architectures.

Alternatively, TIFFReadRGBAImage() can be replaced with amore low-level interface that permits an application to have morecontrol over this reading procedure. The equivalent to the aboveis:

#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_t* raster; npixels = img.width * img.height; raster = (uint32_t*) _TIFFmalloc(npixels * sizeof (uint32_t)); 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);}

However this usage does not take advantage of the more fine-grainedcontrol that's possible. That is, by using this interface it ispossible to:

  • repeatedly fetch (and manipulate) an image without openingand closing the file

  • interpose a method for packing raster pixel data according toapplication-specific needs (or write the data at all)

  • interpose methods that handle TIFF formats that are not alreadyhandled by the core library

The first item means that, for example, image viewers that want tohandle multiple files can cache decoding information in order tospeedup the work required to display a TIFF image.

The second item is the main reason for this interface. By interposinga "put method" (the routine that is called to pack pixel data inthe raster) it is possible share the core logic that understands howto deal with TIFF while packing the resultant pixels in a format thatis optimized for the application. This alternate format might be verydifferent than the 8-bit per sample ABGR format the library writes bydefault. For example, if the application is going to display the imageon an 8-bit colormap display the put routine might take the data andconvert it on-the-fly to the best colormap indices for display.

The last item permits an application to extend the librarywithout modifying the core code.By overriding the code provided an application might add supportfor some esoteric flavor of TIFF that it needs, or it mightsubstitute a packing routine that is able to do optimizationsusing application/environment-specific information.

The TIFF image viewer found in tools/sgigt.c is an exampleof an application that makes use of the TIFFRGBAImage()support.

Scanline-based Image I/O

The simplest interface provided by libtiff is ascanline-oriented interface that can be used to read TIFFimages that have their image data organized in strips(trying to use this interface to read data written in tileswill produce errors.)A scanline is a one pixel high row of image data whose widthis the width of the image.Data is returned packed if the image data is stored with samplespacked together, or as arrays of separate samples if the datais stored with samples separated.The major limitation of the scanline-oriented interface, otherthan the need to first identify an existing file as having asuitable organization, is that random access to individualscanlines can only be provided when data is not stored in acompressed format, or when the number of rows in a stripof image data is set to one (RowsPerStrip is one).

Two routines are provided for scanline-based i/o:TIFFReadScanline()andTIFFWriteScanline().For example, to read the contents of a file thatis assumed to be organized in strips, the following might be used:

#include "tiffio.h"main(){ TIFF* tif = TIFFOpen("myfile.tif", "r"); if (tif) { uint32_t imagelength; tdata_t buf; uint32_t row; TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength); buf = _TIFFmalloc(TIFFScanlineSize(tif)); for (row = 0; row < imagelength; row++) TIFFReadScanline(tif, buf, row, 0); _TIFFfree(buf); TIFFClose(tif); }}

TIFFScanlineSize() returns the number of bytes ina decoded scanline, as returned by TIFFReadScanline().Note however that if the file had been create with sampleswritten in separate planes, then the above code would onlyread data that contained the first sample of each pixel;to handle either case one might use the following instead:

#include "tiffio.h"main(){ TIFF* tif = TIFFOpen("myfile.tif", "r"); if (tif) { uint32_t imagelength; tdata_t buf; uint32_t 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, 0); } else if (config == planarconfig_separate) { uint16_t 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); }}

Beware however that if the following code were used instead toread data in the case PLANARCONFIG_SEPARATE,...

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

...then problems would arise if RowsPerStrip was not onebecause the order in which scanlines are requested would requirerandom access to data within strips (something that is not supportedby the library when strips are compressed).

Strip-oriented Image I/O

The strip-oriented interfaces provided by the library provideaccess to entire strips of data. Unlike the scanline-orientedcalls, data can be read or written compressed or uncompressed.Accessing data at a strip (or tile) level is often desirablebecause there are no complications with regard to random accessto data within strips.

A simple example of reading an image by strips is:

#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); }}

Notice how a strip size of -1 is used; TIFFReadEncodedStrip()will calculate the appropriate size in this case.

The above code reads strips in the order in which thedata is physically stored in the file. If multiple samplesare present and data is stored with PLANARCONFIG_SEPARATEthen all the strips of data holding the first sample will beread, followed by strips for the second sample, etc.

Finally, note that the last strip of data in an image may have fewerrows in it than specified by the RowsPerStrip tag. Areader should not assume that each decoded strip contains a fullset of rows in it.

The following is an example of how to read raw strips of data froma file:

#include "tiffio.h"main(){ TIFF* tif = TIFFOpen("myfile.tif", "r"); if (tif) { tdata_t buf; tstrip_t strip; uint32_t* bc; uint32_t 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); }}

As above the strips are read in the order in which they arephysically stored in the file; this may be different from thelogical ordering expected by an application.

Tile-oriented Image I/O

Tiles of data may be read and written in a manner similar to strips.With this interface, an image isbroken up into a set of rectangular areas that may have dimensionsless than the image width and height. All the tilesin an image have the same size, and the tile width and length must eachbe a multiple of 16 pixels. Tiles are ordered left-to-right andtop-to-bottom in an image. As for scanlines, samples can be packedcontiguously or separately. When separated, all the tiles for a sampleare colocated in the file. That is, all the tiles for sample 0 appearbefore the tiles for sample 1, etc.

Tiles and strips may also be extended in a z dimension to formvolumes. Data volumes are organized as "slices". That is, all thedata for a slice is colocated. Volumes whose data is organized intiles can also have a tile depth so that data can be organized incubes.

There are actually two interfaces for tiles.One interface is similar to scanlines, to read a tiled image,code of the following sort might be used:

main(){ TIFF* tif = TIFFOpen("myfile.tif", "r"); if (tif) { uint32_t imageWidth, imageLength; uint32_t tileWidth, tileLength; uint32_t 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); }}

(once again, we assume samples are packed contiguously.)

Alternatively a direct interface to the low-level data is providedà la strips. Tiles can be read withTIFFReadEncodedTile() or TIFFReadRawTile(),and written with TIFFWriteEncodedTile() orTIFFWriteRawTile(). For example, to read all the tiles in an image:

#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); }}

Other Stuff

Some other stuff will almost certainly go here...

Using The TIFF Library — LibTIFF 4.6.0 documentation (2024)

References

Top Articles
Latest Posts
Article information

Author: Ouida Strosin DO

Last Updated:

Views: 5937

Rating: 4.6 / 5 (76 voted)

Reviews: 83% of readers found this page helpful

Author information

Name: Ouida Strosin DO

Birthday: 1995-04-27

Address: Suite 927 930 Kilback Radial, Candidaville, TN 87795

Phone: +8561498978366

Job: Legacy Manufacturing Specialist

Hobby: Singing, Mountain biking, Water sports, Water sports, Taxidermy, Polo, Pet

Introduction: My name is Ouida Strosin DO, I am a precious, combative, spotless, modern, spotless, beautiful, precious person who loves writing and wants to share my knowledge and understanding with you.