Imaging/TIFF/Tags/Documentation/Intergraph Private Tags

Intergraph's Private TIFF Tags

Written by Ed Grissom
Hosted with kind permission of Ed Grissom of Intergraph


This document describes Intergraph's history and current use of private TIFF tags. This information is not proprietary, and can be used by any customers or vendors that need to create or read TIFF files with Intergraph's private tags in them.


Current Use


About 1991, my group at Intergraph began writing TIFF files as output from our applications. At the time, I worked in Digital Imaging and our products were IrasC, ISI, and all photogrammetry applications. Other groups at Intergraph and related companies also had/have applications that write TIFF files, although I was not involved in their development. These other products (over which I had no control) include DP/Studio, IrasB, and MicroStation.

At the time, we had several features available in the Intergraph raster file format that added significantly to the performance of our raster based products. It seemed that TIFF could, or would soon, support similar features that would make TIFF a useable raster format for our products. These features included overviews, tiling, and the ability to store an unlimited amount of application specific data in the raster file.

In 1991, TIFF version 5.0 supported overviews, and a technical note distributed with the TIFF spec. proposed a method for tiling that we were sure would be adopted in TIFF 6.0 (as it was). The only thing left was being able to store application specific data in the file. The TIFF maintainers at Aldus (now Adobe) would give out a block of 5 tags to companies that wished to have private tags for their own use. These tags could be kept private by the company, or they could be published and used by a wider market, although their description would never be in the official TIFF document.

At the time, we also had a Raster Review Committee that was trying to co-ordinate all the uses of raster within the company in preparation for releasing our (proprietary) raster format to the world. The head of the committee, Bill Farnsworth, and I requested a block of tags from Aldus, and I was given responsibility for maintaining their use here at Intergraph.

We immediately used two of the tags to allow TIFF files to have the same capabilities as our INGR raster format. We assigned tag 33919 to be a pointer to an array of 16 flag registers. The details for this tag are below under Current Use. This gave TIFF overviews the same informational capabilities as the INGR overviews.

We also assigned tag 33918 to point to an area of the file containing Intergraph application packets. Intergraph application packets are described in the INGR Raster File Reference Guide, available by request from An abbreviated description is in Appendix. of this document. Note that there is a difference between PACKETS and TAGS. I have been careful to distinguish between them in this document, as confusion can arise if the terms are used interchangeably. PACKETS are an INTERGRAPH internal method of adding application data to a file, whereas TAGS are a fundamental part of the TIFF raster format. One TAG, 33918, points to PACKETS. Non-INGR applications probably do not understand PACKETS, although all TIFF readers should understand TAGS.

There are several different Intergraph applications packets defined, and they can all co-exist in the same raster file. Two that are of importance to this story are the "matrix" packet and the "geotie" packet. The matrix packet was added to allow applications to store a 4x4 transformation matrix that converts raster pixel coordinates to Microstationdesign file coordinates. This allowed our software to automatically place TIFF images into a MicroStation design file as we were already doing with INGR images. INGR format raster files do not need this packet since the transformation matrix is an integral part of the INGR header. The geotiepacket allowed us to tie raster pixel locations to WGS84 lat-long co-ordinates (irrespective of the design file). This packet was also used by INGR format raster files.

The remaining tags were left unused at that time.


In 1993, at the request of one of our customers, we began to explore the possibility of storing more geographic related information in TIFF files that could be read and written by several vendors software. There were several problems with getting other vendors to support our (then) current method of storing matrix and geotiePACKETS in the TIFF file. First of all, the matrix referred to MicroStation Design file coordinates, not a general model space; secondly, the geotiepacket was fixed to the WGS84 projection system - which, although widely used, is not suitable for all locations on the globe; and thirdly, the application packets had to be stored in "little-endian" order, even if the TIFF file was "big endian". If you need more explanation of this problem, contact me. Suffice it to say that this and other "features" of the INGR application packet format were major stumbling blocks to widespread use of our (then) current method.

Due to these limitations, we proposed using our three remaining tags to define a more general geographic location method. I began a mailing list to several interested developers, vendors, and customers, and proposed using tag 33920 as a more general "raster-to-MODEL" matrix, tag 33921 as a general "GeoReferencing" tag, and tag 33922 as a general "GeoTie" tag.

I put the following disclaimer in all the correspondence:

One last note: currently, no one is writing files conforming to this proposed standard. Until the draft is completed, it would be unwise to begin to write these files.

Unfortunately, IrasB developers saw the new matrix tag as a way to solve some customer complaints, and without knowing about the existing matrix PACKET that goes from raster-to-DGNfile, they began using the proposed raster-to-MODEL TAG as a raster-to-DGNfile matrix. They did not consult with the Raster Review Committee nor with me before they began using this tag for an unintended purpose. Here is the text of my proposal which, I believe, they used for their implementation.

Transformation Matrix

A raster-to-model transformation matrix.

Tag = ??? ( can be 33920 if we use Intergraph's tags)
Type = 12 ( Double -- new for TIFF 6.0)
N = 17

The first 16 values (named a-p and ordered alphabetically) are to be used to compute model coordinates from raster coordinates according to the following matrix equation

X = a b c d * x
Y e f g h y
Z i j k l z
1 m n o p 1

This matrix allows scaling, rotation, and offsets in all three coordinate axis. The values 'm', 'n', and 'o' are normally zero.

Value 'p' can be a "global" scaling factor, however scaling can also be included in the rest of the matrix. This matrix transforms each point of the raster to a point in 3D model space. 'z' is normally zero (or constant) for images, however, Z' need not be 0 nor constant. The default matrix can be considered to be:

The 17th value, 'q', is a "units" code, and can take on the following values:

0.0 = No units, or use units of model space. (default)
1.0 = meters/pix,
2.0 = feet/pix,
3.0 = radians/pix...
(more can be defined)

If this tag (and matrix) exist, applications that understand the matrix should use the values in the matrix to supersede the values in tags 282 and 283 (x and y resolution), tags 286 or 287 x and y position), and tag 296 (resolution unit) if necessary.

Applications that do not understand the matrix will not be able to "properly" orient the file anyway, and should use any info they deem necessary to place the image in a window.

Tag 274 (orientation) can cause the matrix to be re-interpreted. Which pixels are x(0)...x(ppl-1) should be governed by the orientation tag before the matrix equation is used to determine model space coordinates.

Other tags (see below) may be used to define the model space that the matrix refers to. By default it will apply to the current window system.

I realize that the "units" code does not fit in well with this type of data. It is really a flag or integer value. However, it is possible for the matrix to be the only positional referencing tag that is available (i.e. Geo-names and Geo- reference are not required for the matrix to be valid). Thus the units need to be contained with the matrix.

Meanwhile, our mailing list continued to discuss and change my original proposal into something completely different. We decided to use only two of our tags, and to change the definition of them to better fit in with the overall scheme. Several other vendors contributed tags and ideas, and the completed spec was published in June 1995 as GeoTIFF v. 1.0. This document is available at

In that document, the following note describes the changes that had to be made when we found out that IrasB was already using one of the tags that we wanted to use in the GeoTIFF specification.

The former ModelTransformationTag (33920) conflicts with an internal Intergraph implementation and is being deprecated, in favor of a new tag (34264, registered to JPL).

In Revision 0.2 and earlier, tag 33920 was used for this matrix, which has been renamed as follows:

Tag = 33920 (8480.H)
N = 17 (Intergraph implementation) or 16 (GeoTIFF 0.2 impl.)
Owner = Intergraph

This tag conflicts with an internal software implementation at Intergraph, and so its use is no longer encouraged. A GeoTIFF reader should look first for the new tag, and only if it is not found should it check for this older tag. If found, it should only consider it to be contain valid GeoTIFF matrix information if the tag-count is 16; the Intergraph version uses 17 values.

So, in IrasB files, tag 33920 may be present and would contain 17 values. In early GeoTIFF files, tag 33920 may be present and would contain 16 values, and in later GeoTIFf files, tag 33920 should not be present. In reality, there were never many GeoTIFF files distributed (none?) that had the 16 entry tag, so if you do see this tag, it is more than likely to be the 17 entry IrasB version. In either case, the first 16 entries should serve as the 4x4 transformation matrix described above, while the 17'th (if present) is a units flag. The difference is that in the IrasB (17 entry) case, it is a raster-to-DGN transformation, while in GeoTIFF (16 entry) it is a raster-to-model transformation where the model is described elsewhere.

Current Use

Here are the definitions for INGR's private tags as of 6/3/96:

INGR Packet Data Tag
Tag = 33918
Type = SHORT
N = Variable, but if greater than 0, must be greater than 4 since every PACKET has at least 4 shorts in it. This means that the ValueOffset field of the tag is always an Offset instead of a Value.

The offset points to an area of the file containing "N" shorts that make up at least one and perhaps more INGR PACKETS. See appendix. for more info on INGR PACKETS. Note that INGR PACKETS contain their own indexing scheme outside of TIFF that allows access to more than one packet in this area.

INGR Flag Registers
Tag = 33919
Type = LONG
N = 16 - ValueOffset is always an Offset.

Each of the 16 registers is a 32-bit integer. The bottom two bits of the first register were assigned the following meanings:

0 Overview (if any) was created by subsampling.
1 Overview (if any) was created by an XOR process.
2 Overview (if any) was created by averaging.
3 Overview (if any) was created by 5x5 Gaussian Kernel

The second register is now used to represent a value to be used for "uninstantiated" tiles in the TIFF file. This value is replicated to all bands. This value should be ok for 8, 16, or 32 bit data. Uninstantiated tiles violate the TIFF spec, and are only used for internal ZI images. No files that are to be interchanged with other apps should have uninstantiated tiles.

No other meanings have been assigned.

IrasB Transformation Matrix
Tag = 33920
N = 17 (possibly 16, but unlikely)


The first 16 values (named a-p and ordered alphabetically) are to be used to compute DESIGN FILE coordinates from raster coordinates according to the following matrix equation

X = a b c d * x
Y e f g h y
Z i j k l z
1 m n o p 1

This matrix allows scaling, rotation, and offsets in all three coordinate axis. The values 'm', 'n', and 'o' are normally zero. Value 'p' can be a "global" scaling factor, however scaling can also be included in the rest of the matrix. This matrix transforms each point of the raster to a point in 3D model space. 'z' is normally zero (or constant) for images, however, 'Z' need not be 0 nor constant. The default matrix can be considered to be:

The 17th value, 'q', is a "units" code, and can take on the following values:

0.0 = No units, or use units of model space. (default)
1.0 = meters/pix,
2.0 = feet/pix,
3.0 = radians/pix...
(no others have been defined)

Tag = 33921
Type = unspecified
N = unspecified

This tag currently has not been defined. A proposed definition was published, but in the final document, this tag was not needed.

Tag = 33922 (8482.H)
Type = DOUBLE (IEEE Double precision)
N = 6*K, K = number of tiepoints


This tag stores raster->model tiepoint pairs in the order ModelTiepointTag = (...,I,J,K, X,Y,Z...), where (I,J,K) is the point at location (I,J) in raster space with pixel-value K, and (X,Y,Z) is a vector in model space. In most cases the model space is only two-dimensional, in which case both K and Z should be set to zero; this third dimension is provided in anticipation of future support for 3D digital elevation models and vertical coordinate systems.

Appendix - Intergraph packets

All Intergraph application packets have identifying numbers and a length field so that unrecognized packets can be skipped over. A generic packet looks like this:

Word offsetWord
0Type (= 2 for Img.Sys.)Packet header
1Sub Type (=???)
2Words to follow
(WTF+4==total size of packet)
Format is defined by packet creator
Pad (if necessary) to 8-byte boundary.
WTF includes pad.

There are many Intergraph application packets defined. Below I describe two of them that are important for this document.

The geo-tie packet is defined by the following structure:

struct GEO_TIE
    short type;
    short subtype;
    long wtf;
    long num_points;
    long pad_to_dword;
    struct points_st
        double lon;
        double lat;
        double row;
        double col;

    } geo_tie[1];

/* == 2 for Imaging Systems */
/* == 11 for geo-tie */
/* == (16*num_points)+4 for geo-tie */
/* minimum of 4 */
/* pad so doubles begin on double boundary */

/* in radians, referenced to WGS 84 horizontal datum */
/* " " */
/* zero-based, i.e., the upper left hand corner of */
/* the upper left-most pixel is 0.0, 0.0; the center*/
/* of the upper left-most pixel is 0.5, 0.5; etc. */

Although the structure contains an array with a single element, this is just a programmers trick to fool a strict compiler. There will really be "num_points" elements in the array.

Of course, the geo-tie packet begins with the type, subtype and wtf fields common to all packets. The type is 2, subtype 11, and wtf depends on the number of points in the following way:

wtf = (16*num_points) + 4
(the "words" in words-to-follow, wtf, refers to 16-bit words)

The matrix packet is defined by the following structure:

typedef struct matrix_st
    short type;
    short subtype;
    long wtf;
    double mat[16];
    char key_fname[80];


/* == 2 for Imaging Systems */
/* == 10 for matrix */
/* == 104 for matrix */
/* raster to DGN file xform matrix*/
/* filename of .dgn file this matrix is */
/* associated with. there may be several */
/* matrix packets in a file. */

*ONLY* for use in TIFF files -- INGR files have a different method for setting the matrix. The matrix packet (2,10) is needed for TIFF files which have no provisions for storing a transformation matrix. Each copy of packet 10 defines a separate transformation matrix. This is needed for raster files which may be used as backdrops for more than one design file.

The method for keying the design file to the matrix is through a null terminated string (i.e. filename). It is up to the application to request the packet data and parse the matrix packets to find the matrix corresponding to the current design file. A NULL filename (minimum two bytes of 0) is an acceptable key string for possibly more than one matrix. It is up to the application to determine how to handle this.

Note 1.
The geo-tie packet or the matrix packet may not be the only Intergraph packet stored with this tag. If there are packets besides the geo-tie packet, the best recourse is to read the whole set of packets into a buffer, and look at the type and subtype of the first. If they are not 2 and 11 (10 for matrix) respectively, use the wtf to skip to the start of the next packet and repeat until you find the packet of interest. (it is possible that no geo-tie or matrix packet appears)

Note 2.
Intergraph files are stored in "little-endian" byte order. All data in Intergraph packets are stored in "little-endian" byte-order. Even if the TIFF file is "MM" format, the Intergraph packet data will be in "little-endian" byte-order. In this confusing case, the TIFF tag that points to the Intergraph packet data will be big-endian, but the data the tag points to will be little-endian. This is due to the fact that the application does not know {nor need to know} that the file is little or big-endian, but the raster I/O library does not know {nor need to know} the contents of the application packet. Thus to keep both happy, we require little endian format all the time, and the application must be aware if it is running on a big or little endian machine.)