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