Features


Image Processing

Part 1: Reading The Tag Image File Format

Dwayne Phillips


Dwayne Phillips works as a computer and electronics engineer with the United States Department of Defense. He has a Ph.D. in electrical and computer engineering at Louisiana State University. His interests include computer vision, artificial intelligence, software engineering, and programming languages.

Introduction

Programmers increasingly must obtain images, manipulate them, improve them, and output them. This article is the first in a series on images and image processing. Each article will include source code to demonstrate the concepts it covers. The code implements the C Image Processing System (CIPS), a small system that combines image processing operators with a simple user interface. The first article of the series discusses image input and the Tag Image File Format (TIFF). The second and third articles will discuss image output — displaying and printing images. The fourth article will discuss histograms and histogram equalization. [These articles will not all appear in sequential issues. pjp]

Image processing involves processing or altering an existing image in a desired manner. The first step is obtaining an image. While this may sound obvious, it is not a simple matter, since usable image data is not readily available. The programmer needs a simple method of obtaining image data in a standard, usable format. The Tag Image File Format was designed to promote the interchange of digital image data. [1]

Aldus (of PageMaker fame), Microsoft, and several other computer and scanner companies decided to write an industry standard for digital image data communication. Their collaboration resulted in the TIFF specification. Since most scanner manufacturers support the standard in their PC and Macintosh products, TIFF is a natural for PC-based image processing.

The goals of the TIFF specification are extensibility, portability, and revisability. TIFF must be extensible in the future. TIFF must be able to adapt to new types of images and data and must be portable between different computers, processors, and operating systems. TIFF must be revisable — it is not a read-only format. Software systems should be able to edit, process, and change TIFF files.

The tag in Tag Image File Format refers to the file's basic structure. A TIFF tag provides information about the image, such as its width, length, and number of pixels. Tags are organized in tag directories. Tag directories have no set length or number, since pointers lead from one directory to another. The result is a flexible file format that can grow and survive in the future. Figure 3 contains the existing standard tags.

Image Data Basics

An image consists of a two-dimensional array of numbers. The color or gray shade displayed for a given picture element (pixel) depends on the number stored in the array for that pixel. The simplest type of image data is black and white. It is a binary image since each pixel is either 0 or 1. You should scan line drawings as binary images because you will save storage space and because you will not lose any information in the process.

The next more complex type of image data is grayscale, where each pixel takes on a value between 0 and the number of gray scales or gray levels that the scanner can record. These images appear like common black-and-white photographs — they are black, white, and shades of gray. Some scanners record only 16 shades of gray, sufficient for simple applications. In more serious work, however, you should try to use scanners that produce 256 shades of gray. Since the average person can distinguish about 40 shades of gray, a 16-shade image may appear rough, while a 256-shade image "looks like a photograph." This series of articles will concentrate on grayscale images.

The most complex type of image is color. Color images are similar to grayscale except that there are three bands, or channels, corresponding to the additive primary colors red, green, and blue. Thus, each pixel has three values associated with it. A color scanner uses red, green, and blue filters to produce those values.

You can obtain TIFF images by using a desktop scanner and your own photographs. Color photos work reasonably well, but black-and-white photos are better. I have used the Hewlett-Packard ScanJet and ScanJet Plus with good results. The code disk for this issue contains several TIFF images. (See page 80 to order. Ed.) The ScanJet is limited to 16 shades of gray. The ScanJet Plus gives up to 256 shades of gray. Buying your own scanner (about $1,500) is not necessary since many printers and copy services now support desktop publishing with scanners. They will typically charge $10 to $20 per scan. Some PC dealers sell scanners and will also provide this service.

Be prepared to fail on your first try at scanning photos. The biggest problem is file size. The scanner can scan 300 dots per inch, so a 3x5 photo at 300 dpi provides 900x1500 pixels. At eight bits per pixel (256 shades of gray) the image file comes to over 1,350,000 bytes. This is not practical for many applications. Instead, select a one- or two-inch square in your photo and work with it. The scanning software allows you to preview the scanned photo and to select just the area you want scanned onto disk, the resolution in dots per inch, and the number of gray shades.

TIFF Specifics

Figure 1 (a) shows the structure of TIFF. The first eight bytes of the file are the header. These eight bytes have the same format on all TIFF files. They are the only items set in concrete for TIFF files. The remainder of the file differs from image to image. Figure 1 (b) shows the IFD or Image File Directory, which contains the number of directory entries and the directory entries themselves. Figure 1 (c) shows the structure of each directory entry. Each entry contains a tag indicating what type of information the file holds, the data type of the information, the length of the information, and a pointer to the information or the information itself.

Figure 2 shows the beginning of a TIFF file. The addresses are located on the left side in decimal, and the bytes and their valves are in the table in hex.

Glancing between Figure 1 and Figure 2 should clarify the structure. The first eight bytes are the header. Bytes zero and one tell whether the file stores numbers most significant byte (MSB) or least significant byte (LSB) first. If bytes zero and one are II (0x4949), then the least significant byte is first (predominant in the PC world). If the value is MM (0x4D4D), then the most significant byte is first (predominant in the Macintosh world). Your software needs to read both formats.

The example in Figure 2 shows LSB first. Bytes two and three give the TIFF version number, which should be 42 (0x2A) in all TIFF images. Bytes four to seven give the offset to the first image file directory (IFD). Note that all offsets in TIFF indicate locations with respect to the beginning of the file. The first byte in the file has the offset 0. The offset in Figure 2 is 8, so the IFD begins in the ninth byte of the file.

The IFD

The content of address eight is 27, indicating that this file has 27 12-byte directory entries. The first two bytes of the entry contain the tag, which tells the type of information the entry contains. The directory entry at location zero (Figure 2) contains tag=255. This tag tells the file type. (Refer to Figure 3 for possible tags.) The next two bytes of the entry give the data type of the information (Figure 4 lists the possible data types and their lengths). Directory entry zero in Figure 2 is type 3, a short (two-byte unsigned integer). The next four bytes of the entry give the length of the information. This length is not in bytes, but rather in multiples of the data type. If the data type is a short and the length is 1, then the length is one short, or two bytes. An entry's final four bytes give either the value of the information or a pointer to the value. If the size of the information is four bytes or less, then the information is stored here. If it is longer than four bytes, then a pointer to it is stored. The information in directory entry zero is two bytes long and is stored here with a value of 1. (This value has no meaning for this tag.)

As for the next two entries, the first entry has tag=256. This is the image width of the image in number of columns. The type is short and the length of the value is one short, or two bytes. The value 600 means that there are 600 columns in the image. The second entry has tag=257. This is the image length or height in number of rows. The type is short, the length is 1, and the value is 602, meaning that the image has 602 rows.

You continue through the directory entries until you reach the offset to the next IFD. If this offset is 0, as in Figure 2, then no more IFDs follow in the file.

The Code

The code in Listing 1, Listing 2, and Listing 3 read image data from a TIFF file into a 100x100 array of shorts. The code can read four or eight bit gray scale data either most significant byte first or least significant byte first. Future articles will build CIPS (the C Image Processing System) on top of these routines.

Listing 1 (cips.h) contains the #include files and the data structures. The structure tiff_header_struct holds the essential tags we must extract from the TIFF header.

The function read_tiff_header in Listing 2 first determines whether the file uses LSB first or MSB first since the method used influences the manner in which the functions extract_long_from_buffer and extract_short_from_buffer read the remainder of the file header. Next, the offset to the Image File Directory is read. The next section seeks to the IFD and reads the entry count, or number of entries in the IFD. Finally, the code loops over the number of entries. It reads each entry and picks out the necessary tags. The essential information is the width and length of the image, the bits per pixel (four-bit or eight-bit data), and the offset to the start of the data.

The function read_tiff_image in Listing 3 uses read_tiff_header and the header information to read data into a 100x100 array of shorts. The code seeks to the beginning of the data and then to the first line to read. The code in the for loop seeks to the first element on the line, reads the line, and seeks to the end of the line. Each seek depends on the number of bits per pixel. If the file uses eight bits per pixel, then the seeks are integer multiples of the number of pixels. If the files uses four bits per pixel, the seeks are half as long. The function read_line reads the image data into a buffer, then places the data into the array of shorts. read_line uses unions defined in cips.h and also depends on the number of bits per pixel.

The next article in this series will introduce the framework for the C Image Processing System and describe how to display images.

References

1. TIFF Developer's Toolkit, Aldus Corporation, 1988.