Move the sources to trunk
[opencv] / otherlibs / _graphics / src / libtiff / tif_dirinfo.c
1 /* $Id: tif_dirinfo.c,v 1.1 2005/06/17 13:54:52 vp153 Exp $ */
2
3 /*
4  * Copyright (c) 1988-1997 Sam Leffler
5  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and 
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  * 
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
18  * 
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
24  * OF THIS SOFTWARE.
25  */
26
27 /*
28  * TIFF Library.
29  *
30  * Core Directory Tag Support.
31  */
32 #include "tiffiop.h"
33 #include <stdlib.h>
34 #include <stdio.h>
35
36 /*
37  * NB: NB: THIS ARRAY IS ASSUMED TO BE SORTED BY TAG.
38  *     If a tag can have both LONG and SHORT types
39  *     then the LONG must be placed before the SHORT for
40  *     writing to work properly.
41  *
42  * NOTE: The second field (field_readcount) and third field (field_writecount)
43  *       sometimes use the values TIFF_VARIABLE (-1), TIFF_VARIABLE2 (-3)
44  *       and TIFFTAG_SPP (-2). The macros should be used but would throw off 
45  *       the formatting of the code, so please interprete the -1, -2 and -3 
46  *       values accordingly.
47  */
48 #ifndef VMS
49 static 
50 #endif
51 const TIFFFieldInfo tiffFieldInfo[] = {
52     { TIFFTAG_SUBFILETYPE,       1, 1, TIFF_LONG,       FIELD_SUBFILETYPE,
53       TRUE,     FALSE,  "SubfileType" },
54 /* XXX SHORT for compatibility w/ old versions of the library */
55     { TIFFTAG_SUBFILETYPE,       1, 1, TIFF_SHORT,      FIELD_SUBFILETYPE,
56       TRUE,     FALSE,  "SubfileType" },
57     { TIFFTAG_OSUBFILETYPE,      1, 1, TIFF_SHORT,      FIELD_SUBFILETYPE,
58       TRUE,     FALSE,  "OldSubfileType" },
59     { TIFFTAG_IMAGEWIDTH,        1, 1, TIFF_LONG,       FIELD_IMAGEDIMENSIONS,
60       FALSE,    FALSE,  "ImageWidth" },
61     { TIFFTAG_IMAGEWIDTH,        1, 1, TIFF_SHORT,      FIELD_IMAGEDIMENSIONS,
62       FALSE,    FALSE,  "ImageWidth" },
63     { TIFFTAG_IMAGELENGTH,       1, 1, TIFF_LONG,       FIELD_IMAGEDIMENSIONS,
64       TRUE,     FALSE,  "ImageLength" },
65     { TIFFTAG_IMAGELENGTH,       1, 1, TIFF_SHORT,      FIELD_IMAGEDIMENSIONS,
66       TRUE,     FALSE,  "ImageLength" },
67     { TIFFTAG_BITSPERSAMPLE,    -1,-1, TIFF_SHORT,      FIELD_BITSPERSAMPLE,
68       FALSE,    FALSE,  "BitsPerSample" },
69 /* XXX LONG for compatibility with some broken TIFF writers */
70     { TIFFTAG_BITSPERSAMPLE,    -1,-1, TIFF_LONG,       FIELD_BITSPERSAMPLE,
71       FALSE,    FALSE,  "BitsPerSample" },
72     { TIFFTAG_COMPRESSION,      -1, 1, TIFF_SHORT,      FIELD_COMPRESSION,
73       FALSE,    FALSE,  "Compression" },
74 /* XXX LONG for compatibility with some broken TIFF writers */
75     { TIFFTAG_COMPRESSION,      -1, 1, TIFF_LONG,       FIELD_COMPRESSION,
76       FALSE,    FALSE,  "Compression" },
77     { TIFFTAG_PHOTOMETRIC,       1, 1, TIFF_SHORT,      FIELD_PHOTOMETRIC,
78       FALSE,    FALSE,  "PhotometricInterpretation" },
79 /* XXX LONG for compatibility with some broken TIFF writers */
80     { TIFFTAG_PHOTOMETRIC,       1, 1, TIFF_LONG,       FIELD_PHOTOMETRIC,
81       FALSE,    FALSE,  "PhotometricInterpretation" },
82     { TIFFTAG_THRESHHOLDING,     1, 1, TIFF_SHORT,      FIELD_THRESHHOLDING,
83       TRUE,     FALSE,  "Threshholding" },
84     { TIFFTAG_CELLWIDTH,         1, 1, TIFF_SHORT,      FIELD_IGNORE,
85       TRUE,     FALSE,  "CellWidth" },
86     { TIFFTAG_CELLLENGTH,        1, 1, TIFF_SHORT,      FIELD_IGNORE,
87       TRUE,     FALSE,  "CellLength" },
88     { TIFFTAG_FILLORDER,         1, 1, TIFF_SHORT,      FIELD_FILLORDER,
89       FALSE,    FALSE,  "FillOrder" },
90     { TIFFTAG_DOCUMENTNAME,     -1,-1, TIFF_ASCII,      FIELD_DOCUMENTNAME,
91       TRUE,     FALSE,  "DocumentName" },
92     { TIFFTAG_IMAGEDESCRIPTION, -1,-1, TIFF_ASCII,      FIELD_IMAGEDESCRIPTION,
93       TRUE,     FALSE,  "ImageDescription" },
94     { TIFFTAG_MAKE,             -1,-1, TIFF_ASCII,      FIELD_MAKE,
95       TRUE,     FALSE,  "Make" },
96     { TIFFTAG_MODEL,            -1,-1, TIFF_ASCII,      FIELD_MODEL,
97       TRUE,     FALSE,  "Model" },
98     { TIFFTAG_STRIPOFFSETS,     -1,-1, TIFF_LONG,       FIELD_STRIPOFFSETS,
99       FALSE,    FALSE,  "StripOffsets" },
100     { TIFFTAG_STRIPOFFSETS,     -1,-1, TIFF_SHORT,      FIELD_STRIPOFFSETS,
101       FALSE,    FALSE,  "StripOffsets" },
102     { TIFFTAG_ORIENTATION,       1, 1, TIFF_SHORT,      FIELD_ORIENTATION,
103       FALSE,    FALSE,  "Orientation" },
104     { TIFFTAG_SAMPLESPERPIXEL,   1, 1, TIFF_SHORT,      FIELD_SAMPLESPERPIXEL,
105       FALSE,    FALSE,  "SamplesPerPixel" },
106     { TIFFTAG_ROWSPERSTRIP,      1, 1, TIFF_LONG,       FIELD_ROWSPERSTRIP,
107       FALSE,    FALSE,  "RowsPerStrip" },
108     { TIFFTAG_ROWSPERSTRIP,      1, 1, TIFF_SHORT,      FIELD_ROWSPERSTRIP,
109       FALSE,    FALSE,  "RowsPerStrip" },
110     { TIFFTAG_STRIPBYTECOUNTS,  -1,-1, TIFF_LONG,       FIELD_STRIPBYTECOUNTS,
111       FALSE,    FALSE,  "StripByteCounts" },
112     { TIFFTAG_STRIPBYTECOUNTS,  -1,-1, TIFF_SHORT,      FIELD_STRIPBYTECOUNTS,
113       FALSE,    FALSE,  "StripByteCounts" },
114     { TIFFTAG_MINSAMPLEVALUE,   -2,-1, TIFF_SHORT,      FIELD_MINSAMPLEVALUE,
115       TRUE,     FALSE,  "MinSampleValue" },
116     { TIFFTAG_MAXSAMPLEVALUE,   -2,-1, TIFF_SHORT,      FIELD_MAXSAMPLEVALUE,
117       TRUE,     FALSE,  "MaxSampleValue" },
118     { TIFFTAG_XRESOLUTION,       1, 1, TIFF_RATIONAL,   FIELD_RESOLUTION,
119       FALSE,    FALSE,  "XResolution" },
120     { TIFFTAG_YRESOLUTION,       1, 1, TIFF_RATIONAL,   FIELD_RESOLUTION,
121       FALSE,    FALSE,  "YResolution" },
122     { TIFFTAG_PLANARCONFIG,      1, 1, TIFF_SHORT,      FIELD_PLANARCONFIG,
123       FALSE,    FALSE,  "PlanarConfiguration" },
124     { TIFFTAG_PAGENAME,         -1,-1, TIFF_ASCII,      FIELD_PAGENAME,
125       TRUE,     FALSE,  "PageName" },
126     { TIFFTAG_XPOSITION,         1, 1, TIFF_RATIONAL,   FIELD_POSITION,
127       TRUE,     FALSE,  "XPosition" },
128     { TIFFTAG_YPOSITION,         1, 1, TIFF_RATIONAL,   FIELD_POSITION,
129       TRUE,     FALSE,  "YPosition" },
130     { TIFFTAG_FREEOFFSETS,      -1,-1, TIFF_LONG,       FIELD_IGNORE,
131       FALSE,    FALSE,  "FreeOffsets" },
132     { TIFFTAG_FREEBYTECOUNTS,   -1,-1, TIFF_LONG,       FIELD_IGNORE,
133       FALSE,    FALSE,  "FreeByteCounts" },
134     { TIFFTAG_GRAYRESPONSEUNIT,  1, 1, TIFF_SHORT,      FIELD_IGNORE,
135       TRUE,     FALSE,  "GrayResponseUnit" },
136     { TIFFTAG_GRAYRESPONSECURVE,-1,-1, TIFF_SHORT,      FIELD_IGNORE,
137       TRUE,     FALSE,  "GrayResponseCurve" },
138     { TIFFTAG_RESOLUTIONUNIT,    1, 1, TIFF_SHORT,      FIELD_RESOLUTIONUNIT,
139       FALSE,    FALSE,  "ResolutionUnit" },
140     { TIFFTAG_PAGENUMBER,        2, 2, TIFF_SHORT,      FIELD_PAGENUMBER,
141       TRUE,     FALSE,  "PageNumber" },
142     { TIFFTAG_COLORRESPONSEUNIT, 1, 1, TIFF_SHORT,      FIELD_IGNORE,
143       TRUE,     FALSE,  "ColorResponseUnit" },
144     { TIFFTAG_TRANSFERFUNCTION, -1,-1, TIFF_SHORT,      FIELD_TRANSFERFUNCTION,
145       TRUE,     FALSE,  "TransferFunction" },
146     { TIFFTAG_SOFTWARE,         -1,-1, TIFF_ASCII,      FIELD_CUSTOM,
147       TRUE,     FALSE,  "Software" },
148     { TIFFTAG_DATETIME,         20,20, TIFF_ASCII,      FIELD_DATETIME,
149       TRUE,     FALSE,  "DateTime" },
150     { TIFFTAG_ARTIST,           -1,-1, TIFF_ASCII,      FIELD_ARTIST,
151       TRUE,     FALSE,  "Artist" },
152     { TIFFTAG_HOSTCOMPUTER,     -1,-1, TIFF_ASCII,      FIELD_HOSTCOMPUTER,
153       TRUE,     FALSE,  "HostComputer" },
154     { TIFFTAG_WHITEPOINT,        2, 2, TIFF_RATIONAL,FIELD_WHITEPOINT,
155       TRUE,     FALSE,  "WhitePoint" },
156     { TIFFTAG_PRIMARYCHROMATICITIES,6,6,TIFF_RATIONAL,FIELD_PRIMARYCHROMAS,
157       TRUE,     FALSE,  "PrimaryChromaticities" },
158     { TIFFTAG_COLORMAP,         -1,-1, TIFF_SHORT,      FIELD_COLORMAP,
159       TRUE,     FALSE,  "ColorMap" },
160     { TIFFTAG_HALFTONEHINTS,     2, 2, TIFF_SHORT,      FIELD_HALFTONEHINTS,
161       TRUE,     FALSE,  "HalftoneHints" },
162     { TIFFTAG_TILEWIDTH,         1, 1, TIFF_LONG,       FIELD_TILEDIMENSIONS,
163       FALSE,    FALSE,  "TileWidth" },
164     { TIFFTAG_TILEWIDTH,         1, 1, TIFF_SHORT,      FIELD_TILEDIMENSIONS,
165       FALSE,    FALSE,  "TileWidth" },
166     { TIFFTAG_TILELENGTH,        1, 1, TIFF_LONG,       FIELD_TILEDIMENSIONS,
167       FALSE,    FALSE,  "TileLength" },
168     { TIFFTAG_TILELENGTH,        1, 1, TIFF_SHORT,      FIELD_TILEDIMENSIONS,
169       FALSE,    FALSE,  "TileLength" },
170     { TIFFTAG_TILEOFFSETS,      -1, 1, TIFF_LONG,       FIELD_STRIPOFFSETS,
171       FALSE,    FALSE,  "TileOffsets" },
172     { TIFFTAG_TILEBYTECOUNTS,   -1, 1, TIFF_LONG,       FIELD_STRIPBYTECOUNTS,
173       FALSE,    FALSE,  "TileByteCounts" },
174     { TIFFTAG_TILEBYTECOUNTS,   -1, 1, TIFF_SHORT,      FIELD_STRIPBYTECOUNTS,
175       FALSE,    FALSE,  "TileByteCounts" },
176     { TIFFTAG_SUBIFD,           -1,-1, TIFF_IFD,        FIELD_SUBIFD,
177       TRUE,     TRUE,   "SubIFD" },
178     { TIFFTAG_SUBIFD,           -1,-1, TIFF_LONG,       FIELD_SUBIFD,
179       TRUE,     TRUE,   "SubIFD" },
180     { TIFFTAG_INKSET,            1, 1, TIFF_SHORT,      FIELD_INKSET,
181       FALSE,    FALSE,  "InkSet" },
182     { TIFFTAG_INKNAMES,         -1,-1, TIFF_ASCII,      FIELD_INKNAMES,
183       TRUE,     TRUE,   "InkNames" },
184     { TIFFTAG_NUMBEROFINKS,      1, 1, TIFF_SHORT,      FIELD_NUMBEROFINKS,
185       TRUE,     FALSE,  "NumberOfInks" },
186     { TIFFTAG_DOTRANGE,          2, 2, TIFF_SHORT,      FIELD_DOTRANGE,
187       FALSE,    FALSE,  "DotRange" },
188     { TIFFTAG_DOTRANGE,          2, 2, TIFF_BYTE,       FIELD_DOTRANGE,
189       FALSE,    FALSE,  "DotRange" },
190     { TIFFTAG_TARGETPRINTER,    -1,-1, TIFF_ASCII,      FIELD_TARGETPRINTER,
191       TRUE,     FALSE,  "TargetPrinter" },
192     { TIFFTAG_EXTRASAMPLES,     -1,-1, TIFF_SHORT,      FIELD_EXTRASAMPLES,
193       FALSE,    TRUE,   "ExtraSamples" },
194 /* XXX for bogus Adobe Photoshop v2.5 files */
195     { TIFFTAG_EXTRASAMPLES,     -1,-1, TIFF_BYTE,       FIELD_EXTRASAMPLES,
196       FALSE,    TRUE,   "ExtraSamples" },
197     { TIFFTAG_SAMPLEFORMAT,     -1,-1, TIFF_SHORT,      FIELD_SAMPLEFORMAT,
198       FALSE,    FALSE,  "SampleFormat" },
199     { TIFFTAG_SMINSAMPLEVALUE,  -2,-1, TIFF_ANY,        FIELD_SMINSAMPLEVALUE,
200       TRUE,     FALSE,  "SMinSampleValue" },
201     { TIFFTAG_SMAXSAMPLEVALUE,  -2,-1, TIFF_ANY,        FIELD_SMAXSAMPLEVALUE,
202       TRUE,     FALSE,  "SMaxSampleValue" },
203     { TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL,   FIELD_YCBCRCOEFFICIENTS,
204       FALSE,    FALSE,  "YCbCrCoefficients" },
205     { TIFFTAG_YCBCRSUBSAMPLING,  2, 2, TIFF_SHORT,      FIELD_YCBCRSUBSAMPLING,
206       FALSE,    FALSE,  "YCbCrSubsampling" },
207     { TIFFTAG_YCBCRPOSITIONING,  1, 1, TIFF_SHORT,      FIELD_YCBCRPOSITIONING,
208       FALSE,    FALSE,  "YCbCrPositioning" },
209     { TIFFTAG_REFERENCEBLACKWHITE,6,6,TIFF_RATIONAL,    FIELD_REFBLACKWHITE,
210       TRUE,     FALSE,  "ReferenceBlackWhite" },
211 /* XXX temporarily accept LONG for backwards compatibility */
212     { TIFFTAG_REFERENCEBLACKWHITE,6,6,TIFF_LONG,        FIELD_REFBLACKWHITE,
213       TRUE,     FALSE,  "ReferenceBlackWhite" },
214     { TIFFTAG_XMLPACKET,        -1,-3, TIFF_BYTE,       FIELD_XMLPACKET,
215       FALSE,    TRUE,   "XMLPacket" },
216 /* begin SGI tags */
217     { TIFFTAG_MATTEING,          1, 1, TIFF_SHORT,      FIELD_EXTRASAMPLES,
218       FALSE,    FALSE,  "Matteing" },
219     { TIFFTAG_DATATYPE,         -2,-1, TIFF_SHORT,      FIELD_SAMPLEFORMAT,
220       FALSE,    FALSE,  "DataType" },
221     { TIFFTAG_IMAGEDEPTH,        1, 1, TIFF_LONG,       FIELD_IMAGEDEPTH,
222       FALSE,    FALSE,  "ImageDepth" },
223     { TIFFTAG_IMAGEDEPTH,        1, 1, TIFF_SHORT,      FIELD_IMAGEDEPTH,
224       FALSE,    FALSE,  "ImageDepth" },
225     { TIFFTAG_TILEDEPTH,         1, 1, TIFF_LONG,       FIELD_TILEDEPTH,
226       FALSE,    FALSE,  "TileDepth" },
227     { TIFFTAG_TILEDEPTH,         1, 1, TIFF_SHORT,      FIELD_TILEDEPTH,
228       FALSE,    FALSE,  "TileDepth" },
229 /* end SGI tags */
230 /* begin Pixar tags */
231     { TIFFTAG_PIXAR_IMAGEFULLWIDTH,  1, 1, TIFF_LONG,   FIELD_IMAGEFULLWIDTH,
232       TRUE,     FALSE,  "ImageFullWidth" },
233     { TIFFTAG_PIXAR_IMAGEFULLLENGTH, 1, 1, TIFF_LONG,   FIELD_IMAGEFULLLENGTH,
234       TRUE,     FALSE,  "ImageFullLength" },
235     { TIFFTAG_PIXAR_TEXTUREFORMAT,  -1,-1, TIFF_ASCII,  FIELD_TEXTUREFORMAT,
236       TRUE,     FALSE,  "TextureFormat" },
237     { TIFFTAG_PIXAR_WRAPMODES,      -1,-1, TIFF_ASCII,  FIELD_WRAPMODES,
238       TRUE,     FALSE,  "TextureWrapModes" },
239     { TIFFTAG_PIXAR_FOVCOT,          1, 1, TIFF_FLOAT,  FIELD_FOVCOT,
240       TRUE,     FALSE,  "FieldOfViewCotan" },
241     { TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN,       16,16,  TIFF_FLOAT,
242       FIELD_MATRIX_WORLDTOSCREEN,       TRUE,   FALSE,  "MatrixWorldToScreen" },
243     { TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA,       16,16,  TIFF_FLOAT,
244        FIELD_MATRIX_WORLDTOCAMERA,      TRUE,   FALSE,  "MatrixWorldToCamera" },
245     { TIFFTAG_COPYRIGHT,        -1,-1, TIFF_ASCII,      FIELD_COPYRIGHT,
246       TRUE,     FALSE,  "Copyright" },
247 /* end Pixar tags */
248     { TIFFTAG_RICHTIFFIPTC, -1,-3, TIFF_LONG,   FIELD_RICHTIFFIPTC, 
249       FALSE,    TRUE,   "RichTIFFIPTC" },
250     { TIFFTAG_PHOTOSHOP,    -1,-3, TIFF_BYTE,   FIELD_PHOTOSHOP, 
251       FALSE,    TRUE,   "Photoshop" },
252     { TIFFTAG_ICCPROFILE,       -1,-3, TIFF_UNDEFINED,  FIELD_ICCPROFILE,
253       FALSE,    TRUE,   "ICC Profile" },
254     { TIFFTAG_STONITS,           1, 1, TIFF_DOUBLE,     FIELD_STONITS,
255       FALSE,    FALSE,  "StoNits" },
256 };
257 #define N(a)    (sizeof (a) / sizeof (a[0]))
258
259 void
260 _TIFFSetupFieldInfo(TIFF* tif)
261 {
262         if (tif->tif_fieldinfo) {
263                 int  i;
264
265                 for (i = 0; i < tif->tif_nfields; i++) 
266                 {
267                         TIFFFieldInfo *fld = tif->tif_fieldinfo[i];
268                         if (fld->field_bit == FIELD_CUSTOM && 
269                                 strncmp("Tag ", fld->field_name, 4) == 0) 
270                                 {
271                                 _TIFFfree(fld->field_name);
272                                 _TIFFfree(fld);
273                                 }
274                 }   
275       
276                 _TIFFfree(tif->tif_fieldinfo);
277                 tif->tif_nfields = 0;
278         }
279         _TIFFMergeFieldInfo(tif, tiffFieldInfo, N(tiffFieldInfo));
280 }
281
282 static int
283 tagCompare(const void* a, const void* b)
284 {
285         const TIFFFieldInfo* ta = *(const TIFFFieldInfo**) a;
286         const TIFFFieldInfo* tb = *(const TIFFFieldInfo**) b;
287         /* NB: be careful of return values for 16-bit platforms */
288         if (ta->field_tag != tb->field_tag)
289                 return (ta->field_tag < tb->field_tag ? -1 : 1);
290         else
291                 return ((int)tb->field_type - (int)ta->field_type);
292 }
293
294 static int
295 tagNameCompare(const void* a, const void* b)
296 {
297         const TIFFFieldInfo* ta = *(const TIFFFieldInfo**) a;
298         const TIFFFieldInfo* tb = *(const TIFFFieldInfo**) b;
299
300         return strcmp(ta->field_name, tb->field_name);
301 }
302
303 void
304 _TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], int n)
305 {
306         TIFFFieldInfo** tp;
307         int i;
308
309         tif->tif_foundfield = NULL;
310
311         if (tif->tif_nfields > 0) {
312                 tif->tif_fieldinfo = (TIFFFieldInfo**)
313                     _TIFFrealloc(tif->tif_fieldinfo,
314                         (tif->tif_nfields+n) * sizeof (TIFFFieldInfo*));
315         } else {
316                 tif->tif_fieldinfo = (TIFFFieldInfo**)
317                     _TIFFmalloc(n * sizeof (TIFFFieldInfo*));
318         }
319         assert(tif->tif_fieldinfo != NULL);
320         tp = &tif->tif_fieldinfo[tif->tif_nfields];
321         for (i = 0; i < n; i++)
322                 tp[i] = (TIFFFieldInfo*) &info[i];      /* XXX */
323
324         /* Sort the field info by tag number */
325         qsort(tif->tif_fieldinfo, (size_t) (tif->tif_nfields += n),
326               sizeof (TIFFFieldInfo*), tagCompare);
327 }
328
329 void
330 _TIFFPrintFieldInfo(TIFF* tif, FILE* fd)
331 {
332         int i;
333
334         fprintf(fd, "%s: \n", tif->tif_name);
335         for (i = 0; i < tif->tif_nfields; i++) {
336                 const TIFFFieldInfo* fip = tif->tif_fieldinfo[i];
337                 fprintf(fd, "field[%2d] %5lu, %2d, %2d, %d, %2d, %5s, %5s, %s\n"
338                         , i
339                         , (unsigned long) fip->field_tag
340                         , fip->field_readcount, fip->field_writecount
341                         , fip->field_type
342                         , fip->field_bit
343                         , fip->field_oktochange ? "TRUE" : "FALSE"
344                         , fip->field_passcount ? "TRUE" : "FALSE"
345                         , fip->field_name
346                 );
347         }
348 }
349
350 /*
351  * Return size of TIFFDataType in bytes
352  */
353 int
354 TIFFDataWidth(TIFFDataType type)
355 {
356         switch(type)
357         {
358         case 0:  /* nothing */
359         case 1:  /* TIFF_BYTE */
360         case 2:  /* TIFF_ASCII */
361         case 6:  /* TIFF_SBYTE */
362         case 7:  /* TIFF_UNDEFINED */
363                 return 1;
364         case 3:  /* TIFF_SHORT */
365         case 8:  /* TIFF_SSHORT */
366                 return 2;
367         case 4:  /* TIFF_LONG */
368         case 9:  /* TIFF_SLONG */
369         case 11: /* TIFF_FLOAT */
370         case 13: /* TIFF_IFD */
371                 return 4;
372         case 5:  /* TIFF_RATIONAL */
373         case 10: /* TIFF_SRATIONAL */
374         case 12: /* TIFF_DOUBLE */
375                 return 8;
376         default:
377                 return 0; /* will return 0 for unknown types */
378         }
379 }
380
381 /*
382  * Return nearest TIFFDataType to the sample type of an image.
383  */
384 TIFFDataType
385 _TIFFSampleToTagType(TIFF* tif)
386 {
387         uint32 bps = TIFFhowmany8(tif->tif_dir.td_bitspersample);
388
389         switch (tif->tif_dir.td_sampleformat) {
390         case SAMPLEFORMAT_IEEEFP:
391                 return (bps == 4 ? TIFF_FLOAT : TIFF_DOUBLE);
392         case SAMPLEFORMAT_INT:
393                 return (bps <= 1 ? TIFF_SBYTE :
394                     bps <= 2 ? TIFF_SSHORT : TIFF_SLONG);
395         case SAMPLEFORMAT_UINT:
396                 return (bps <= 1 ? TIFF_BYTE :
397                     bps <= 2 ? TIFF_SHORT : TIFF_LONG);
398         case SAMPLEFORMAT_VOID:
399                 return (TIFF_UNDEFINED);
400         }
401         /*NOTREACHED*/
402         return (TIFF_UNDEFINED);
403 }
404
405 const TIFFFieldInfo*
406 _TIFFFindFieldInfo(TIFF* tif, ttag_t tag, TIFFDataType dt)
407 {
408         int i, n;
409
410         if (tif->tif_foundfield && tif->tif_foundfield->field_tag == tag &&
411             (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type))
412                 return (tif->tif_foundfield);
413         /* NB: use sorted search (e.g. binary search) */
414         if(dt != TIFF_ANY) {
415             TIFFFieldInfo key = {0, 0, 0, 0, 0, 0, 0, 0};
416             key.field_tag = tag;
417             key.field_type = dt;
418             return((const TIFFFieldInfo *) bsearch(&key, 
419                                                    tif->tif_fieldinfo, 
420                                                    tif->tif_nfields,
421                                                    sizeof(TIFFFieldInfo), 
422                                                    tagCompare));
423         } else for (i = 0, n = tif->tif_nfields; i < n; i++) {
424                 const TIFFFieldInfo* fip = tif->tif_fieldinfo[i];
425                 if (fip->field_tag == tag &&
426                     (dt == TIFF_ANY || fip->field_type == dt))
427                         return (tif->tif_foundfield = fip);
428         }
429         return ((const TIFFFieldInfo *)0);
430 }
431
432 const TIFFFieldInfo*
433 _TIFFFindFieldInfoByName(TIFF* tif, const char *field_name, TIFFDataType dt)
434 {
435         int i, n;
436
437         if (tif->tif_foundfield
438             && streq(tif->tif_foundfield->field_name, field_name)
439             && (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type))
440                 return (tif->tif_foundfield);
441         /* NB: use sorted search (e.g. binary search) */
442         if(dt != TIFF_ANY) {
443             TIFFFieldInfo key = {0, 0, 0, 0, 0, 0, 0, 0};
444             key.field_name = (char *)field_name;
445             key.field_type = dt;
446             return((const TIFFFieldInfo *) bsearch(&key, 
447                                                    tif->tif_fieldinfo, 
448                                                    tif->tif_nfields,
449                                                    sizeof(TIFFFieldInfo), 
450                                                    tagNameCompare));
451         } else for (i = 0, n = tif->tif_nfields; i < n; i++) {
452                 const TIFFFieldInfo* fip = tif->tif_fieldinfo[i];
453                 if (streq(fip->field_name, field_name) &&
454                     (dt == TIFF_ANY || fip->field_type == dt))
455                         return (tif->tif_foundfield = fip);
456         }
457         return ((const TIFFFieldInfo *)0);
458 }
459
460 const TIFFFieldInfo*
461 _TIFFFieldWithTag(TIFF* tif, ttag_t tag)
462 {
463         const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
464         if (!fip) {
465                 TIFFError("TIFFFieldWithTag",
466                           "Internal error, unknown tag 0x%x",
467                           (unsigned int) tag);
468                 assert(fip != NULL);
469                 /*NOTREACHED*/
470         }
471         return (fip);
472 }
473
474 const TIFFFieldInfo*
475 _TIFFFieldWithName(TIFF* tif, const char *field_name)
476 {
477         const TIFFFieldInfo* fip =
478                 _TIFFFindFieldInfoByName(tif, field_name, TIFF_ANY);
479         if (!fip) {
480                 TIFFError("TIFFFieldWithName",
481                           "Internal error, unknown tag %s", field_name);
482                 assert(fip != NULL);
483                 /*NOTREACHED*/
484         }
485         return (fip);
486 }
487
488 const TIFFFieldInfo*
489 _TIFFFindOrRegisterFieldInfo( TIFF *tif, ttag_t tag, TIFFDataType dt )
490
491 {
492     const TIFFFieldInfo *fld;
493
494     fld = _TIFFFindFieldInfo( tif, tag, dt );
495     if( fld == NULL )
496     {
497         fld = _TIFFCreateAnonFieldInfo( tif, tag, dt );
498         _TIFFMergeFieldInfo( tif, fld, 1 );
499     }
500
501     return fld;
502 }
503
504 TIFFFieldInfo*
505 _TIFFCreateAnonFieldInfo(TIFF *tif, ttag_t tag, TIFFDataType field_type)
506 {
507     TIFFFieldInfo *fld;
508
509     fld = (TIFFFieldInfo *) _TIFFmalloc(sizeof (TIFFFieldInfo));
510     if (fld == NULL)
511         return NULL;
512     _TIFFmemset( fld, 0, sizeof(TIFFFieldInfo) );
513
514     fld->field_tag = tag;
515     fld->field_readcount = TIFF_VARIABLE;
516     fld->field_writecount = TIFF_VARIABLE;
517     fld->field_type = field_type;
518     fld->field_bit = FIELD_CUSTOM;
519     fld->field_oktochange = TRUE;
520     fld->field_passcount = TRUE;
521     fld->field_name = (char *) _TIFFmalloc(32);
522     if (fld->field_name == NULL) {
523         _TIFFfree(fld);
524         return NULL;
525     }
526
527     /* note that this name is a special sign to TIFFClose() and
528      * _TIFFSetupFieldInfo() to free the field
529      */
530     sprintf(fld->field_name, "Tag %d", (int) tag);
531
532     return fld;    
533 }
534
535 /* vim: set ts=8 sts=8 sw=8 noet: */