|
Packit |
7838c8 |
<HTML>
|
|
Packit |
7838c8 |
<HEAD>
|
|
Packit |
7838c8 |
<TITLE>
|
|
Packit |
7838c8 |
Modifying The TIFF Library
|
|
Packit |
7838c8 |
</TITLE>
|
|
Packit |
7838c8 |
</HEAD>
|
|
Packit |
7838c8 |
<BODY BGCOLOR=white>
|
|
Packit |
7838c8 |
<FONT FACE="Arial, Helvetica, Sans">
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Defining New TIFF Tags
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Libtiff has built-in knowledge of all the standard TIFF tags, as
|
|
Packit |
7838c8 |
well as extentions. The following describes how to add knowledge of
|
|
Packit |
7838c8 |
new tags as builtins to libtiff, or how to application specific tags can
|
|
Packit |
7838c8 |
be used by applications without modifying libtiff.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
TIFFFieldInfo
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
How libtiff manages specific tags is primarily controlled by the
|
|
Packit |
7838c8 |
definition for that tag value stored internally as a TIFFFieldInfo structure.
|
|
Packit |
7838c8 |
This structure looks like this:
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
typedef struct {
|
|
Packit |
7838c8 |
ttag_t field_tag; /* field's tag */
|
|
Packit |
7838c8 |
short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */
|
|
Packit |
7838c8 |
short field_writecount; /* write count/TIFF_VARIABLE */
|
|
Packit |
7838c8 |
TIFFDataType field_type; /* type of associated data */
|
|
Packit |
7838c8 |
unsigned short field_bit; /* bit in fieldsset bit vector */
|
|
Packit |
7838c8 |
unsigned char field_oktochange;/* if true, can change while writing */
|
|
Packit |
7838c8 |
unsigned char field_passcount;/* if true, pass dir count on set */
|
|
Packit |
7838c8 |
char *field_name; /* ASCII name */
|
|
Packit |
7838c8 |
} TIFFFieldInfo;
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
field_tag: the tag number. For instance 277 for the
|
|
Packit |
7838c8 |
SamplesPerPixel tag. Builtin tags will generally have a #define in
|
|
Packit |
7838c8 |
tiff.h for each known tag.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
field_readcount: The number of values which should be read.
|
|
Packit |
7838c8 |
The special value TIFF_VARIABLE (-1) indicates that a variable number of
|
|
Packit |
7838c8 |
values may be read. The special value TIFFTAG_SPP (-2) indicates that there
|
|
Packit |
7838c8 |
should be one value for each sample as defined by TIFFTAG_SAMPLESPERPIXEL.
|
|
Packit |
7838c8 |
The special value TIFF_VARIABLE2 (-3) is presumably similar to TIFF_VARIABLE
|
|
Packit |
7838c8 |
though I am not sure what the distinction in behaviour is. This field
|
|
Packit |
7838c8 |
is TIFF_VARIABLE for variable length ascii fields.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
field_writecount: The number of values which should be written.
|
|
Packit |
7838c8 |
Generally the same as field_readcount. A few built-in exceptions exist, but
|
|
Packit |
7838c8 |
I haven't analysed why they differ.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
field_type: Type of the field. One of TIFF_BYTE, TIFF_ASCII,
|
|
Packit |
7838c8 |
TIFF_SHORT, TIFF_LONG, TIFF_RATIONAL, TIFF_SBYTE, TIFF_UNDEFINED,
|
|
Packit |
7838c8 |
TIFF_SSHORT, TIFF_SLONG, TIFF_SRATIONAL, TIFF_FLOAT, TIFF_DOUBLE or
|
|
Packit |
7838c8 |
TIFF_IFD. Note that some fields can support more than one type (for
|
|
Packit |
7838c8 |
instance short and long). These fields should have multiple TIFFFieldInfos.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
field_bit: Built-in tags stored in special fields in the
|
|
Packit |
7838c8 |
TIFF structure have assigned field numbers to distinguish them (ie.
|
|
Packit |
7838c8 |
FIELD_SAMPLESPERPIXEL). New tags should generally just use
|
|
Packit |
7838c8 |
FIELD_CUSTOM indicating they are stored in the generic tag list.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
field_oktochange: TRUE if it is OK to change this tag value
|
|
Packit |
7838c8 |
while an image is being written. FALSE for stuff that must be set once
|
|
Packit |
7838c8 |
and then left unchanged (like ImageWidth, or PhotometricInterpretation for
|
|
Packit |
7838c8 |
instance).
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
field_passcount: If TRUE, then the count value must be passed
|
|
Packit |
7838c8 |
in TIFFSetField(), and TIFFGetField(), otherwise the count is not required.
|
|
Packit |
7838c8 |
This should generally be TRUE for non-ascii variable count tags unless
|
|
Packit |
7838c8 |
the count is implicit (such as with the colormap).
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
field_name: A name for the tag. Normally mixed case (studly caps)
|
|
Packit |
7838c8 |
like "StripByteCounts" and relatively short.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
A TIFFFieldInfo definition exists for each built-in tag in the tif_dirinfo.c
|
|
Packit |
7838c8 |
file. Some tags which support multiple data types have more than one
|
|
Packit |
7838c8 |
definition, one per data type supported.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Various functions exist for getting the internal TIFFFieldInfo definitions,
|
|
Packit |
7838c8 |
including _TIFFFindFieldInfo(), and _TIFFFindFieldInfoByName(). See
|
|
Packit |
7838c8 |
tif_dirinfo.c for details. There must be some mechanism to get the whole
|
|
Packit |
7838c8 |
list, though I don't see it off hand.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Default Tag Auto-registration
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
In libtiff 3.6.0 a new mechanism was introduced allowing libtiff to
|
|
Packit |
7838c8 |
read unrecognised tags automatically. When an unknown tags is encountered,
|
|
Packit |
7838c8 |
it is automatically internally defined with a default name and a type
|
|
Packit |
7838c8 |
derived from the tag value in the file. Applications only need to predefine
|
|
Packit |
7838c8 |
application specific tags if they need to be able to set them in a file, or
|
|
Packit |
7838c8 |
if particular calling conventions are desired for TIFFSetField() and
|
|
Packit |
7838c8 |
TIFFGetField().
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
When tags are autodefined like this the field_readcount and
|
|
Packit |
7838c8 |
field_writecount values are always TIFF_VARIABLE. The
|
|
Packit |
7838c8 |
field_passcount is always TRUE, and the field_bit is
|
|
Packit |
7838c8 |
FIELD_CUSTOM. The field name will be "Tag %d" where the %d is the tag
|
|
Packit |
7838c8 |
number.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Defining Application Tags
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
For various reasons, it is common for applications to want to define
|
|
Packit |
7838c8 |
their own tags to store information outside the core TIFF specification.
|
|
Packit |
7838c8 |
This is done by calling TIFFMergeFieldInfo() with one or more TIFFFieldInfos.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
The libgeotiff library provides geospatial information extentions within
|
|
Packit |
7838c8 |
a TIFF file. First, a set of TIFFFieldInfo's is prepared with information
|
|
Packit |
7838c8 |
on the new tags:
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
static const TIFFFieldInfo xtiffFieldInfo[] = {
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
/* XXX Insert Your tags here */
|
|
Packit |
7838c8 |
{ TIFFTAG_GEOPIXELSCALE, -1,-1, TIFF_DOUBLE, FIELD_CUSTOM,
|
|
Packit |
7838c8 |
TRUE, TRUE, "GeoPixelScale" },
|
|
Packit |
7838c8 |
{ TIFFTAG_GEOTRANSMATRIX, -1,-1, TIFF_DOUBLE, FIELD_CUSTOM,
|
|
Packit |
7838c8 |
TRUE, TRUE, "GeoTransformationMatrix" },
|
|
Packit |
7838c8 |
{ TIFFTAG_GEOTIEPOINTS, -1,-1, TIFF_DOUBLE, FIELD_CUSTOM,
|
|
Packit |
7838c8 |
TRUE, TRUE, "GeoTiePoints" },
|
|
Packit |
7838c8 |
{ TIFFTAG_GEOKEYDIRECTORY, -1,-1, TIFF_SHORT, FIELD_CUSTOM,
|
|
Packit |
7838c8 |
TRUE, TRUE, "GeoKeyDirectory" },
|
|
Packit |
7838c8 |
{ TIFFTAG_GEODOUBLEPARAMS, -1,-1, TIFF_DOUBLE, FIELD_CUSTOM,
|
|
Packit |
7838c8 |
TRUE, TRUE, "GeoDoubleParams" },
|
|
Packit |
7838c8 |
{ TIFFTAG_GEOASCIIPARAMS, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
|
|
Packit |
7838c8 |
TRUE, FALSE, "GeoASCIIParams" }
|
|
Packit |
7838c8 |
};
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
In order to define the tags, we call TIFFMergeFieldInfo() on the
|
|
Packit |
7838c8 |
desired TIFF handle with the list of TIFFFieldInfos.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
#define N(a) (sizeof (a) / sizeof (a[0]))
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
/* Install the extended Tag field info */
|
|
Packit |
7838c8 |
TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
The tags need to be defined for each TIFF file opened - and when reading
|
|
Packit |
7838c8 |
they should be defined before the tags of the file are read, yet a valid
|
|
Packit |
7838c8 |
TIFF * is needed to merge the tags against. In order to get them
|
|
Packit |
7838c8 |
registered at the appropriate part of the setup process, it is necessary
|
|
Packit |
7838c8 |
to register our merge function as an extender callback with libtiff.
|
|
Packit |
7838c8 |
This is done with TIFFSetTagExtender(). We also keep track of the
|
|
Packit |
7838c8 |
previous tag extender (if any) so that we can call it from our extender
|
|
Packit |
7838c8 |
allowing a chain of customizations to take effect.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
static TIFFExtendProc _ParentExtender = NULL;
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
static
|
|
Packit |
7838c8 |
void _XTIFFInitialize(void)
|
|
Packit |
7838c8 |
{
|
|
Packit |
7838c8 |
static int first_time=1;
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
if (! first_time) return; /* Been there. Done that. */
|
|
Packit |
7838c8 |
first_time = 0;
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
/* Grab the inherited method and install */
|
|
Packit |
7838c8 |
_ParentExtender = TIFFSetTagExtender(_XTIFFDefaultDirectory);
|
|
Packit |
7838c8 |
}
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
The extender callback is looks like this. It merges in our new fields
|
|
Packit |
7838c8 |
and then calls the next extender if there is one in effect.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
static void
|
|
Packit |
7838c8 |
_XTIFFDefaultDirectory(TIFF *tif)
|
|
Packit |
7838c8 |
{
|
|
Packit |
7838c8 |
/* Install the extended Tag field info */
|
|
Packit |
7838c8 |
TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
/* Since an XTIFF client module may have overridden
|
|
Packit |
7838c8 |
* the default directory method, we call it now to
|
|
Packit |
7838c8 |
* allow it to set up the rest of its own methods.
|
|
Packit |
7838c8 |
*/
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
if (_ParentExtender)
|
|
Packit |
7838c8 |
(*_ParentExtender)(tif);
|
|
Packit |
7838c8 |
}
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
The above approach ensures that our new definitions are used when reading
|
|
Packit |
7838c8 |
or writing any TIFF file. However, since on reading we already have
|
|
Packit |
7838c8 |
default definitions for tags, it is usually not critical to pre-define them.
|
|
Packit |
7838c8 |
If tag definitions are only required for writing custom tags, you can just
|
|
Packit |
7838c8 |
call TIFFMergeFieldInfo() before setting new tags. The whole extender
|
|
Packit |
7838c8 |
architecture can then be avoided.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Adding New Builtin Tags
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
A similar approach is taken to the above. However, the TIFFFieldInfo
|
|
Packit |
7838c8 |
should be added to the tiffFieldInfo[] list in tif_dirinfo.c. Ensure that
|
|
Packit |
7838c8 |
new tags are added in sorted order by the tag number.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Normally new built-in tags should be defined with FIELD_CUSTOM; however, if
|
|
Packit |
7838c8 |
it is desirable for the tag value to have it's own field in the TIFFDirectory
|
|
Packit |
7838c8 |
structure, then you will need to #define a new FIELD_ value for it, and
|
|
Packit |
7838c8 |
add appropriate handling as follows:
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Define the tag in tiff.h.
|
|
Packit |
7838c8 |
Add a field to the directory structure in tif_dir.h
|
|
Packit |
7838c8 |
and define a <TT>FIELD_*</TT> bit (also update the definition of
|
|
Packit |
7838c8 |
<TT>FIELD_CODEC</TT> to reflect your addition).
|
|
Packit |
7838c8 |
Add an entry in the <TT>TIFFFieldInfo</TT> array defined at the top of
|
|
Packit |
7838c8 |
tif_dirinfo.c.
|
|
Packit |
7838c8 |
Note that you must keep this array sorted by tag
|
|
Packit |
7838c8 |
number and that the widest variant entry for a tag should come
|
|
Packit |
7838c8 |
first (e.g. <TT>LONG</TT> before <TT>SHORT</TT>).
|
|
Packit |
7838c8 |
Add entries in <TT>_TIFFVSetField()</TT> and <TT>_TIFFVGetField()</TT>
|
|
Packit |
7838c8 |
for the new tag.
|
|
Packit |
7838c8 |
(optional) If the value associated with the tag is not a scalar value
|
|
Packit |
7838c8 |
(e.g. the array for <TT>TransferFunction</TT>) and requires
|
|
Packit |
7838c8 |
special processing,
|
|
Packit |
7838c8 |
then add the appropriate code to <TT>TIFFReadDirectory()</TT> and
|
|
Packit |
7838c8 |
<TT>TIFFWriteDirectory()</TT>. You're best off finding a similar tag and
|
|
Packit |
7838c8 |
cribbing code.
|
|
Packit |
7838c8 |
Add support to <TT>TIFFPrintDirectory()</TT> in tif_print.c
|
|
Packit |
7838c8 |
to print the tag's value.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
If you want to maintain portability, beware of making assumptions
|
|
Packit |
7838c8 |
about data types. Use the typedefs (<TT>uint16</TT>, etc. when dealing with
|
|
Packit |
7838c8 |
data on disk and <TT>t*_t</TT> when stuff is in memory) and be careful about
|
|
Packit |
7838c8 |
passing items through printf or similar vararg interfaces.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Adding New Codec-private Tags
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
To add tags that are meaningful only when a particular compression
|
|
Packit |
7838c8 |
algorithm is used follow these steps:
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Define the tag in tiff.h.
|
|
Packit |
7838c8 |
Allocate storage for the tag values in the private state block of
|
|
Packit |
7838c8 |
the codec.
|
|
Packit |
7838c8 |
Insure the state block is created when the codec is initialized.
|
|
Packit |
7838c8 |
At <TT>TIFFInitfoo</TT> time override the method pointers in the
|
|
Packit |
7838c8 |
TIFF structure
|
|
Packit |
7838c8 |
for getting, setting and printing tag values. For example,
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
sp->vgetparent = tif->tif_vgetfield;
|
|
Packit |
7838c8 |
tif->tif_vgetfield = fooVGetField; /* hook for codec tags */
|
|
Packit |
7838c8 |
sp->vsetparent = tif->tif_vsetfield;
|
|
Packit |
7838c8 |
tif->tif_vsetfield = fooVSetField; /* hook for codec tags */
|
|
Packit |
7838c8 |
tif->tif_printdir = fooPrintDir; /* hook for codec tags */
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
(Actually you may decide not to override the
|
|
Packit |
7838c8 |
<TT>tif_printdir</TT> method, but rather just specify it).
|
|
Packit |
7838c8 |
Create a private <TT>TIFFFieldInfo</TT> array for your tags and
|
|
Packit |
7838c8 |
merge them into the core tags at initialization time using
|
|
Packit |
7838c8 |
<TT>_TIFFMergeFieldInfo</TT>; e.g.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
_TIFFMergeFieldInfo(tif, fooFieldInfo, N(fooFieldInfo));
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
(where <TT>N</TT> is a macro used liberaly throughout the distributed code).
|
|
Packit |
7838c8 |
Fill in the get and set routines. Be sure to call the parent method
|
|
Packit |
7838c8 |
for tags that you are not handled directly. Also be sure to set the
|
|
Packit |
7838c8 |
<TT>FIELD_*</TT> bits for tags that are to be written to the file. Note that
|
|
Packit |
7838c8 |
you can create ``pseudo-tags'' by defining tags that are processed
|
|
Packit |
7838c8 |
exclusively in the get/set routines and never written to file (see
|
|
Packit |
7838c8 |
the handling of <TT>TIFFTAG_FAXMODE</TT> in tif_fax3.c
|
|
Packit |
7838c8 |
for an example of this).
|
|
Packit |
7838c8 |
Fill in the print routine, if appropriate.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Note that space has been allocated in the <TT>FIELD_*</TT> bit space for
|
|
Packit |
7838c8 |
codec-private tags. Define your bits as <TT>FIELD_CODEC+<offset></TT> to
|
|
Packit |
7838c8 |
keep them away from the core tags. If you need more tags than there
|
|
Packit |
7838c8 |
is room for, just increase <TT>FIELD_SETLONGS</TT> at the top of
|
|
Packit |
7838c8 |
tiffiop.h.
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
Last updated: $Date: 2016-09-25 20:05:44 $
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
</BODY>
|
|
Packit |
7838c8 |
|
|
Packit |
7838c8 |
</HTML>
|