Appendix A. Stream TIFF Data Format

This appendix describes the Stream TIFF data format (STIFF), the primary interchange file format between printer filters and drivers, and libstiff;, a C application program interface (API) used to read and write Stream TIFF files. Stream TIFF is also used by gscan to store images in TIFF files and to scan to the screen (in conjunction with vstiff).

The following major topics are discussed:

Library Description

libstiff provides a C application program interface (API) to the reading and writing of Stream TIFF files. Stream TIFF (STIFF) is a subset of the Tag Image File Format (TIFF) Revision 6.0 originally developed by Aldus Corporation. TIFF is an extremely flexible format, well suited for monochrome and color bitmap images. The primary difference between TIFF and STIFF is that while a TIFF file may require file seeking during reading or writing, a STIFF file does not. This means that a STIFF file can be read and written to both files and non-seekable streams such as pipes and sockets. STIFF can be used by application developers to write TIFF 6.0-compliant files, and a STIFF file can be read by any TIFF reader that conforms to the TIFF Revision 6.0 specifications. However, libstiff cannot be used to read many standard TIFF files since STIFF is a subset of TIFF.

The functions provided by libstiff greatly simplify the reading and writing of TIFF-compatible files. Using the STIFF API, TIFF 6.0-compatible STIFF files can be read and written without the need to understand the structure of a TIFF file and without the need to explicitly specify TIFF tags.

Library Access

There are two sets of libstiff functions. One set comprises the generic libstiff API. These functions are designated by an ST prefix and may be used to read and write generic STIFF files. To access these functions, an application must include the header file stiff.h located in the /usr/include directory. The second set of libstiff functions is tailored to reading and writing STIFF files that are to be passed between printing filters and drivers. These printing-related functions are designated by the prefix PST and are accessed through the header file printstiff.h, also located in /usr/include. If printstiff.h is used, the header stiff.h need not be specified. The generic and printing-specific functions may be freely intermixed within an application.

Programs that call libstiff functions must link with the libstiff.a library located in the directory /usr/lib. An example command line is shown below:

cc -o myprog myprog.c -lstiff 

Library Functions

libstiff provides the generic functions listed in Table A-1.

Table A-1. STIFF Generic Functions

Task

Function Name

Description

Stream Handling

STOpen()

STClose()

STSkipTo()

Opens a STIFF stream on the specified file descriptor

Closes a STIFF stream opened by STOpen()

Skips forward on a specified stream

Reading and Writing

STReadImageHeader()

STWriteImageHeader()

STRead()

STWrite()

Reads the STIFF image header from the specified stream

Writes the image header to the specified stream

Reads the specified amount of image data from
the stream

Writes the specified amount of image data to the stream

TIFF Tag Support

STAddTag()

STRemoveTag()

STGetTag()

STPrintTags()

Adds the specified tag to the TIFF tag list

Removes the specified tag from the output TIFF tag list

Searches the tag list for the specified TIFF tag

Prints the current TIFF tag list

Execution Error Handling

STPerror()

STErrorString()

Prints error messages to standard error

Gets the error string for the specified error code

STIFF also provides the printing-specific functions listed in Table A-2.

Table A-2. STIFF Printing-Specific Functions

Function Name

Description

PSTReadImageHeader()

Reads the printing-specific STIFF image header from the stream

PSTWriteImageHeader()

Writes the printing-specific STIFF image header to the stream


Example Usage

The sequence of operations for writing a STIFF stream is as follows:

  1. Obtain a writable file descriptor. Note that this descriptor can be associated with a non-seekable stream.

  2. Call STOpen() with the writable file descriptor and the flag ST_WRITE.

  3. Fill in the STIFF image header (STImageHeader() or PSTImageHeader()).

  4. Optionally, add any application-specific TIFF tags to the file using STAddTag().

  5. Call the image header write function STWriteImageHeader() or PSTWriteImageHeader().

  6. Write the image data using STWrite().

  7. Repeat steps 3 through 6 for each page of image data.

  8. Close the STIFF file using STClose().

  9. Close the file descriptor.

The sequence of operations for reading a STIFF stream is as follows:

  1. Obtain a readable file descriptor. Note that this descriptor can be associated with a non-seekable stream.

  2. Call STOpen() with the readable file descriptor and the flag ST_READ.

  3. Call the image header read function STReadImageHeader() or PSTReadImageHeader().

  4. Access the fields of the image header structure to determine the amount of image data to be read for this page.

  5. Optionally, retrieve any application-specific TIFF tags from the file using STGetTag().

  6. Read the image data using STRead().

  7. Repeat steps 3 through 6 for each page of image data. The last page of image data is an empty page (that is, the amount of data equals zero). An STEEOF error occurs if an attempt is made to read past the end of the STIFF.

  8. Close the STIFF stream using STClose().

  9. Close the file descriptor.

If an error condition is returned by a libstiff function, STPerror() can be used to print a diagnostic error message to the standard error, and STErrorString() can be used to obtain an appropriate error message for display to the user by other means.

Printing-Specific STIFF

The printing-specific functions (PST) provided by libstiff read and write STIFF files as described above. The printing-specific aspect of these functions is found in the image header structure. PSTImageHeader(), the printing-specific image header, contains all fields of the STImageHeader() plus printing-specific information fields such as image resolution and halftoning method.

If a STIFF file is written using the generic functions and is read using the printing-specific functions, default values are used for the PSTImageHeader() fields not found in the STIFF. Similarly, a STIFF file written using the printing-specific functions can be read by the generic functions. In this case, the additional information in the stream can be ignored or obtained using the STGetTag() function.

Refer to the header file /usr/include/printstiff.h for additional information regarding printing-specific STIFF.

Printer driver developers should pay special attention to the command-line options string that is part of a PST image header. See the LaserJet example driver for an example of how to combine parsing the command-line and image-header driver options.

Generic STIFF File Structure

While it is not necessary to understand the STIFF file structure to use libstiff, this explanation is provided for those who need to know. A Stream TIFF file is first and foremost a valid TIFF file. STIFF is derived from the TIFF 6.0 specifications available from Aldus Corporation (see below). The terms used below to describe a STIFF file (for example, IFD) are explained in the TIFF specifications and are not described here.

The primary restriction STIFF places on the TIFF structure is that all data must be read from or written to the file without the need to seek within the file. Specifically, within a STIFF file, these things must be true:

  1. The bitmap image data must be in page-number order.

  2. Data that does not fit in the value section of a tag must be located immediately after the IFD and must occur in the same order in which the tags are encountered. The exception to this is the image data itself, which must come last for each page.

  3. Image data must immediately follow the IFD and any associated offset values.

  4. A terminating, empty IFD is always added to the end of the STIFF file. This IFD guarantees that an IFD with 0000 in its “next IFD” field appears in the IFD chain. Note that this empty IFD is not encountered when following IFD pointers if the last “real” IFD is written with the last parameter set to 1. While the TIFF specification states that IFDs should not be empty, relaxing this restriction appears to have no impact on TIFF compatibility.

A generic STIFF file can be represented as shown in Figure A-1.

Figure A-1. Generic STIFF File Structure

Figure A-1 Generic STIFF File Structure

The libstiff functions support only the Motorola® (MM) byte ordering. In addition to supporting TIFF class RGB data, libstiff supports the CMYK color image data type (PhotoMetricInterpretation = 5 and InkSet = 1) and four additional color image separation types: CMY, YMC, YMCK, and KCMY.

For these additional types, PhotoMetricInterpretation = 5, InkSet = 2, NumberOfInks = 3 or 4, and the InkNames tag is used to indicate the inks contained in each channel.

When reading an image header, libstiff parses the ink names for these additional types and sets the type field of the STImageHeader structure to the appropriate value defined in stiff.h. When writing an image header, libstiff writes the appropriate PhotoMetricInterpretation, InkSet, NumberOfInks, and InkNames tags based on the value of the type field of the STImageHeader structure.

The CMYK data format is a TIFF data format extension, as shown in Table A-3.

Table A-3. CMYK Data Format

Tag

Possible Values

BitsPerSample

(1,1,1,1) (4,4,4,4) (8,8,8,8)

PhotoMetricInterpretation

5

SamplesPerPixel

4

PlanarConfiguration

1, 2

NumberOfInks

4

The CMY data class is a subset of the CMYK class and differs from the CMYK class in a TIFF-compliant manner, as shown in Table A-4.

Table A-4. CMY Data Format

Tag

Possible Values

BitsPerSample

(1,1,1,1) (1,1,1) (4,4,4) (8,8,8)

PhotoMetricInterpretation

5

SamplesPerPixel

3 (4 or 8 bits, 1-bit planar) or 4 (1-bit chunky)

PlanarConfiguration

1, 2

NumberOfInks

3

The YMC data class is similar to the CMY class except that data is organized as YMC instead of CMY (see Table A-5). When using libstiff, YMC data corresponds to the data type ST_TYPE_YMC.

Table A-5. YMC Data Format

Tag

Possible Values

BitsPerSample

(1,1,1,1) (1,1,1) (4,4,4) (8,8,8)

PhotoMetricInterpretation

5

SamplesPerPixel

3 (4 or 8 bits, 1-bit planar) or 4 (1-bit chunky)

PlanarConfiguration

1, 2

NumberOfInks

3

InkSet

2

InkNames

yellow, magenta, cyan

The YMCK class is similar to the CMYK class except that data is organized as YMCK instead of CMYK (see Table A-6). When using libstiff, YMCK data corresponds to the data type ST_TYPE_YMCK.

Table A-6. YMCK Data Format

Tag

Possible Values

BitsPerSample

(1,1,1,1) (4,4,4,4) (8,8,8,8)

PhotoMetricInterpretation

5

SamplesPerPixel

4

PlanarConfiguration

1, 2

NumberOfInks

4

InkSet

2

InkNames

yellow, magenta, cyan, black

The KCMY class is similar to the CMYK class except that the data is organized as KCMY instead of CMYK (see Table A-7). When using libstiff, KCMY data corresponds to the data type ST_TYPE_KCMY.

Table A-7. KCMY Data Format

Tag

Possible Values

BitsPerSample

(1,1,1,1) (4,4,4,4) (8,8,8,8)

PhotoMetricInterpretation

5

SamplesPerPixel

4

PlanarConfiguration

1, 2

NumberOfInks

4

InkSet

2

InkNames

black, cyan, magenta, yellow

Note that for the RGB, CMY, and YMC classes with BitsPerSample values of (1,1,1) and a PlanarConfiguration value of 1, pixels are stored two to a byte, with the bits ordered from most-significant to least-significant.

For example, CMY data is stored as

CMY0CMY0

Rows are padded to contain an integral number of bytes.

Refer to the header file stiff.h for additional information regarding the STIFF file structure.