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