Blame tools/tiffdump.c

Packit 994f1a
/* $Id: tiffdump.c,v 1.13.2.1 2010-06-08 18:50:44 bfriesen Exp $ */
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Copyright (c) 1988-1997 Sam Leffler
Packit 994f1a
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
Packit 994f1a
 *
Packit 994f1a
 * Permission to use, copy, modify, distribute, and sell this software and 
Packit 994f1a
 * its documentation for any purpose is hereby granted without fee, provided
Packit 994f1a
 * that (i) the above copyright notices and this permission notice appear in
Packit 994f1a
 * all copies of the software and related documentation, and (ii) the names of
Packit 994f1a
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
Packit 994f1a
 * publicity relating to the software without the specific, prior written
Packit 994f1a
 * permission of Sam Leffler and Silicon Graphics.
Packit 994f1a
 * 
Packit 994f1a
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
Packit 994f1a
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
Packit 994f1a
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
Packit 994f1a
 * 
Packit 994f1a
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
Packit 994f1a
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
Packit 994f1a
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Packit 994f1a
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
Packit 994f1a
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
Packit 994f1a
 * OF THIS SOFTWARE.
Packit 994f1a
 */
Packit 994f1a
Packit 994f1a
#include "tif_config.h"
Packit 994f1a
Packit 994f1a
#include <stdio.h>
Packit 994f1a
#include <stdlib.h>
Packit 994f1a
#include <string.h>
Packit 994f1a
Packit 994f1a
#ifdef HAVE_UNISTD_H
Packit 994f1a
# include <unistd.h>
Packit 994f1a
#endif
Packit 994f1a
Packit 994f1a
#ifdef HAVE_FCNTL_H
Packit 994f1a
# include <fcntl.h>
Packit 994f1a
#endif
Packit 994f1a
Packit 994f1a
#ifdef HAVE_SYS_TYPES_H
Packit 994f1a
# include <sys/types.h>
Packit 994f1a
#endif
Packit 994f1a
Packit 994f1a
#ifdef HAVE_IO_H
Packit 994f1a
# include <io.h>
Packit 994f1a
#endif
Packit 994f1a
Packit 994f1a
#include "tiffio.h"
Packit 994f1a
Packit 994f1a
#ifndef O_BINARY
Packit 994f1a
# define O_BINARY	0
Packit 994f1a
#endif
Packit 994f1a
Packit 994f1a
char*	appname;
Packit 994f1a
char*	curfile;
Packit 994f1a
int	swabflag;
Packit 994f1a
int	bigendian;
Packit 994f1a
int	typeshift[14];		/* data type shift counts */
Packit 994f1a
long	typemask[14];		/* data type masks */
Packit 994f1a
uint32	maxitems = 24;		/* maximum indirect data items to print */
Packit 994f1a
Packit 994f1a
char*	bytefmt = "%s%#02x";		/* BYTE */
Packit 994f1a
char*	sbytefmt = "%s%d";		/* SBYTE */
Packit 994f1a
char*	shortfmt = "%s%u";		/* SHORT */
Packit 994f1a
char*	sshortfmt = "%s%d";		/* SSHORT */
Packit 994f1a
char*	longfmt = "%s%lu";		/* LONG */
Packit 994f1a
char*	slongfmt = "%s%ld";		/* SLONG */
Packit 994f1a
char*	rationalfmt = "%s%g";		/* RATIONAL */
Packit 994f1a
char*	srationalfmt = "%s%g";		/* SRATIONAL */
Packit 994f1a
char*	floatfmt = "%s%g";		/* FLOAT */
Packit 994f1a
char*	doublefmt = "%s%g";		/* DOUBLE */
Packit 994f1a
char*	ifdfmt = "%s%#04x";		/* IFD offset */
Packit 994f1a
Packit 994f1a
static	void dump(int, off_t);
Packit 994f1a
extern	int optind;
Packit 994f1a
extern	char* optarg;
Packit 994f1a
Packit 994f1a
void
Packit 994f1a
usage()
Packit 994f1a
{
Packit 994f1a
	fprintf(stderr, "usage: %s [-h] [-o offset] [-m maxitems] file.tif ...\n", appname);
Packit 994f1a
	exit(-1);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
int
Packit 994f1a
main(int argc, char* argv[])
Packit 994f1a
{
Packit 994f1a
	int one = 1, fd;
Packit 994f1a
	int multiplefiles = (argc > 1);
Packit 994f1a
	int c;
Packit 994f1a
	uint32 diroff = (uint32) 0;
Packit 994f1a
	bigendian = (*(char *)&one == 0);
Packit 994f1a
Packit 994f1a
	appname = argv[0];
Packit 994f1a
	while ((c = getopt(argc, argv, "m:o:h")) != -1) {
Packit 994f1a
		switch (c) {
Packit 994f1a
		case 'h':			/* print values in hex */
Packit 994f1a
			shortfmt = "%s%#x";
Packit 994f1a
			sshortfmt = "%s%#x";
Packit 994f1a
			longfmt = "%s%#lx";
Packit 994f1a
			slongfmt = "%s%#lx";
Packit 994f1a
			break;
Packit 994f1a
		case 'o':
Packit 994f1a
			diroff = (uint32) strtoul(optarg, NULL, 0);
Packit 994f1a
			break;
Packit 994f1a
		case 'm':
Packit 994f1a
			maxitems = strtoul(optarg, NULL, 0);
Packit 994f1a
			break;
Packit 994f1a
		default:
Packit 994f1a
			usage();
Packit 994f1a
		}
Packit 994f1a
	}
Packit 994f1a
	if (optind >= argc)
Packit 994f1a
		usage();
Packit 994f1a
	for (; optind < argc; optind++) {
Packit 994f1a
		fd = open(argv[optind], O_RDONLY|O_BINARY, 0);
Packit 994f1a
		if (fd < 0) {
Packit 994f1a
			perror(argv[0]);
Packit 994f1a
			return (-1);
Packit 994f1a
		}
Packit 994f1a
		if (multiplefiles)
Packit 994f1a
			printf("%s:\n", argv[optind]);
Packit 994f1a
		curfile = argv[optind];
Packit 994f1a
		swabflag = 0;
Packit 994f1a
		dump(fd, diroff);
Packit 994f1a
		close(fd);
Packit 994f1a
	}
Packit 994f1a
	return (0);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static	TIFFHeader hdr;
Packit 994f1a
Packit 994f1a
#define	ord(e)	((int)e)
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Initialize shift & mask tables and byte
Packit 994f1a
 * swapping state according to the file
Packit 994f1a
 * byte order.
Packit 994f1a
 */
Packit 994f1a
static void
Packit 994f1a
InitByteOrder(int magic)
Packit 994f1a
{
Packit 994f1a
	typemask[0] = 0;
Packit 994f1a
	typemask[ord(TIFF_BYTE)] = 0xff;
Packit 994f1a
	typemask[ord(TIFF_SBYTE)] = 0xff;
Packit 994f1a
	typemask[ord(TIFF_UNDEFINED)] = 0xff;
Packit 994f1a
	typemask[ord(TIFF_SHORT)] = 0xffff;
Packit 994f1a
	typemask[ord(TIFF_SSHORT)] = 0xffff;
Packit 994f1a
	typemask[ord(TIFF_LONG)] = 0xffffffff;
Packit 994f1a
	typemask[ord(TIFF_SLONG)] = 0xffffffff;
Packit 994f1a
	typemask[ord(TIFF_IFD)] = 0xffffffff;
Packit 994f1a
	typemask[ord(TIFF_RATIONAL)] = 0xffffffff;
Packit 994f1a
	typemask[ord(TIFF_SRATIONAL)] = 0xffffffff;
Packit 994f1a
	typemask[ord(TIFF_FLOAT)] = 0xffffffff;
Packit 994f1a
	typemask[ord(TIFF_DOUBLE)] = 0xffffffff;
Packit 994f1a
	typeshift[0] = 0;
Packit 994f1a
	typeshift[ord(TIFF_LONG)] = 0;
Packit 994f1a
	typeshift[ord(TIFF_SLONG)] = 0;
Packit 994f1a
	typeshift[ord(TIFF_IFD)] = 0;
Packit 994f1a
	typeshift[ord(TIFF_RATIONAL)] = 0;
Packit 994f1a
	typeshift[ord(TIFF_SRATIONAL)] = 0;
Packit 994f1a
	typeshift[ord(TIFF_FLOAT)] = 0;
Packit 994f1a
	typeshift[ord(TIFF_DOUBLE)] = 0;
Packit 994f1a
	if (magic == TIFF_BIGENDIAN || magic == MDI_BIGENDIAN) {
Packit 994f1a
		typeshift[ord(TIFF_BYTE)] = 24;
Packit 994f1a
		typeshift[ord(TIFF_SBYTE)] = 24;
Packit 994f1a
		typeshift[ord(TIFF_SHORT)] = 16;
Packit 994f1a
		typeshift[ord(TIFF_SSHORT)] = 16;
Packit 994f1a
		swabflag = !bigendian;
Packit 994f1a
	} else {
Packit 994f1a
		typeshift[ord(TIFF_BYTE)] = 0;
Packit 994f1a
		typeshift[ord(TIFF_SBYTE)] = 0;
Packit 994f1a
		typeshift[ord(TIFF_SHORT)] = 0;
Packit 994f1a
		typeshift[ord(TIFF_SSHORT)] = 0;
Packit 994f1a
		swabflag = bigendian;
Packit 994f1a
	}
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static	off_t ReadDirectory(int, unsigned, off_t);
Packit 994f1a
static	void ReadError(char*);
Packit 994f1a
static	void Error(const char*, ...);
Packit 994f1a
static	void Fatal(const char*, ...);
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
dump(int fd, off_t diroff)
Packit 994f1a
{
Packit 994f1a
	unsigned i;
Packit 994f1a
Packit 994f1a
	lseek(fd, (off_t) 0, 0);
Packit 994f1a
	if (read(fd, (char*) &hdr, sizeof (hdr)) != sizeof (hdr))
Packit 994f1a
		ReadError("TIFF header");
Packit 994f1a
	/*
Packit 994f1a
	 * Setup the byte order handling.
Packit 994f1a
	 */
Packit 994f1a
	if (hdr.tiff_magic != TIFF_BIGENDIAN && hdr.tiff_magic != TIFF_LITTLEENDIAN &&
Packit 994f1a
#if HOST_BIGENDIAN
Packit 994f1a
	    // MDI is sensitive to the host byte order, unlike TIFF
Packit 994f1a
	    MDI_BIGENDIAN != hdr.tiff_magic )
Packit 994f1a
#else
Packit 994f1a
	    MDI_LITTLEENDIAN != hdr.tiff_magic )
Packit 994f1a
#endif
Packit 994f1a
		Fatal("Not a TIFF or MDI file, bad magic number %u (%#x)",
Packit 994f1a
		    hdr.tiff_magic, hdr.tiff_magic);
Packit 994f1a
	InitByteOrder(hdr.tiff_magic);
Packit 994f1a
	/*
Packit 994f1a
	 * Swap header if required.
Packit 994f1a
	 */
Packit 994f1a
	if (swabflag) {
Packit 994f1a
		TIFFSwabShort(&hdr.tiff_version);
Packit 994f1a
		TIFFSwabLong(&hdr.tiff_diroff);
Packit 994f1a
	}
Packit 994f1a
	/*
Packit 994f1a
	 * Now check version (if needed, it's been byte-swapped).
Packit 994f1a
	 * Note that this isn't actually a version number, it's a
Packit 994f1a
	 * magic number that doesn't change (stupid).
Packit 994f1a
	 */
Packit 994f1a
	if (hdr.tiff_version != TIFF_VERSION)
Packit 994f1a
		Fatal("Not a TIFF file, bad version number %u (%#x)",
Packit 994f1a
		    hdr.tiff_version, hdr.tiff_version); 
Packit 994f1a
	printf("Magic: %#x <%s-endian> Version: %#x\n",
Packit 994f1a
	    hdr.tiff_magic,
Packit 994f1a
	    hdr.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
Packit 994f1a
	    hdr.tiff_version);
Packit 994f1a
	if (diroff == 0)
Packit 994f1a
	    diroff = hdr.tiff_diroff;
Packit 994f1a
	for (i = 0; diroff != 0; i++) {
Packit 994f1a
		if (i > 0)
Packit 994f1a
			putchar('\n');
Packit 994f1a
		diroff = ReadDirectory(fd, i, diroff);
Packit 994f1a
	}
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int datawidth[] = {
Packit 994f1a
    0,	/* nothing */
Packit 994f1a
    1,	/* TIFF_BYTE */
Packit 994f1a
    1,	/* TIFF_ASCII */
Packit 994f1a
    2,	/* TIFF_SHORT */
Packit 994f1a
    4,	/* TIFF_LONG */
Packit 994f1a
    8,	/* TIFF_RATIONAL */
Packit 994f1a
    1,	/* TIFF_SBYTE */
Packit 994f1a
    1,	/* TIFF_UNDEFINED */
Packit 994f1a
    2,	/* TIFF_SSHORT */
Packit 994f1a
    4,	/* TIFF_SLONG */
Packit 994f1a
    8,	/* TIFF_SRATIONAL */
Packit 994f1a
    4,	/* TIFF_FLOAT */
Packit 994f1a
    8,	/* TIFF_DOUBLE */
Packit 994f1a
    4	/* TIFF_IFD */
Packit 994f1a
};
Packit 994f1a
#define	NWIDTHS	(sizeof (datawidth) / sizeof (datawidth[0]))
Packit 994f1a
static	int TIFFFetchData(int, TIFFDirEntry*, void*);
Packit 994f1a
static	void PrintTag(FILE*, uint16);
Packit 994f1a
static	void PrintType(FILE*, uint16);
Packit 994f1a
static	void PrintData(FILE*, uint16, uint32, unsigned char*);
Packit 994f1a
static	void PrintByte(FILE*, const char*, TIFFDirEntry*);
Packit 994f1a
static	void PrintShort(FILE*, const char*, TIFFDirEntry*);
Packit 994f1a
static	void PrintLong(FILE*, const char*, TIFFDirEntry*);
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Read the next TIFF directory from a file
Packit 994f1a
 * and convert it to the internal format.
Packit 994f1a
 * We read directories sequentially.
Packit 994f1a
 */
Packit 994f1a
static off_t
Packit 994f1a
ReadDirectory(int fd, unsigned ix, off_t off)
Packit 994f1a
{
Packit 994f1a
	register TIFFDirEntry *dp;
Packit 994f1a
	register unsigned int n;
Packit 994f1a
	TIFFDirEntry *dir = 0;
Packit 994f1a
	uint16 dircount;
Packit 994f1a
	int space;
Packit 994f1a
	uint32 nextdiroff = 0;
Packit 994f1a
Packit 994f1a
	if (off == 0)			/* no more directories */
Packit 994f1a
		goto done;
Packit 994f1a
	if (lseek(fd, (off_t) off, 0) != off) {
Packit 994f1a
		Fatal("Seek error accessing TIFF directory");
Packit 994f1a
		goto done;
Packit 994f1a
	}
Packit 994f1a
	if (read(fd, (char*) &dircount, sizeof (uint16)) != sizeof (uint16)) {
Packit 994f1a
		ReadError("directory count");
Packit 994f1a
		goto done;
Packit 994f1a
	}
Packit 994f1a
	if (swabflag)
Packit 994f1a
		TIFFSwabShort(&dircount);
Packit 994f1a
	dir = (TIFFDirEntry *)_TIFFmalloc(dircount * sizeof (TIFFDirEntry));
Packit 994f1a
	if (dir == NULL) {
Packit 994f1a
		Fatal("No space for TIFF directory");
Packit 994f1a
		goto done;
Packit 994f1a
	}
Packit 994f1a
	n = read(fd, (char*) dir, dircount*sizeof (*dp));
Packit 994f1a
	if (n != dircount*sizeof (*dp)) {
Packit 994f1a
		n /= sizeof (*dp);
Packit 994f1a
		Error(
Packit 994f1a
	    "Could only read %u of %u entries in directory at offset %#lx",
Packit 994f1a
		    n, dircount, (unsigned long) off);
Packit 994f1a
		dircount = n;
Packit 994f1a
	}
Packit 994f1a
	if (read(fd, (char*) &nextdiroff, sizeof (uint32)) != sizeof (uint32))
Packit 994f1a
		nextdiroff = 0;
Packit 994f1a
	if (swabflag)
Packit 994f1a
		TIFFSwabLong(&nextdiroff);
Packit 994f1a
	printf("Directory %u: offset %lu (%#lx) next %lu (%#lx)\n", ix,
Packit 994f1a
	    (unsigned long)off, (unsigned long)off,
Packit 994f1a
	    (unsigned long)nextdiroff, (unsigned long)nextdiroff);
Packit 994f1a
	for (dp = dir, n = dircount; n > 0; n--, dp++) {
Packit 994f1a
		if (swabflag) {
Packit 994f1a
			TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
Packit 994f1a
			TIFFSwabArrayOfLong(&dp->tdir_count, 2);
Packit 994f1a
		}
Packit 994f1a
		PrintTag(stdout, dp->tdir_tag);
Packit 994f1a
		putchar(' ');
Packit 994f1a
		PrintType(stdout, dp->tdir_type);
Packit 994f1a
		putchar(' ');
Packit 994f1a
		printf("%lu<", (unsigned long) dp->tdir_count);
Packit 994f1a
		if (dp->tdir_type >= NWIDTHS) {
Packit 994f1a
			printf(">\n");
Packit 994f1a
			continue;
Packit 994f1a
		}
Packit 994f1a
		space = dp->tdir_count * datawidth[dp->tdir_type];
Packit 994f1a
		if (space <= 0) {
Packit 994f1a
			printf(">\n");
Packit 994f1a
			Error("Invalid count for tag %u", dp->tdir_tag);
Packit 994f1a
			continue;
Packit 994f1a
                }
Packit 994f1a
		if (space <= 4) {
Packit 994f1a
			switch (dp->tdir_type) {
Packit 994f1a
			case TIFF_FLOAT:
Packit 994f1a
			case TIFF_UNDEFINED:
Packit 994f1a
			case TIFF_ASCII: {
Packit 994f1a
				unsigned char data[4];
Packit 994f1a
				_TIFFmemcpy(data, &dp->tdir_offset, 4);
Packit 994f1a
				if (swabflag)
Packit 994f1a
					TIFFSwabLong((uint32*) data);
Packit 994f1a
				PrintData(stdout,
Packit 994f1a
				    dp->tdir_type, dp->tdir_count, data);
Packit 994f1a
				break;
Packit 994f1a
			}
Packit 994f1a
			case TIFF_BYTE:
Packit 994f1a
				PrintByte(stdout, bytefmt, dp);
Packit 994f1a
				break;
Packit 994f1a
			case TIFF_SBYTE:
Packit 994f1a
				PrintByte(stdout, sbytefmt, dp);
Packit 994f1a
				break;
Packit 994f1a
			case TIFF_SHORT:
Packit 994f1a
				PrintShort(stdout, shortfmt, dp);
Packit 994f1a
				break;
Packit 994f1a
			case TIFF_SSHORT:
Packit 994f1a
				PrintShort(stdout, sshortfmt, dp);
Packit 994f1a
				break;
Packit 994f1a
			case TIFF_LONG:
Packit 994f1a
				PrintLong(stdout, longfmt, dp);
Packit 994f1a
				break;
Packit 994f1a
			case TIFF_SLONG:
Packit 994f1a
				PrintLong(stdout, slongfmt, dp);
Packit 994f1a
				break;
Packit 994f1a
			case TIFF_IFD:
Packit 994f1a
				PrintLong(stdout, ifdfmt, dp);
Packit 994f1a
				break;
Packit 994f1a
			}
Packit 994f1a
		} else {
Packit 994f1a
			unsigned char *data = (unsigned char *)_TIFFmalloc(space);
Packit 994f1a
			if (data) {
Packit 994f1a
				if (TIFFFetchData(fd, dp, data)) {
Packit 994f1a
					if (dp->tdir_count > maxitems) {
Packit 994f1a
						PrintData(stdout, dp->tdir_type,
Packit 994f1a
						    maxitems, data);
Packit 994f1a
						printf(" ...");
Packit 994f1a
					} else
Packit 994f1a
						PrintData(stdout, dp->tdir_type,
Packit 994f1a
						    dp->tdir_count, data);
Packit 994f1a
                                }
Packit 994f1a
				_TIFFfree(data);
Packit 994f1a
			} else
Packit 994f1a
				Error("No space for data for tag %u",
Packit 994f1a
				    dp->tdir_tag);
Packit 994f1a
		}
Packit 994f1a
		printf(">\n");
Packit 994f1a
	}
Packit 994f1a
done:
Packit 994f1a
	if (dir)
Packit 994f1a
		_TIFFfree((char *)dir);
Packit 994f1a
	return (nextdiroff);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static	struct tagname {
Packit 994f1a
	uint16	tag;
Packit 994f1a
	char*	name;
Packit 994f1a
} tagnames[] = {
Packit 994f1a
    { TIFFTAG_SUBFILETYPE,	"SubFileType" },
Packit 994f1a
    { TIFFTAG_OSUBFILETYPE,	"OldSubFileType" },
Packit 994f1a
    { TIFFTAG_IMAGEWIDTH,	"ImageWidth" },
Packit 994f1a
    { TIFFTAG_IMAGELENGTH,	"ImageLength" },
Packit 994f1a
    { TIFFTAG_BITSPERSAMPLE,	"BitsPerSample" },
Packit 994f1a
    { TIFFTAG_COMPRESSION,	"Compression" },
Packit 994f1a
    { TIFFTAG_PHOTOMETRIC,	"Photometric" },
Packit 994f1a
    { TIFFTAG_THRESHHOLDING,	"Threshholding" },
Packit 994f1a
    { TIFFTAG_CELLWIDTH,	"CellWidth" },
Packit 994f1a
    { TIFFTAG_CELLLENGTH,	"CellLength" },
Packit 994f1a
    { TIFFTAG_FILLORDER,	"FillOrder" },
Packit 994f1a
    { TIFFTAG_DOCUMENTNAME,	"DocumentName" },
Packit 994f1a
    { TIFFTAG_IMAGEDESCRIPTION,	"ImageDescription" },
Packit 994f1a
    { TIFFTAG_MAKE,		"Make" },
Packit 994f1a
    { TIFFTAG_MODEL,		"Model" },
Packit 994f1a
    { TIFFTAG_STRIPOFFSETS,	"StripOffsets" },
Packit 994f1a
    { TIFFTAG_ORIENTATION,	"Orientation" },
Packit 994f1a
    { TIFFTAG_SAMPLESPERPIXEL,	"SamplesPerPixel" },
Packit 994f1a
    { TIFFTAG_ROWSPERSTRIP,	"RowsPerStrip" },
Packit 994f1a
    { TIFFTAG_STRIPBYTECOUNTS,	"StripByteCounts" },
Packit 994f1a
    { TIFFTAG_MINSAMPLEVALUE,	"MinSampleValue" },
Packit 994f1a
    { TIFFTAG_MAXSAMPLEVALUE,	"MaxSampleValue" },
Packit 994f1a
    { TIFFTAG_XRESOLUTION,	"XResolution" },
Packit 994f1a
    { TIFFTAG_YRESOLUTION,	"YResolution" },
Packit 994f1a
    { TIFFTAG_PLANARCONFIG,	"PlanarConfig" },
Packit 994f1a
    { TIFFTAG_PAGENAME,		"PageName" },
Packit 994f1a
    { TIFFTAG_XPOSITION,	"XPosition" },
Packit 994f1a
    { TIFFTAG_YPOSITION,	"YPosition" },
Packit 994f1a
    { TIFFTAG_FREEOFFSETS,	"FreeOffsets" },
Packit 994f1a
    { TIFFTAG_FREEBYTECOUNTS,	"FreeByteCounts" },
Packit 994f1a
    { TIFFTAG_GRAYRESPONSEUNIT,	"GrayResponseUnit" },
Packit 994f1a
    { TIFFTAG_GRAYRESPONSECURVE,"GrayResponseCurve" },
Packit 994f1a
    { TIFFTAG_GROUP3OPTIONS,	"Group3Options" },
Packit 994f1a
    { TIFFTAG_GROUP4OPTIONS,	"Group4Options" },
Packit 994f1a
    { TIFFTAG_RESOLUTIONUNIT,	"ResolutionUnit" },
Packit 994f1a
    { TIFFTAG_PAGENUMBER,	"PageNumber" },
Packit 994f1a
    { TIFFTAG_COLORRESPONSEUNIT,"ColorResponseUnit" },
Packit 994f1a
    { TIFFTAG_TRANSFERFUNCTION,	"TransferFunction" },
Packit 994f1a
    { TIFFTAG_SOFTWARE,		"Software" },
Packit 994f1a
    { TIFFTAG_DATETIME,		"DateTime" },
Packit 994f1a
    { TIFFTAG_ARTIST,		"Artist" },
Packit 994f1a
    { TIFFTAG_HOSTCOMPUTER,	"HostComputer" },
Packit 994f1a
    { TIFFTAG_PREDICTOR,	"Predictor" },
Packit 994f1a
    { TIFFTAG_WHITEPOINT,	"Whitepoint" },
Packit 994f1a
    { TIFFTAG_PRIMARYCHROMATICITIES,"PrimaryChromaticities" },
Packit 994f1a
    { TIFFTAG_COLORMAP,		"Colormap" },
Packit 994f1a
    { TIFFTAG_HALFTONEHINTS,	"HalftoneHints" },
Packit 994f1a
    { TIFFTAG_TILEWIDTH,	"TileWidth" },
Packit 994f1a
    { TIFFTAG_TILELENGTH,	"TileLength" },
Packit 994f1a
    { TIFFTAG_TILEOFFSETS,	"TileOffsets" },
Packit 994f1a
    { TIFFTAG_TILEBYTECOUNTS,	"TileByteCounts" },
Packit 994f1a
    { TIFFTAG_BADFAXLINES,	"BadFaxLines" },
Packit 994f1a
    { TIFFTAG_CLEANFAXDATA,	"CleanFaxData" },
Packit 994f1a
    { TIFFTAG_CONSECUTIVEBADFAXLINES, "ConsecutiveBadFaxLines" },
Packit 994f1a
    { TIFFTAG_SUBIFD,		"SubIFD" },
Packit 994f1a
    { TIFFTAG_INKSET,		"InkSet" },
Packit 994f1a
    { TIFFTAG_INKNAMES,		"InkNames" },
Packit 994f1a
    { TIFFTAG_NUMBEROFINKS,	"NumberOfInks" },
Packit 994f1a
    { TIFFTAG_DOTRANGE,		"DotRange" },
Packit 994f1a
    { TIFFTAG_TARGETPRINTER,	"TargetPrinter" },
Packit 994f1a
    { TIFFTAG_EXTRASAMPLES,	"ExtraSamples" },
Packit 994f1a
    { TIFFTAG_SAMPLEFORMAT,	"SampleFormat" },
Packit 994f1a
    { TIFFTAG_SMINSAMPLEVALUE,	"SMinSampleValue" },
Packit 994f1a
    { TIFFTAG_SMAXSAMPLEVALUE,	"SMaxSampleValue" },
Packit 994f1a
    { TIFFTAG_JPEGPROC,		"JPEGProcessingMode" },
Packit 994f1a
    { TIFFTAG_JPEGIFOFFSET,	"JPEGInterchangeFormat" },
Packit 994f1a
    { TIFFTAG_JPEGIFBYTECOUNT,	"JPEGInterchangeFormatLength" },
Packit 994f1a
    { TIFFTAG_JPEGRESTARTINTERVAL,"JPEGRestartInterval" },
Packit 994f1a
    { TIFFTAG_JPEGLOSSLESSPREDICTORS,"JPEGLosslessPredictors" },
Packit 994f1a
    { TIFFTAG_JPEGPOINTTRANSFORM,"JPEGPointTransform" },
Packit 994f1a
    { TIFFTAG_JPEGTABLES,       "JPEGTables" },
Packit 994f1a
    { TIFFTAG_JPEGQTABLES,	"JPEGQTables" },
Packit 994f1a
    { TIFFTAG_JPEGDCTABLES,	"JPEGDCTables" },
Packit 994f1a
    { TIFFTAG_JPEGACTABLES,	"JPEGACTables" },
Packit 994f1a
    { TIFFTAG_YCBCRCOEFFICIENTS,"YCbCrCoefficients" },
Packit 994f1a
    { TIFFTAG_YCBCRSUBSAMPLING,	"YCbCrSubsampling" },
Packit 994f1a
    { TIFFTAG_YCBCRPOSITIONING,	"YCbCrPositioning" },
Packit 994f1a
    { TIFFTAG_REFERENCEBLACKWHITE, "ReferenceBlackWhite" },
Packit 994f1a
    { TIFFTAG_REFPTS,		"IgReferencePoints (Island Graphics)" },
Packit 994f1a
    { TIFFTAG_REGIONTACKPOINT,	"IgRegionTackPoint (Island Graphics)" },
Packit 994f1a
    { TIFFTAG_REGIONWARPCORNERS,"IgRegionWarpCorners (Island Graphics)" },
Packit 994f1a
    { TIFFTAG_REGIONAFFINE,	"IgRegionAffine (Island Graphics)" },
Packit 994f1a
    { TIFFTAG_MATTEING,		"OBSOLETE Matteing (Silicon Graphics)" },
Packit 994f1a
    { TIFFTAG_DATATYPE,		"OBSOLETE DataType (Silicon Graphics)" },
Packit 994f1a
    { TIFFTAG_IMAGEDEPTH,	"ImageDepth (Silicon Graphics)" },
Packit 994f1a
    { TIFFTAG_TILEDEPTH,	"TileDepth (Silicon Graphics)" },
Packit 994f1a
    { 32768,			"OLD BOGUS Matteing tag" },
Packit 994f1a
    { TIFFTAG_COPYRIGHT,	"Copyright" },
Packit 994f1a
    { TIFFTAG_ICCPROFILE,	"ICC Profile" },
Packit 994f1a
    { TIFFTAG_JBIGOPTIONS,	"JBIG Options" },
Packit 994f1a
    { TIFFTAG_STONITS,		"StoNits" },
Packit 994f1a
};
Packit 994f1a
#define	NTAGS	(sizeof (tagnames) / sizeof (tagnames[0]))
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
PrintTag(FILE* fd, uint16 tag)
Packit 994f1a
{
Packit 994f1a
	register struct tagname *tp;
Packit 994f1a
Packit 994f1a
	for (tp = tagnames; tp < &tagnames[NTAGS]; tp++)
Packit 994f1a
		if (tp->tag == tag) {
Packit 994f1a
			fprintf(fd, "%s (%u)", tp->name, tag);
Packit 994f1a
			return;
Packit 994f1a
		}
Packit 994f1a
	fprintf(fd, "%u (%#x)", tag, tag);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
PrintType(FILE* fd, uint16 type)
Packit 994f1a
{
Packit 994f1a
	static char *typenames[] = {
Packit 994f1a
	    "0",
Packit 994f1a
	    "BYTE",
Packit 994f1a
	    "ASCII",
Packit 994f1a
	    "SHORT",
Packit 994f1a
	    "LONG",
Packit 994f1a
	    "RATIONAL",
Packit 994f1a
	    "SBYTE",
Packit 994f1a
	    "UNDEFINED",
Packit 994f1a
	    "SSHORT",
Packit 994f1a
	    "SLONG",
Packit 994f1a
	    "SRATIONAL",
Packit 994f1a
	    "FLOAT",
Packit 994f1a
	    "DOUBLE"
Packit 994f1a
	};
Packit 994f1a
#define	NTYPES	(sizeof (typenames) / sizeof (typenames[0]))
Packit 994f1a
Packit 994f1a
	if (type < NTYPES)
Packit 994f1a
		fprintf(fd, "%s (%u)", typenames[type], type);
Packit 994f1a
	else
Packit 994f1a
		fprintf(fd, "%u (%#x)", type, type);
Packit 994f1a
}
Packit 994f1a
#undef	NTYPES
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
PrintByte(FILE* fd, const char* fmt, TIFFDirEntry* dp)
Packit 994f1a
{
Packit 994f1a
	char* sep = "";
Packit 994f1a
Packit 994f1a
	if (hdr.tiff_magic == TIFF_BIGENDIAN) {
Packit 994f1a
		switch ((int)dp->tdir_count) {
Packit 994f1a
		case 4: fprintf(fd, fmt, sep, dp->tdir_offset&0xff);
Packit 994f1a
			sep = " ";
Packit 994f1a
		case 3: fprintf(fd, fmt, sep, (dp->tdir_offset>>8)&0xff);
Packit 994f1a
			sep = " ";
Packit 994f1a
		case 2: fprintf(fd, fmt, sep, (dp->tdir_offset>>16)&0xff);
Packit 994f1a
			sep = " ";
Packit 994f1a
		case 1: fprintf(fd, fmt, sep, dp->tdir_offset>>24);
Packit 994f1a
		}
Packit 994f1a
	} else {
Packit 994f1a
		switch ((int)dp->tdir_count) {
Packit 994f1a
		case 4: fprintf(fd, fmt, sep, dp->tdir_offset>>24);
Packit 994f1a
			sep = " ";
Packit 994f1a
		case 3: fprintf(fd, fmt, sep, (dp->tdir_offset>>16)&0xff);
Packit 994f1a
			sep = " ";
Packit 994f1a
		case 2: fprintf(fd, fmt, sep, (dp->tdir_offset>>8)&0xff);
Packit 994f1a
			sep = " ";
Packit 994f1a
		case 1: fprintf(fd, fmt, sep, dp->tdir_offset&0xff);
Packit 994f1a
		}
Packit 994f1a
	}
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
PrintShort(FILE* fd, const char* fmt, TIFFDirEntry* dp)
Packit 994f1a
{
Packit 994f1a
	char *sep = "";
Packit 994f1a
Packit 994f1a
	if (hdr.tiff_magic == TIFF_BIGENDIAN) {
Packit 994f1a
		switch (dp->tdir_count) {
Packit 994f1a
		case 2: fprintf(fd, fmt, sep, dp->tdir_offset&0xffff);
Packit 994f1a
			sep = " ";
Packit 994f1a
		case 1: fprintf(fd, fmt, sep, dp->tdir_offset>>16);
Packit 994f1a
		}
Packit 994f1a
	} else {
Packit 994f1a
		switch (dp->tdir_count) {
Packit 994f1a
		case 2: fprintf(fd, fmt, sep, dp->tdir_offset>>16);
Packit 994f1a
			sep = " ";
Packit 994f1a
		case 1: fprintf(fd, fmt, sep, dp->tdir_offset&0xffff);
Packit 994f1a
		}
Packit 994f1a
	}
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
PrintLong(FILE* fd, const char* fmt, TIFFDirEntry* dp)
Packit 994f1a
{
Packit 994f1a
	fprintf(fd, fmt, "", (long) dp->tdir_offset);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
#include <ctype.h>
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
PrintASCII(FILE* fd, uint32 cc, const unsigned char* cp)
Packit 994f1a
{
Packit 994f1a
	for (; cc > 0; cc--, cp++) {
Packit 994f1a
		const char* tp;
Packit 994f1a
Packit 994f1a
		if (isprint(*cp)) {
Packit 994f1a
			fputc(*cp, fd);
Packit 994f1a
			continue;
Packit 994f1a
		}
Packit 994f1a
		for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++)
Packit 994f1a
			if (*tp++ == *cp)
Packit 994f1a
				break;
Packit 994f1a
		if (*tp)
Packit 994f1a
			fprintf(fd, "\\%c", *tp);
Packit 994f1a
		else if (*cp)
Packit 994f1a
			fprintf(fd, "\\%03o", *cp);
Packit 994f1a
		else
Packit 994f1a
			fprintf(fd, "\\0");
Packit 994f1a
	}
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
PrintData(FILE* fd, uint16 type, uint32 count, unsigned char* data)
Packit 994f1a
{
Packit 994f1a
	char* sep = "";
Packit 994f1a
Packit 994f1a
	switch (type) {
Packit 994f1a
	case TIFF_BYTE:
Packit 994f1a
		while (count-- > 0)
Packit 994f1a
			fprintf(fd, bytefmt, sep, *data++), sep = " ";
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_SBYTE:
Packit 994f1a
		while (count-- > 0)
Packit 994f1a
			fprintf(fd, sbytefmt, sep, *(char *)data++), sep = " ";
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_UNDEFINED:
Packit 994f1a
		while (count-- > 0)
Packit 994f1a
			fprintf(fd, bytefmt, sep, *data++), sep = " ";
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_ASCII:
Packit 994f1a
		PrintASCII(fd, count, data);
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_SHORT: {
Packit 994f1a
		uint16 *wp = (uint16*)data;
Packit 994f1a
		while (count-- > 0)
Packit 994f1a
			fprintf(fd, shortfmt, sep, *wp++), sep = " ";
Packit 994f1a
		break;
Packit 994f1a
	}
Packit 994f1a
	case TIFF_SSHORT: {
Packit 994f1a
		int16 *wp = (int16*)data;
Packit 994f1a
		while (count-- > 0)
Packit 994f1a
			fprintf(fd, sshortfmt, sep, *wp++), sep = " ";
Packit 994f1a
		break;
Packit 994f1a
	}
Packit 994f1a
	case TIFF_LONG: {
Packit 994f1a
		uint32 *lp = (uint32*)data;
Packit 994f1a
		while (count-- > 0) {
Packit 994f1a
			fprintf(fd, longfmt, sep, (unsigned long) *lp++);
Packit 994f1a
			sep = " ";
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	}
Packit 994f1a
	case TIFF_SLONG: {
Packit 994f1a
		int32 *lp = (int32*)data;
Packit 994f1a
		while (count-- > 0)
Packit 994f1a
			fprintf(fd, slongfmt, sep, (long) *lp++), sep = " ";
Packit 994f1a
		break;
Packit 994f1a
	}
Packit 994f1a
	case TIFF_RATIONAL: {
Packit 994f1a
		uint32 *lp = (uint32*)data;
Packit 994f1a
		while (count-- > 0) {
Packit 994f1a
			if (lp[1] == 0)
Packit 994f1a
				fprintf(fd, "%sNan (%lu/%lu)", sep,
Packit 994f1a
				    (unsigned long) lp[0],
Packit 994f1a
				    (unsigned long) lp[1]);
Packit 994f1a
			else
Packit 994f1a
				fprintf(fd, rationalfmt, sep,
Packit 994f1a
				    (double)lp[0] / (double)lp[1]);
Packit 994f1a
			sep = " ";
Packit 994f1a
			lp += 2;
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	}
Packit 994f1a
	case TIFF_SRATIONAL: {
Packit 994f1a
		int32 *lp = (int32*)data;
Packit 994f1a
		while (count-- > 0) {
Packit 994f1a
			if (lp[1] == 0)
Packit 994f1a
				fprintf(fd, "%sNan (%ld/%ld)", sep,
Packit 994f1a
				    (long) lp[0], (long) lp[1]);
Packit 994f1a
			else
Packit 994f1a
				fprintf(fd, srationalfmt, sep,
Packit 994f1a
				    (double)lp[0] / (double)lp[1]);
Packit 994f1a
			sep = " ";
Packit 994f1a
			lp += 2;
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	}
Packit 994f1a
	case TIFF_FLOAT: {
Packit 994f1a
		float *fp = (float *)data;
Packit 994f1a
		while (count-- > 0)
Packit 994f1a
			fprintf(fd, floatfmt, sep, *fp++), sep = " ";
Packit 994f1a
		break;
Packit 994f1a
	}
Packit 994f1a
	case TIFF_DOUBLE: {
Packit 994f1a
		double *dp = (double *)data;
Packit 994f1a
		while (count-- > 0)
Packit 994f1a
			fprintf(fd, doublefmt, sep, *dp++), sep = " ";
Packit 994f1a
		break;
Packit 994f1a
	}
Packit 994f1a
	case TIFF_IFD: {
Packit 994f1a
		uint32 *lp = (uint32*)data;
Packit 994f1a
		while (count-- > 0) {
Packit 994f1a
			fprintf(fd, ifdfmt, sep, (unsigned long) *lp++);
Packit 994f1a
			sep = " ";
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	}
Packit 994f1a
	}
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Fetch a contiguous directory item.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFFetchData(int fd, TIFFDirEntry* dir, void* cp)
Packit 994f1a
{
Packit 994f1a
	int cc, w;
Packit 994f1a
Packit 994f1a
	w = (dir->tdir_type < NWIDTHS ? datawidth[dir->tdir_type] : 0);
Packit 994f1a
	cc = dir->tdir_count * w;
Packit 994f1a
	if (lseek(fd, (off_t)dir->tdir_offset, 0) != (off_t)-1
Packit 994f1a
	    && read(fd, cp, cc) != -1) {
Packit 994f1a
		if (swabflag) {
Packit 994f1a
			switch (dir->tdir_type) {
Packit 994f1a
			case TIFF_SHORT:
Packit 994f1a
			case TIFF_SSHORT:
Packit 994f1a
				TIFFSwabArrayOfShort((uint16*) cp,
Packit 994f1a
				    dir->tdir_count);
Packit 994f1a
				break;
Packit 994f1a
			case TIFF_LONG:
Packit 994f1a
			case TIFF_SLONG:
Packit 994f1a
			case TIFF_FLOAT:
Packit 994f1a
			case TIFF_IFD:
Packit 994f1a
				TIFFSwabArrayOfLong((uint32*) cp,
Packit 994f1a
				    dir->tdir_count);
Packit 994f1a
				break;
Packit 994f1a
			case TIFF_RATIONAL:
Packit 994f1a
				TIFFSwabArrayOfLong((uint32*) cp,
Packit 994f1a
				    2*dir->tdir_count);
Packit 994f1a
				break;
Packit 994f1a
			case TIFF_DOUBLE:
Packit 994f1a
				TIFFSwabArrayOfDouble((double*) cp,
Packit 994f1a
				    dir->tdir_count);
Packit 994f1a
				break;
Packit 994f1a
			}
Packit 994f1a
		}
Packit 994f1a
		return (cc);
Packit 994f1a
	}
Packit 994f1a
	Error("Error while reading data for tag %u", dir->tdir_tag);
Packit 994f1a
	return (0);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
ReadError(char* what)
Packit 994f1a
{
Packit 994f1a
	Fatal("Error while reading %s", what);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
#include <stdarg.h>
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
vError(FILE* fd, const char* fmt, va_list ap)
Packit 994f1a
{
Packit 994f1a
	fprintf(fd, "%s: ", curfile);
Packit 994f1a
	vfprintf(fd, fmt, ap);
Packit 994f1a
	fprintf(fd, ".\n");
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
Error(const char* fmt, ...)
Packit 994f1a
{
Packit 994f1a
	va_list ap;
Packit 994f1a
	va_start(ap, fmt);
Packit 994f1a
	vError(stderr, fmt, ap);
Packit 994f1a
	va_end(ap);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static void
Packit 994f1a
Fatal(const char* fmt, ...)
Packit 994f1a
{
Packit 994f1a
	va_list ap;
Packit 994f1a
	va_start(ap, fmt);
Packit 994f1a
	vError(stderr, fmt, ap);
Packit 994f1a
	va_end(ap);
Packit 994f1a
	exit(-1);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/* vim: set ts=8 sts=8 sw=8 noet: */
Packit 994f1a
/*
Packit 994f1a
 * Local Variables:
Packit 994f1a
 * mode: c
Packit 994f1a
 * c-basic-offset: 8
Packit 994f1a
 * fill-column: 78
Packit 994f1a
 * End:
Packit 994f1a
 */