xref: /libtiff-4.0.7/tools/tiffdump.c (revision a042a8d4)
1 /* $Id: tiffdump.c,v 1.21 2009-01-22 21:12:45 fwarmerdam 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 #include "tif_config.h"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #ifdef HAVE_UNISTD_H
34 # include <unistd.h>
35 #endif
36 
37 #ifdef HAVE_FCNTL_H
38 # include <fcntl.h>
39 #endif
40 
41 #ifdef HAVE_SYS_TYPES_H
42 # include <sys/types.h>
43 #endif
44 
45 #ifdef HAVE_IO_H
46 # include <io.h>
47 #endif
48 
49 #ifdef NEED_LIBPORT
50 # include "libport.h"
51 #endif
52 
53 #ifndef HAVE_GETOPT
54 extern int getopt(int, char**, char*);
55 #endif
56 
57 #include "tiffio.h"
58 
59 #ifndef O_BINARY
60 # define O_BINARY	0
61 #endif
62 
63 static union
64 {
65 	TIFFHeaderClassic classic;
66 	TIFFHeaderBig big;
67 	TIFFHeaderCommon common;
68 } hdr;
69 char* appname;
70 char* curfile;
71 int swabflag;
72 int bigendian;
73 int bigtiff;
74 uint32 maxitems = 24;   /* maximum indirect data items to print */
75 
76 const char* bytefmt = "%s%#02x";	/* BYTE */
77 const char* sbytefmt = "%s%d";		/* SBYTE */
78 const char* shortfmt = "%s%u";		/* SHORT */
79 const char* sshortfmt = "%s%d";		/* SSHORT */
80 const char* longfmt = "%s%lu";		/* LONG */
81 const char* slongfmt = "%s%ld";		/* SLONG */
82 const char* ifdfmt = "%s%#04lx";	/* IFD offset */
83 #if defined(__WIN32__) && defined(_MSC_VER)
84 const char* long8fmt = "%s%I64u";	/* LONG8 */
85 const char* slong8fmt = "%s%I64d";	/* SLONG8 */
86 const char* ifd8fmt = "%s%#08I64x";	/* IFD offset8*/
87 #else
88 const char* long8fmt = "%s%llu";	/* LONG8 */
89 const char* slong8fmt = "%s%lld";	/* SLONG8 */
90 const char* ifd8fmt = "%s%#08llx";	/* IFD offset8*/
91 #endif
92 const char* rationalfmt = "%s%g";	/* RATIONAL */
93 const char* srationalfmt = "%s%g";	/* SRATIONAL */
94 const char* floatfmt = "%s%g";		/* FLOAT */
95 const char* doublefmt = "%s%g";		/* DOUBLE */
96 
97 static void dump(int, uint64);
98 extern int optind;
99 extern char* optarg;
100 
101 void
102 usage()
103 {
104 	fprintf(stderr, "usage: %s [-h] [-o offset] [-m maxitems] file.tif ...\n", appname);
105 	exit(-1);
106 }
107 
108 int
109 main(int argc, char* argv[])
110 {
111 	int one = 1, fd;
112 	int multiplefiles = (argc > 1);
113 	int c;
114 	uint64 diroff = 0;
115 	bigendian = (*(char *)&one == 0);
116 
117 	appname = argv[0];
118 	while ((c = getopt(argc, argv, "m:o:h")) != -1) {
119 		switch (c) {
120 		case 'h':			/* print values in hex */
121 			shortfmt = "%s%#x";
122 			sshortfmt = "%s%#x";
123 			longfmt = "%s%#lx";
124 			slongfmt = "%s%#lx";
125 			break;
126 		case 'o':
127 			diroff = (uint64) strtoul(optarg, NULL, 0);
128 			break;
129 		case 'm':
130 			maxitems = strtoul(optarg, NULL, 0);
131 			break;
132 		default:
133 			usage();
134 		}
135 	}
136 	if (optind >= argc)
137 		usage();
138 	for (; optind < argc; optind++) {
139 		fd = open(argv[optind], O_RDONLY|O_BINARY, 0);
140 		if (fd < 0) {
141 			perror(argv[0]);
142 			return (-1);
143 		}
144 		if (multiplefiles)
145 			printf("%s:\n", argv[optind]);
146 		curfile = argv[optind];
147 		swabflag = 0;
148 		bigtiff = 0;
149 		dump(fd, diroff);
150 		close(fd);
151 	}
152 	return (0);
153 }
154 
155 #define ord(e) ((int)e)
156 
157 static uint64 ReadDirectory(int, unsigned, uint64);
158 static void ReadError(char*);
159 static void Error(const char*, ...);
160 static void Fatal(const char*, ...);
161 
162 static void
163 dump(int fd, uint64 diroff)
164 {
165 	unsigned i;
166 
167 	lseek(fd, (off_t) 0, 0);
168 	if (read(fd, (char*) &hdr, sizeof (TIFFHeaderCommon)) != sizeof (TIFFHeaderCommon))
169 		ReadError("TIFF header");
170 	if (hdr.common.tiff_magic != TIFF_BIGENDIAN && hdr.common.tiff_magic != TIFF_LITTLEENDIAN &&
171 #if HOST_BIGENDIAN
172 	    // MDI is sensitive to the host byte order, unlike TIFF
173 	    MDI_BIGENDIAN != hdr.common.tiff_magic )
174 #else
175 	    MDI_LITTLEENDIAN != hdr.common.tiff_magic )
176 #endif
177 		Fatal("Not a TIFF or MDI file, bad magic number %u (%#x)",
178 		    hdr.common.tiff_magic, hdr.common.tiff_magic);
179 	if (hdr.common.tiff_magic == TIFF_BIGENDIAN
180 	    || hdr.common.tiff_magic == MDI_BIGENDIAN)
181 		swabflag = !bigendian;
182 	else
183 		swabflag = bigendian;
184 	if (swabflag)
185 		TIFFSwabShort(&hdr.common.tiff_version);
186 	if (hdr.common.tiff_version==42)
187 	{
188 		if (read(fd, (char*) &hdr.classic.tiff_diroff, 4) != 4)
189 			ReadError("TIFF header");
190 		if (swabflag)
191 			TIFFSwabLong(&hdr.classic.tiff_diroff);
192 		printf("Magic: %#x <%s-endian> Version: %#x <%s>\n",
193 		    hdr.classic.tiff_magic,
194 		    hdr.classic.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
195 		    42,"ClassicTIFF");
196 		if (diroff == 0)
197 			diroff = hdr.classic.tiff_diroff;
198 	}
199 	else if (hdr.common.tiff_version==43)
200 	{
201 		if (read(fd, (char*) &hdr.big.tiff_offsetsize, 12) != 12)
202 			ReadError("TIFF header");
203 		if (swabflag)
204 		{
205 			TIFFSwabShort(&hdr.big.tiff_offsetsize);
206 			TIFFSwabShort(&hdr.big.tiff_unused);
207 			TIFFSwabLong8(&hdr.big.tiff_diroff);
208 		}
209 		printf("Magic: %#x <%s-endian> Version: %#x <%s>\n",
210 		    hdr.big.tiff_magic,
211 		    hdr.big.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
212 		    43,"BigTIFF");
213 		printf("OffsetSize: %#x Unused: %#x\n",
214 		    hdr.big.tiff_offsetsize,hdr.big.tiff_unused);
215 		if (diroff == 0)
216 			diroff = hdr.big.tiff_diroff;
217 		bigtiff = 1;
218 	}
219 	else
220 		Fatal("Not a TIFF file, bad version number %u (%#x)",
221 		    hdr.common.tiff_version, hdr.common.tiff_version);
222 	for (i = 0; diroff != 0; i++) {
223 		if (i > 0)
224 			putchar('\n');
225 		diroff = ReadDirectory(fd, i, diroff);
226 	}
227 }
228 
229 static const int datawidth[] = {
230 	0, /* 00 = undefined */
231 	1, /* 01 = TIFF_BYTE */
232 	1, /* 02 = TIFF_ASCII */
233 	2, /* 03 = TIFF_SHORT */
234 	4, /* 04 = TIFF_LONG */
235 	8, /* 05 = TIFF_RATIONAL */
236 	1, /* 06 = TIFF_SBYTE */
237 	1, /* 07 = TIFF_UNDEFINED */
238 	2, /* 08 = TIFF_SSHORT */
239 	4, /* 09 = TIFF_SLONG */
240 	8, /* 10 = TIFF_SRATIONAL */
241 	4, /* 11 = TIFF_FLOAT */
242 	8, /* 12 = TIFF_DOUBLE */
243 	4, /* 13 = TIFF_IFD */
244 	0, /* 14 = undefined */
245 	0, /* 15 = undefined */
246 	8, /* 16 = TIFF_LONG8 */
247 	8, /* 17 = TIFF_SLONG8 */
248 	8, /* 18 = TIFF_IFD8 */
249 };
250 #define NWIDTHS (sizeof (datawidth) / sizeof (datawidth[0]))
251 static void PrintTag(FILE*, uint16);
252 static void PrintType(FILE*, uint16);
253 static void PrintData(FILE*, uint16, uint32, unsigned char*);
254 
255 /*
256  * Read the next TIFF directory from a file
257  * and convert it to the internal format.
258  * We read directories sequentially.
259  */
260 static uint64
261 ReadDirectory(int fd, unsigned int ix, uint64 off)
262 {
263 	uint16 dircount;
264 	uint32 direntrysize;
265 	void* dirmem = NULL;
266 	uint64 nextdiroff;
267 	uint32 n;
268 	uint8* dp;
269 
270 	if (off == 0)			/* no more directories */
271 		goto done;
272 #if defined(__WIN32__) && defined(_MSC_VER)
273 	if (_lseeki64(fd, (__int64)off, SEEK_SET) != (__int64)off) {
274 #else
275 	if (lseek(fd, (off_t)off, SEEK_SET) != (off_t)off) {
276 #endif
277 		Fatal("Seek error accessing TIFF directory");
278 		goto done;
279 	}
280 	if (!bigtiff) {
281 		if (read(fd, (char*) &dircount, sizeof (uint16)) != sizeof (uint16)) {
282 			ReadError("directory count");
283 			goto done;
284 		}
285 		if (swabflag)
286 			TIFFSwabShort(&dircount);
287 		direntrysize = 12;
288 	} else {
289 		uint64 dircount64;
290 		if (read(fd, (char*) &dircount64, sizeof (uint64)) != sizeof (uint64)) {
291 			ReadError("directory count");
292 			goto done;
293 		}
294 		if (swabflag)
295 			TIFFSwabLong8(&dircount64);
296 		if (dircount64>0xFFFF) {
297 			Error("Sanity check on directory count failed");
298 			goto done;
299 		}
300 		dircount = (uint16)dircount64;
301 		direntrysize = 20;
302 	}
303 	dirmem = _TIFFmalloc(dircount * direntrysize);
304 	if (dirmem == NULL) {
305 		Fatal("No space for TIFF directory");
306 		goto done;
307 	}
308 	n = read(fd, (char*) dirmem, dircount*direntrysize);
309 	if (n != dircount*direntrysize) {
310 		n /= direntrysize;
311 		Error(
312 #if defined(__WIN32__) && defined(_MSC_VER)
313 	    "Could only read %lu of %u entries in directory at offset %#I64x",
314 		      (unsigned long)n, dircount, (unsigned __int64) off);
315 #else
316 	    "Could only read %lu of %u entries in directory at offset %#llx",
317 		      (unsigned long)n, dircount, (unsigned long long) off);
318 #endif
319 		dircount = n;
320 		nextdiroff = 0;
321 	} else {
322 		if (!bigtiff) {
323 			uint32 nextdiroff32;
324 			if (read(fd, (char*) &nextdiroff32, sizeof (uint32)) != sizeof (uint32))
325 				nextdiroff32 = 0;
326 			if (swabflag)
327 				TIFFSwabLong(&nextdiroff32);
328 			nextdiroff = nextdiroff32;
329 		} else {
330 			if (read(fd, (char*) &nextdiroff, sizeof (uint64)) != sizeof (uint64))
331 				nextdiroff = 0;
332 			if (swabflag)
333 				TIFFSwabLong8(&nextdiroff);
334 		}
335 	}
336 #if defined(__WIN32__) && defined(_MSC_VER)
337 	printf("Directory %u: offset %I64u (%#I64x) next %I64u (%#I64x)\n", ix,
338 	    (unsigned __int64)off, (unsigned __int64)off,
339 	    (unsigned __int64)nextdiroff, (unsigned __int64)nextdiroff);
340 #else
341 	printf("Directory %u: offset %llu (%#llx) next %llu (%#llx)\n", ix,
342 	    (unsigned long long)off, (unsigned long long)off,
343 	    (unsigned long long)nextdiroff, (unsigned long long)nextdiroff);
344 #endif
345 	for (dp = (uint8*)dirmem, n = dircount; n > 0; n--) {
346 		uint16 tag;
347 		uint16 type;
348 		uint16 typewidth;
349 		uint64 count;
350 		uint64 datasize;
351 		int datafits;
352 		void* datamem;
353 		uint64 dataoffset;
354 		int datatruncated;
355 		tag = *(uint16*)dp;
356 		if (swabflag)
357 			TIFFSwabShort(&tag);
358 		dp += sizeof(uint16);
359 		type = *(uint16*)dp;
360 		dp += sizeof(uint16);
361 		if (swabflag)
362 			TIFFSwabShort(&type);
363 		PrintTag(stdout, tag);
364 		putchar(' ');
365 		PrintType(stdout, type);
366 		putchar(' ');
367 		if (!bigtiff)
368 		{
369 			uint32 count32;
370 			count32 = *(uint32*)dp;
371 			if (swabflag)
372 				TIFFSwabLong(&count32);
373 			dp += sizeof(uint32);
374 			count = count32;
375 		}
376 		else
377 		{
378 			count = *(uint64*)dp;
379 			if (swabflag)
380 				TIFFSwabLong8(&count);
381 			dp += sizeof(uint64);
382 		}
383 #if defined(__WIN32__) && defined(_MSC_VER)
384 		printf("%I64u<", (unsigned __int64)count);
385 #else
386 		printf("%llu<", (unsigned long long)count);
387 #endif
388 		if (type >= NWIDTHS)
389 			typewidth = 0;
390 		else
391 			typewidth = datawidth[type];
392 		datasize = count*typewidth;
393 		datafits = 1;
394 		datamem = dp;
395 		dataoffset = 0;
396 		datatruncated = 0;
397 		if (!bigtiff)
398 		{
399 			if (datasize>4)
400 			{
401 				uint32 dataoffset32;
402 				datafits = 0;
403 				datamem = NULL;
404 				dataoffset32 = *(uint32*)dp;
405 				if (swabflag)
406 					TIFFSwabLong(&dataoffset32);
407 				dataoffset = dataoffset32;
408 			}
409 			dp += sizeof(uint32);
410 		}
411 		else
412 		{
413 			if (datasize>8)
414 			{
415 				datafits = 0;
416 				datamem = NULL;
417 				dataoffset = *(uint64*)dp;
418 				if (swabflag)
419 					TIFFSwabLong8(&dataoffset);
420 			}
421 			dp += sizeof(uint64);
422 		}
423 		if (datasize>0x10000)
424 		{
425 			datatruncated = 1;
426 			count = 0x10000/typewidth;
427 			datasize = count*typewidth;
428 		}
429 		if (count>maxitems)
430 		{
431 			datatruncated = 1;
432 			count = maxitems;
433 			datasize = count*typewidth;
434 		}
435 		if (!datafits)
436 		{
437 			datamem = _TIFFmalloc((uint32)datasize);
438 			if (datamem) {
439 #if defined(__WIN32__) && defined(_MSC_VER)
440 				if (_lseeki64(fd, (__int64)dataoffset, SEEK_SET)
441 				    != (__int64)dataoffset) {
442 #else
443 				if (lseek(fd, (off_t)dataoffset, 0) !=
444 				    (off_t)dataoffset) {
445 #endif
446 					Error(
447 				"Seek error accessing tag %u value", tag);
448 					_TIFFfree(datamem);
449 					datamem = NULL;
450 				}
451 				if (read(fd, datamem, (size_t)datasize) != (TIFF_SSIZE_T)datasize)
452 				{
453 					Error(
454 				"Read error accessing tag %u value", tag);
455 					_TIFFfree(datamem);
456 					datamem = NULL;
457 				}
458 			} else
459 				Error("No space for data for tag %u",tag);
460 		}
461 		if (datamem)
462 		{
463 			if (swabflag)
464 			{
465 				switch (type)
466 				{
467 					case TIFF_BYTE:
468 					case TIFF_ASCII:
469 					case TIFF_SBYTE:
470 					case TIFF_UNDEFINED:
471 						break;
472 					case TIFF_SHORT:
473 					case TIFF_SSHORT:
474 						TIFFSwabArrayOfShort((uint16*)datamem,(tmsize_t)count);
475 						break;
476 					case TIFF_LONG:
477 					case TIFF_SLONG:
478 					case TIFF_FLOAT:
479 					case TIFF_IFD:
480 						TIFFSwabArrayOfLong((uint32*)datamem,(tmsize_t)count);
481 						break;
482 					case TIFF_RATIONAL:
483 					case TIFF_SRATIONAL:
484 						TIFFSwabArrayOfLong((uint32*)datamem,(tmsize_t)count*2);
485 						break;
486 					case TIFF_DOUBLE:
487 					case TIFF_LONG8:
488 					case TIFF_SLONG8:
489 					case TIFF_IFD8:
490 						TIFFSwabArrayOfLong8((uint64*)datamem,(tmsize_t)count);
491 						break;
492 				}
493 			}
494 			PrintData(stdout,type,(uint32)count,datamem);
495 			if (datatruncated)
496 				printf(" ...");
497 			if (!datafits)
498 				_TIFFfree(datamem);
499 		}
500 		printf(">\n");
501 	}
502 done:
503 	if (dirmem)
504 		_TIFFfree((char *)dirmem);
505 	return (nextdiroff);
506 }
507 
508 static const struct tagname {
509 	uint16 tag;
510 	const char* name;
511 } tagnames[] = {
512     { TIFFTAG_SUBFILETYPE,	"SubFileType" },
513     { TIFFTAG_OSUBFILETYPE,	"OldSubFileType" },
514     { TIFFTAG_IMAGEWIDTH,	"ImageWidth" },
515     { TIFFTAG_IMAGELENGTH,	"ImageLength" },
516     { TIFFTAG_BITSPERSAMPLE,	"BitsPerSample" },
517     { TIFFTAG_COMPRESSION,	"Compression" },
518     { TIFFTAG_PHOTOMETRIC,	"Photometric" },
519     { TIFFTAG_THRESHHOLDING,	"Threshholding" },
520     { TIFFTAG_CELLWIDTH,	"CellWidth" },
521     { TIFFTAG_CELLLENGTH,	"CellLength" },
522     { TIFFTAG_FILLORDER,	"FillOrder" },
523     { TIFFTAG_DOCUMENTNAME,	"DocumentName" },
524     { TIFFTAG_IMAGEDESCRIPTION,	"ImageDescription" },
525     { TIFFTAG_MAKE,		"Make" },
526     { TIFFTAG_MODEL,		"Model" },
527     { TIFFTAG_STRIPOFFSETS,	"StripOffsets" },
528     { TIFFTAG_ORIENTATION,	"Orientation" },
529     { TIFFTAG_SAMPLESPERPIXEL,	"SamplesPerPixel" },
530     { TIFFTAG_ROWSPERSTRIP,	"RowsPerStrip" },
531     { TIFFTAG_STRIPBYTECOUNTS,	"StripByteCounts" },
532     { TIFFTAG_MINSAMPLEVALUE,	"MinSampleValue" },
533     { TIFFTAG_MAXSAMPLEVALUE,	"MaxSampleValue" },
534     { TIFFTAG_XRESOLUTION,	"XResolution" },
535     { TIFFTAG_YRESOLUTION,	"YResolution" },
536     { TIFFTAG_PLANARCONFIG,	"PlanarConfig" },
537     { TIFFTAG_PAGENAME,		"PageName" },
538     { TIFFTAG_XPOSITION,	"XPosition" },
539     { TIFFTAG_YPOSITION,	"YPosition" },
540     { TIFFTAG_FREEOFFSETS,	"FreeOffsets" },
541     { TIFFTAG_FREEBYTECOUNTS,	"FreeByteCounts" },
542     { TIFFTAG_GRAYRESPONSEUNIT,	"GrayResponseUnit" },
543     { TIFFTAG_GRAYRESPONSECURVE,"GrayResponseCurve" },
544     { TIFFTAG_GROUP3OPTIONS,	"Group3Options" },
545     { TIFFTAG_GROUP4OPTIONS,	"Group4Options" },
546     { TIFFTAG_RESOLUTIONUNIT,	"ResolutionUnit" },
547     { TIFFTAG_PAGENUMBER,	"PageNumber" },
548     { TIFFTAG_COLORRESPONSEUNIT,"ColorResponseUnit" },
549     { TIFFTAG_TRANSFERFUNCTION,	"TransferFunction" },
550     { TIFFTAG_SOFTWARE,		"Software" },
551     { TIFFTAG_DATETIME,		"DateTime" },
552     { TIFFTAG_ARTIST,		"Artist" },
553     { TIFFTAG_HOSTCOMPUTER,	"HostComputer" },
554     { TIFFTAG_PREDICTOR,	"Predictor" },
555     { TIFFTAG_WHITEPOINT,	"Whitepoint" },
556     { TIFFTAG_PRIMARYCHROMATICITIES,"PrimaryChromaticities" },
557     { TIFFTAG_COLORMAP,		"Colormap" },
558     { TIFFTAG_HALFTONEHINTS,	"HalftoneHints" },
559     { TIFFTAG_TILEWIDTH,	"TileWidth" },
560     { TIFFTAG_TILELENGTH,	"TileLength" },
561     { TIFFTAG_TILEOFFSETS,	"TileOffsets" },
562     { TIFFTAG_TILEBYTECOUNTS,	"TileByteCounts" },
563     { TIFFTAG_BADFAXLINES,	"BadFaxLines" },
564     { TIFFTAG_CLEANFAXDATA,	"CleanFaxData" },
565     { TIFFTAG_CONSECUTIVEBADFAXLINES, "ConsecutiveBadFaxLines" },
566     { TIFFTAG_SUBIFD,		"SubIFD" },
567     { TIFFTAG_INKSET,		"InkSet" },
568     { TIFFTAG_INKNAMES,		"InkNames" },
569     { TIFFTAG_NUMBEROFINKS,	"NumberOfInks" },
570     { TIFFTAG_DOTRANGE,		"DotRange" },
571     { TIFFTAG_TARGETPRINTER,	"TargetPrinter" },
572     { TIFFTAG_EXTRASAMPLES,	"ExtraSamples" },
573     { TIFFTAG_SAMPLEFORMAT,	"SampleFormat" },
574     { TIFFTAG_SMINSAMPLEVALUE,	"SMinSampleValue" },
575     { TIFFTAG_SMAXSAMPLEVALUE,	"SMaxSampleValue" },
576     { TIFFTAG_JPEGPROC,		"JPEGProcessingMode" },
577     { TIFFTAG_JPEGIFOFFSET,	"JPEGInterchangeFormat" },
578     { TIFFTAG_JPEGIFBYTECOUNT,	"JPEGInterchangeFormatLength" },
579     { TIFFTAG_JPEGRESTARTINTERVAL,"JPEGRestartInterval" },
580     { TIFFTAG_JPEGLOSSLESSPREDICTORS,"JPEGLosslessPredictors" },
581     { TIFFTAG_JPEGPOINTTRANSFORM,"JPEGPointTransform" },
582     { TIFFTAG_JPEGTABLES,       "JPEGTables" },
583     { TIFFTAG_JPEGQTABLES,	"JPEGQTables" },
584     { TIFFTAG_JPEGDCTABLES,	"JPEGDCTables" },
585     { TIFFTAG_JPEGACTABLES,	"JPEGACTables" },
586     { TIFFTAG_YCBCRCOEFFICIENTS,"YCbCrCoefficients" },
587     { TIFFTAG_YCBCRSUBSAMPLING,	"YCbCrSubsampling" },
588     { TIFFTAG_YCBCRPOSITIONING,	"YCbCrPositioning" },
589     { TIFFTAG_REFERENCEBLACKWHITE, "ReferenceBlackWhite" },
590     { TIFFTAG_REFPTS,		"IgReferencePoints (Island Graphics)" },
591     { TIFFTAG_REGIONTACKPOINT,	"IgRegionTackPoint (Island Graphics)" },
592     { TIFFTAG_REGIONWARPCORNERS,"IgRegionWarpCorners (Island Graphics)" },
593     { TIFFTAG_REGIONAFFINE,	"IgRegionAffine (Island Graphics)" },
594     { TIFFTAG_MATTEING,		"OBSOLETE Matteing (Silicon Graphics)" },
595     { TIFFTAG_DATATYPE,		"OBSOLETE DataType (Silicon Graphics)" },
596     { TIFFTAG_IMAGEDEPTH,	"ImageDepth (Silicon Graphics)" },
597     { TIFFTAG_TILEDEPTH,	"TileDepth (Silicon Graphics)" },
598     { 32768,			"OLD BOGUS Matteing tag" },
599     { TIFFTAG_COPYRIGHT,	"Copyright" },
600     { TIFFTAG_ICCPROFILE,	"ICC Profile" },
601     { TIFFTAG_JBIGOPTIONS,	"JBIG Options" },
602     { TIFFTAG_STONITS,		"StoNits" },
603 };
604 #define	NTAGS	(sizeof (tagnames) / sizeof (tagnames[0]))
605 
606 static void
607 PrintTag(FILE* fd, uint16 tag)
608 {
609 	const struct tagname *tp;
610 
611 	for (tp = tagnames; tp < &tagnames[NTAGS]; tp++)
612 		if (tp->tag == tag) {
613 			fprintf(fd, "%s (%u)", tp->name, tag);
614 			return;
615 		}
616 	fprintf(fd, "%u (%#x)", tag, tag);
617 }
618 
619 static void
620 PrintType(FILE* fd, uint16 type)
621 {
622 	static const char *typenames[] = {
623 	    "0",
624 	    "BYTE",
625 	    "ASCII",
626 	    "SHORT",
627 	    "LONG",
628 	    "RATIONAL",
629 	    "SBYTE",
630 	    "UNDEFINED",
631 	    "SSHORT",
632 	    "SLONG",
633 	    "SRATIONAL",
634 	    "FLOAT",
635 	    "DOUBLE",
636 	    "IFD",
637 	    "14",
638 	    "15",
639 	    "LONG8",
640 	    "SLONG8",
641 	    "IFD8"
642 	};
643 #define	NTYPES	(sizeof (typenames) / sizeof (typenames[0]))
644 
645 	if (type < NTYPES)
646 		fprintf(fd, "%s (%u)", typenames[type], type);
647 	else
648 		fprintf(fd, "%u (%#x)", type, type);
649 }
650 #undef	NTYPES
651 
652 #include <ctype.h>
653 
654 static void
655 PrintASCII(FILE* fd, uint32 cc, const unsigned char* cp)
656 {
657 	for (; cc > 0; cc--, cp++) {
658 		const char* tp;
659 
660 		if (isprint(*cp)) {
661 			fputc(*cp, fd);
662 			continue;
663 		}
664 		for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++)
665 			if (*tp++ == *cp)
666 				break;
667 		if (*tp)
668 			fprintf(fd, "\\%c", *tp);
669 		else if (*cp)
670 			fprintf(fd, "\\%03o", *cp);
671 		else
672 			fprintf(fd, "\\0");
673 	}
674 }
675 
676 static void
677 PrintData(FILE* fd, uint16 type, uint32 count, unsigned char* data)
678 {
679 	char* sep = "";
680 
681 	switch (type) {
682 	case TIFF_BYTE:
683 		while (count-- > 0)
684 			fprintf(fd, bytefmt, sep, *data++), sep = " ";
685 		break;
686 	case TIFF_SBYTE:
687 		while (count-- > 0)
688 			fprintf(fd, sbytefmt, sep, *(char *)data++), sep = " ";
689 		break;
690 	case TIFF_UNDEFINED:
691 		while (count-- > 0)
692 			fprintf(fd, bytefmt, sep, *data++), sep = " ";
693 		break;
694 	case TIFF_ASCII:
695 		PrintASCII(fd, count, data);
696 		break;
697 	case TIFF_SHORT: {
698 		uint16 *wp = (uint16*)data;
699 		while (count-- > 0)
700 			fprintf(fd, shortfmt, sep, *wp++), sep = " ";
701 		break;
702 	}
703 	case TIFF_SSHORT: {
704 		int16 *wp = (int16*)data;
705 		while (count-- > 0)
706 			fprintf(fd, sshortfmt, sep, *wp++), sep = " ";
707 		break;
708 	}
709 	case TIFF_LONG: {
710 		uint32 *lp = (uint32*)data;
711 		while (count-- > 0) {
712 			fprintf(fd, longfmt, sep, (unsigned long) *lp++);
713 			sep = " ";
714 		}
715 		break;
716 	}
717 	case TIFF_SLONG: {
718 		int32 *lp = (int32*)data;
719 		while (count-- > 0)
720 			fprintf(fd, slongfmt, sep, (long) *lp++), sep = " ";
721 		break;
722 	}
723 	case TIFF_LONG8: {
724 		uint64 *llp = (uint64*)data;
725 		while (count-- > 0) {
726 #if defined(__WIN32__) && defined(_MSC_VER)
727 			fprintf(fd, long8fmt, sep, (unsigned __int64) *llp++);
728 #else
729 			fprintf(fd, long8fmt, sep, (unsigned long long) *llp++);
730 #endif
731 			sep = " ";
732 		}
733 		break;
734 	}
735 	case TIFF_SLONG8: {
736 		int64 *llp = (int64*)data;
737 		while (count-- > 0)
738 #if defined(__WIN32__) && defined(_MSC_VER)
739 			fprintf(fd, slong8fmt, sep, (__int64) *llp++), sep = " ";
740 #else
741 			fprintf(fd, slong8fmt, sep, (long long) *llp++), sep = " ";
742 #endif
743 		break;
744 	}
745 	case TIFF_RATIONAL: {
746 		uint32 *lp = (uint32*)data;
747 		while (count-- > 0) {
748 			if (lp[1] == 0)
749 				fprintf(fd, "%sNan (%lu/%lu)", sep,
750 				    (unsigned long) lp[0],
751 				    (unsigned long) lp[1]);
752 			else
753 				fprintf(fd, rationalfmt, sep,
754 				    (double)lp[0] / (double)lp[1]);
755 			sep = " ";
756 			lp += 2;
757 		}
758 		break;
759 	}
760 	case TIFF_SRATIONAL: {
761 		int32 *lp = (int32*)data;
762 		while (count-- > 0) {
763 			if (lp[1] == 0)
764 				fprintf(fd, "%sNan (%ld/%ld)", sep,
765 				    (long) lp[0], (long) lp[1]);
766 			else
767 				fprintf(fd, srationalfmt, sep,
768 				    (double)lp[0] / (double)lp[1]);
769 			sep = " ";
770 			lp += 2;
771 		}
772 		break;
773 	}
774 	case TIFF_FLOAT: {
775 		float *fp = (float *)data;
776 		while (count-- > 0)
777 			fprintf(fd, floatfmt, sep, *fp++), sep = " ";
778 		break;
779 	}
780 	case TIFF_DOUBLE: {
781 		double *dp = (double *)data;
782 		while (count-- > 0)
783 			fprintf(fd, doublefmt, sep, *dp++), sep = " ";
784 		break;
785 	}
786 	case TIFF_IFD: {
787 		uint32 *lp = (uint32*)data;
788 		while (count-- > 0) {
789 			fprintf(fd, ifdfmt, sep, (unsigned long) *lp++);
790 			sep = " ";
791 		}
792 		break;
793 	}
794 	case TIFF_IFD8: {
795 		uint64 *llp = (uint64*)data;
796 		while (count-- > 0) {
797 #if defined(__WIN32__) && defined(_MSC_VER)
798 			fprintf(fd, ifd8fmt, sep, (unsigned __int64) *llp++);
799 #else
800 			fprintf(fd, ifd8fmt, sep, (unsigned long long) *llp++);
801 #endif
802 			sep = " ";
803 		}
804 		break;
805 	}
806 	}
807 }
808 
809 static void
810 ReadError(char* what)
811 {
812 	Fatal("Error while reading %s", what);
813 }
814 
815 #include <stdarg.h>
816 
817 static void
818 vError(FILE* fd, const char* fmt, va_list ap)
819 {
820 	fprintf(fd, "%s: ", curfile);
821 	vfprintf(fd, fmt, ap);
822 	fprintf(fd, ".\n");
823 }
824 
825 static void
826 Error(const char* fmt, ...)
827 {
828 	va_list ap;
829 	va_start(ap, fmt);
830 	vError(stderr, fmt, ap);
831 	va_end(ap);
832 }
833 
834 static void
835 Fatal(const char* fmt, ...)
836 {
837 	va_list ap;
838 	va_start(ap, fmt);
839 	vError(stderr, fmt, ap);
840 	va_end(ap);
841 	exit(-1);
842 }
843 
844 /* vim: set ts=8 sts=8 sw=8 noet: */
845