File: addingtags.rst

package info (click to toggle)
tiff 4.7.1-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 9,704 kB
  • sloc: ansic: 92,024; makefile: 966; cpp: 964; sh: 964; python: 151
file content (370 lines) | stat: -rw-r--r-- 15,687 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
Defining New TIFF Tags
======================

Libtiff has built-in knowledge of all the standard TIFF tags, as
well as extensions.  The following describes how to add knowledge of
new tags as builtins to libtiff, or how to application specific tags can
be used by applications without modifying libtiff.

.. _TIFFFieldInfo_Definition:

TIFFFieldInfo
-------------

How libtiff manages specific tags is primarily controlled by the
definition for that tag value stored internally as a TIFFFieldInfo structure.
This structure looks like this:

.. highlight:: c

::

    typedef struct {
      uint32_t       field_tag;        /* field's tag */
      short          field_readcount;  /* read count / TIFF_VARIABLE / TIFF_VARIABLE2 / TIFF_SPP */
      short          field_writecount; /* write count / TIFF_VARIABLE / TIFF_VARIABLE2 */
      TIFFDataType   field_type;       /* type of associated data */
      unsigned short field_bit;        /* bit in fieldsset bit vector */
      unsigned char  field_oktochange; /* if true, can change while writing */
      unsigned char  field_passcount;  /* if true, pass dir count on set */
      char          *field_name;       /* ASCII name */
    } TIFFFieldInfo;


.. c:member:: uint32_t TIFFFieldInfo.field_tag

    The tag number.  For instance 277 for the
    SamplesPerPixel tag.  Builtin tags will generally have a ``#define`` in
    :file:`tiff.h` for each known tag.

.. c:member:: short TIFFFieldInfo.field_readcount

    The number of values which should be read.
    The special value :c:macro:`TIFF_VARIABLE` (-1) indicates that a variable number of
    values may be read.  The special value :c:macro:`TIFFTAG_SPP` (-2) indicates that there
    should be one value for each sample as defined by :c:macro:`TIFFTAG_SAMPLESPERPIXEL`.
    The special value :c:macro:`TIFF_VARIABLE2` (-3) is similar to :c:macro:`TIFF_VARIABLE`
    but the required TIFFGetField() count value must be uint32_t* instead of uint16_t* as
    for :c:macro:`TIFF_VARIABLE` (-1).
    For ASCII fields with variable length, this field is :c:macro:`TIFF_VARIABLE`.

.. c:member:: short TIFFFieldInfo.field_writecount

    The number of values which should be written.
    Generally the same as field_readcount.  A few built-in exceptions exist, but
    I haven't analysed why they differ.

.. c:member:: TIFFDataType TIFFFieldInfo.field_type

    Type of the field.  One of :c:enumerator:`TIFF_BYTE`, :c:enumerator:`TIFF_ASCII`,
    :c:enumerator:`TIFF_SHORT`, :c:enumerator:`TIFF_LONG`,
    :c:enumerator:`TIFF_RATIONAL`, :c:enumerator:`TIFF_SBYTE`,
    :c:enumerator:`TIFF_UNDEFINED`, :c:enumerator:`TIFF_SSHORT`,
    :c:enumerator:`TIFF_SLONG`, :c:enumerator:`TIFF_SRATIONAL`,
    :c:enumerator:`TIFF_FLOAT`, :c:enumerator:`TIFF_DOUBLE` or
    :c:enumerator:`TIFF_IFD`.
    And for BigTIFF :c:enumerator:`TIFF_LONG8`,
    :c:enumerator:`TIFF_SLONG8` and :c:enumerator:`TIFF_IFD8`,
    which are automatically reverted to 4 byte fields in
    ClassicTIFF.

.. c:member:: unsigned short TIFFFieldInfo.field_bit

    Built-in tags stored in special fields in the
    TIFF structure have assigned field numbers to distinguish them (e.g.
    :c:macro:`FIELD_SAMPLESPERPIXEL`).  New tags should generally just use
    :c:macro:`FIELD_CUSTOM` indicating they are stored in the generic tag list.

.. c:member:: unsigned char TIFFFieldInfo.field_oktochange

    TRUE if it is OK to change this tag value
    while an image is being written.  FALSE for stuff that must be set once
    and then left unchanged (like ImageWidth, or PhotometricInterpretation for
    instance).

.. c:member:: unsigned char TIFFFieldInfo.field_passcount

    If TRUE, then the count value must be passed
    in :c:func:`TIFFSetField`, and :c:func:`TIFFGetField`, otherwise the count is not required.
    This should generally be TRUE for non-ascii variable count tags unless
    the count is implicit (such as with the colormap).

.. c:member:: char * TIFFFieldInfo.field_name

    A name for the tag.  Normally mixed case (studly caps)
    like ``StripByteCounts``, and relatively short.

Within :file:`tif_dirinfo.c` file, the built-in TIFF tags are defined with
:c:struct:`TIFFField` structure that has additional parameters defining the var_arg
interface of :c:func:`TIFFSetField` and :c:func:`TIFFGetField`.

Various functions exist for getting the internal :c:struct:`TIFFFieldInfo`
definitions, including :c:func:`_TIFFFindFieldInfo`, and
:c:func:`_TIFFFindFieldInfoByName`.  See
:file:`tif_dirinfo.c` for details.

.. _Tag_Auto_registration:

Default Tag Auto-registration
-----------------------------

In libtiff 3.6.0 a new mechanism was introduced allowing libtiff to
read unrecognised tags automatically.  When an unknown tags is encountered,
it is automatically internally defined with a default name and a type
derived from the tag value in the file.  Applications only need to predefine
application specific tags if they need to be able to set them in a file, or
if particular calling conventions are desired for :c:func:`TIFFSetField` and
:c:func:`TIFFGetField`.

When tags are autodefined like this the :c:member:`field_readcount` and
:c:member:`field_writecount` values are always :c:macro:`TIFF_VARIABLE2` (-3).  The
:c:member:`field_passcount` is always TRUE, and the :c:member:`field_bit` is
:c:macro:`FIELD_CUSTOM`.  The field name will be ``Tag %d`` where the ``%d``
is the tag number.

Thus, to read anonymous auto-registered tags use the following:

::

    uint32_t count;
    void* value;  //has to be a pointer to the expected value type.
    TIFFGetField(tif, TIFFTAG_UNKNOWN_TO_LIBTIFF, &count, &value);


.. _Define_Application_Tags:

Defining Application Tags
-------------------------

For various reasons, it is common for applications to want to define
their own tags to store information outside the core TIFF specification.
This is done by calling :c:func:`TIFFMergeFieldInfo` with one or more
:c:struct:`TIFFFieldInfo`.

The libgeotiff library provides geospatial information extensions within
a TIFF file.  First, an array of :c:struct:`TIFFFieldInfo` is prepared with
information on the new tags:

::

    static const TIFFFieldInfo xtiffFieldInfo[] = {

        /* XXX Insert Your tags here */
        { TIFFTAG_GEOPIXELSCALE,	-1,-1, TIFF_DOUBLE,	FIELD_CUSTOM,
          TRUE,	TRUE,	"GeoPixelScale" },
        { TIFFTAG_GEOTRANSMATRIX,	-1,-1, TIFF_DOUBLE,	FIELD_CUSTOM,
          TRUE,	TRUE,	"GeoTransformationMatrix" },
        { TIFFTAG_GEOTIEPOINTS,	-1,-1, TIFF_DOUBLE,	FIELD_CUSTOM,
          TRUE,	TRUE,	"GeoTiePoints" },
        { TIFFTAG_GEOKEYDIRECTORY, -1,-1, TIFF_SHORT,	FIELD_CUSTOM,
          TRUE,	TRUE,	"GeoKeyDirectory" },
        { TIFFTAG_GEODOUBLEPARAMS,	-1,-1, TIFF_DOUBLE,	FIELD_CUSTOM,
          TRUE,	TRUE,	"GeoDoubleParams" },
        { TIFFTAG_GEOASCIIPARAMS,	-1,-1, TIFF_ASCII,	FIELD_CUSTOM,
          TRUE,	FALSE,	"GeoASCIIParams" }
    };

In order to define the tags, we call :c:func:`TIFFMergeFieldInfo` on the
desired TIFF handle with the list of :c:struct:`TIFFFieldInfo`.

::

    #define	N(a)	(sizeof (a) / sizeof (a[0]))

    /* Install the extended Tag field info */
    TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));

The tags need to be defined for each TIFF file opened - and when reading
they should be defined before the tags of the file are read, yet a valid
:c:expr:`TIFF *` is needed to merge the tags against.  In order to get them
registered at the appropriate part of the setup process, it is necessary
to register our merge function as an extender callback with libtiff.
This is done with :c:func:`TIFFSetTagExtender`.  We also keep track of the
previous tag extender (if any) so that we can call it from our extender
allowing a chain of customizations to take effect.

::

    static TIFFExtendProc _ParentExtender = NULL;

    static
    void _XTIFFInitialize(void)
    {
        static int first_time=1;
	
        if (! first_time) return; /* Been there. Done that. */
        first_time = 0;
	
        /* Grab the inherited method and install */
        _ParentExtender = TIFFSetTagExtender(_XTIFFDefaultDirectory);
    }

The extender callback is looks like this.  It merges in our new fields
and then calls the next extender if there is one in effect.

::

    static void
    _XTIFFDefaultDirectory(TIFF *tif)
    {
        /* Install the extended Tag field info */
        TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));

        /* Since an XTIFF client module may have overridden
         * the default directory method, we call it now to
         * allow it to set up the rest of its own methods.
         */

        if (_ParentExtender)
            (*_ParentExtender)(tif);
    }

The above approach ensures that our new definitions are used when reading
or writing any TIFF file.  However, since on reading we already have
default definitions for tags, it is usually not critical to pre-define them.
If tag definitions are only required for writing custom tags, you can just
call :c:func:`TIFFMergeFieldInfo` before setting new tags.  The whole extender
architecture can then be avoided.

Adding New Builtin Tags
-----------------------

A similar approach is taken to the above.  However, the :c:struct:`_TIFFField`
information should be added to the :c:expr:`tiffFields[]` list in
:file:`tif_dirinfo.c`. This :c:struct:`_TIFFField` structure is like
TIFFFieldInfo structure but has additional members:

The tags in the :c:expr:`tiffFields[]` list need not to be in sorted
order by the tag number. Sorting is done when setting up the
:c:expr:`TIFFFieldArray` at IFD initialization.

.. highlight:: c

::

    typedef struct _TIFFField {
      uint32_t             field_tag;        /* field's tag */
      short                field_readcount;  /* read count / TIFF_VARIABLE / TIFF_VARIABLE2 / TIFF_SPP */
      short                field_writecount; /* write count / TIFF_VARIABLE / TIFF_VARIABLE2 */
      TIFFDataType         field_type;       /* type of associated data */
      uint32_t             field_anonymous;  /* if true, this is a unknown / anonymous tag */
      TIFFSetGetFieldType  set_field_type;   /* type to be passed to TIFFSetField and TIFFGetField */
      TIFFSetGetFieldType  get_field_type;   /* not used */
      unsigned short       field_bit;        /* bit in fieldsset bit vector */
      unsigned char        field_oktochange; /* if true, can change while writing */
      unsigned char        field_passcount;  /* if true, pass dir count on set */
      char                *field_name;       /* ASCII name */
      TIFFFieldArray      *field_subfields;  /* if field points to child ifds, child ifd field definition array */ 
    };


.. c:member:: uint32_t _TIFFField.field_anonymous

    Used internally to indicate auto-registered tags.
    See :c:func:`TIFFFieldIsAnonymous`.

.. c:member:: TIFFSetGetFieldType _TIFFField.set_field_type

    | The enummeration identifier gives a hint and defines the `vararg`
      parameters passed to :c:func:`TIFFSetField` and :c:func:`TIFFGetField`.
    | For example :c:enum:`TIFF_SETGET_UINT64` defines a single
      ``uint64_t`` parameter to be passed to `TIFFSetField()` and
      `TIFFGetField()`, respectively.
    | To distinguish the three different array types, there are three
      strings before the value type within the enummeration identifier
      (e.g. TIFF_SETGET_C0_UINT64):
    | "**_C0_**" for fixed arrays and thus no count parameter is required
      for TIFFSetField() and TIFFGetField(), respectively.
      The array length is constant and given by `field_readcount` or
      `field_writecount`, respectively.
    | "**_C16_**" and "**_C32_**" are for variable arrays with ``uint16_t``
      or ``uint32_t`` count parameter required for TIFFSetField() and
      TIFFGetField(), respectively. But then, `field_readcount` and
      `field_writecount` has to be set to -1 for _C16_ and -3 for _C32_,
      respectively.

.. c:member:: TIFFSetGetFieldType _TIFFField.get_field_type

    Currently, this parameter is not used for TIFFGetField().
    Nevertheless, it is set as a copy of set_field_type or set to
    `TIFF_SETGET_UNDEFINED`.

Normally new built-in tags should be defined with :c:macro:`FIELD_CUSTOM`
and then only two points need to be done:

#. Define the tag in :file:`tiff.h`.
#. Add an entry in the :c:expr:`tiffFields[]` array list defined at the
   top of :file:`tif_dirinfo.c`.

However, if it is desirable for the tag value to have its own field in
the :c:struct:`TIFFDirectory` structure, then you will also need to
``#define`` a new :c:macro:`FIELD_` value for it, and add appropriate
handling as follows:

#. Add a field to the :c:struct:`TIFFDirectory` structure in :file:`tif_dir.h`
   and define a ``FIELD_*`` bit number (also update the definition of
   :c:macro:`FIELD_CODEC` to reflect your addition).
#. Add entries in :c:func:`_TIFFVSetField` and :c:func:`_TIFFVGetField`
   for the new tag.
#. (*optional*) If the value associated with the tag is not a scalar value
   (e.g. the array for ``TransferFunction``) and requires
   special processing,
   then add the appropriate code to :c:func:`TIFFReadDirectory` and
   :c:func:`TIFFWriteDirectory`.  You're best off finding a similar tag and
   cribbing code.
#. Add support to :c:func:`TIFFPrintDirectory` in :file:`tif_print.c`
   to print the tag's value.

If you want to maintain portability, beware of making assumptions
about data types.  Use the typedefs (:c:type:`uint16_t`, etc. when dealing with
data on disk and ``t*_t`` when stuff is in memory) and be careful about
passing items through printf or similar vararg interfaces.

Adding New Codec-private Tags
-----------------------------

To add tags that are meaningful *only when a particular compression
algorithm is used* follow these steps:

#. Define the tag in :file:`tiff.h`.
#. Allocate storage for the tag values in the private state block of
   the codec.
#. Insure the state block is created when the codec is initialized.
#. At :c:func:`TIFFInitfoo` time override the method pointers in the
   :c:struct:`TIFF` structure for getting, setting and printing tag values.
   For example,

   ::

      sp->vgetparent = tif->tif_vgetfield;
      tif->tif_vgetfield = fooVGetField;	/* hook for codec tags */
      sp->vsetparent = tif->tif_vsetfield;
      tif->tif_vsetfield = fooVSetField;	/* hook for codec tags */
      tif->tif_printdir = fooPrintDir;	/* hook for codec tags */

   (Actually you may decide not to override the
   :c:member:`tif_printdir` method, but rather just specify it).
#. Create a private :c:struct:`TIFFFieldInfo` array for your tags and
   merge them into the core tags at initialization time using
   :c:func:`_TIFFMergeFieldInfo`; e.g.

   ::

       _TIFFMergeFieldInfo(tif, fooFieldInfo, N(fooFieldInfo));

   (where :c:macro:`N` is a macro used liberaly throughout the distributed code).

#. Fill in the get and set routines.  Be sure to call the parent method
   for tags that you are not handled directly.  Also be sure to set the
   ``FIELD_*`` bits for tags that are to be written to the file.  Note that
   you can create "pseudo-tags" by defining tags that are processed
   exclusively in the get/set routines and never written to file (see
   the handling of :c:macro:`TIFFTAG_FAXMODE` in :file:`tif_fax3.c`
   for an example of this).
#. Fill in the print routine, if appropriate.

Note that space has been allocated in the ``FIELD_*`` bit space for
codec-private tags.  Define your bits as ``FIELD_CODEC+<offset>`` to
keep them away from the core tags. If you need more tags than there
is room for, just increase :c:macro:`td_fieldsset` at the top of
:file:`tif_dir.h`.