typedef struct { ttag_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;
Various functions exist for getting the internal TIFFFieldInfo definitions, including _TIFFFindFieldInfo(), and _TIFFFindFieldInfoByName(). See tif_dirinfo.c for details. There must be some mechanism to get the whole list, though I don't see it off hand.
When tags are autodefined like this the field_readcount and field_writecount values are always TIFF_VARIABLE2 (-3). The field_passcount is always TRUE, and the field_bit is 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);
The libgeotiff library provides geospatial information extensions within a TIFF file. First, a set of TIFFFieldInfo's 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" } };
#define N(a) (sizeof (a) / sizeof (a[0])) /* Install the extended Tag field info */ TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));
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); }
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); }
A similar approach is taken to the above. However, the TIFFFieldInfo should be added to the tiffFieldInfo[] list in tif_dirinfo.c. Ensure that new tags are added in sorted order by the tag number.
Normally new built-in tags should be defined with FIELD_CUSTOM; however, if it is desirable for the tag value to have it's own field in the TIFFDirectory structure, then you will need to #define a new FIELD_ value for it, and add appropriate handling as follows:
If you want to maintain portability, beware of making assumptions about data types. Use the typedefs (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.
To add tags that are meaningful only when a particular compression algorithm is used follow these steps:
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 */
_TIFFMergeFieldInfo(tif, fooFieldInfo, N(fooFieldInfo));