1
/* $Id: tiffdump.c,v 1.13.2.4 2010-07-07 14:02:56 dron Exp $ */
4
* Copyright (c) 1988-1997 Sam Leffler
5
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
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.
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.
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
27
#include "tif_config.h"
41
#ifdef HAVE_SYS_TYPES_H
42
# include <sys/types.h>
55
/* Safe multiply which returns zero if there is an integer overflow */
56
#ifndef TIFFSafeMultiply
57
# define TIFFSafeMultiply(t,v,m) ((((t)m != (t)0) && (((t)((v*m)/m)) == (t)v)) ? (t)(v*m) : (t)0)
64
int typeshift[14]; /* data type shift counts */
65
long typemask[14]; /* data type masks */
66
uint32 maxitems = 24; /* maximum indirect data items to print */
68
char* bytefmt = "%s%#02x"; /* BYTE */
69
char* sbytefmt = "%s%d"; /* SBYTE */
70
char* shortfmt = "%s%u"; /* SHORT */
71
char* sshortfmt = "%s%d"; /* SSHORT */
72
char* longfmt = "%s%lu"; /* LONG */
73
char* slongfmt = "%s%ld"; /* SLONG */
74
char* rationalfmt = "%s%g"; /* RATIONAL */
75
char* srationalfmt = "%s%g"; /* SRATIONAL */
76
char* floatfmt = "%s%g"; /* FLOAT */
77
char* doublefmt = "%s%g"; /* DOUBLE */
78
char* ifdfmt = "%s%#04x"; /* IFD offset */
80
static void dump(int, off_t);
87
fprintf(stderr, "usage: %s [-h] [-o offset] [-m maxitems] file.tif ...\n", appname);
92
main(int argc, char* argv[])
95
int multiplefiles = (argc > 1);
97
uint32 diroff = (uint32) 0;
98
bigendian = (*(char *)&one == 0);
101
while ((c = getopt(argc, argv, "m:o:h")) != -1) {
103
case 'h': /* print values in hex */
110
diroff = (uint32) strtoul(optarg, NULL, 0);
113
maxitems = strtoul(optarg, NULL, 0);
121
for (; optind < argc; optind++) {
122
fd = open(argv[optind], O_RDONLY|O_BINARY, 0);
128
printf("%s:\n", argv[optind]);
129
curfile = argv[optind];
137
static TIFFHeader hdr;
139
#define ord(e) ((int)e)
142
* Initialize shift & mask tables and byte
143
* swapping state according to the file
147
InitByteOrder(int magic)
150
typemask[ord(TIFF_BYTE)] = 0xff;
151
typemask[ord(TIFF_SBYTE)] = 0xff;
152
typemask[ord(TIFF_UNDEFINED)] = 0xff;
153
typemask[ord(TIFF_SHORT)] = 0xffff;
154
typemask[ord(TIFF_SSHORT)] = 0xffff;
155
typemask[ord(TIFF_LONG)] = 0xffffffff;
156
typemask[ord(TIFF_SLONG)] = 0xffffffff;
157
typemask[ord(TIFF_IFD)] = 0xffffffff;
158
typemask[ord(TIFF_RATIONAL)] = 0xffffffff;
159
typemask[ord(TIFF_SRATIONAL)] = 0xffffffff;
160
typemask[ord(TIFF_FLOAT)] = 0xffffffff;
161
typemask[ord(TIFF_DOUBLE)] = 0xffffffff;
163
typeshift[ord(TIFF_LONG)] = 0;
164
typeshift[ord(TIFF_SLONG)] = 0;
165
typeshift[ord(TIFF_IFD)] = 0;
166
typeshift[ord(TIFF_RATIONAL)] = 0;
167
typeshift[ord(TIFF_SRATIONAL)] = 0;
168
typeshift[ord(TIFF_FLOAT)] = 0;
169
typeshift[ord(TIFF_DOUBLE)] = 0;
170
if (magic == TIFF_BIGENDIAN || magic == MDI_BIGENDIAN) {
171
typeshift[ord(TIFF_BYTE)] = 24;
172
typeshift[ord(TIFF_SBYTE)] = 24;
173
typeshift[ord(TIFF_SHORT)] = 16;
174
typeshift[ord(TIFF_SSHORT)] = 16;
175
swabflag = !bigendian;
177
typeshift[ord(TIFF_BYTE)] = 0;
178
typeshift[ord(TIFF_SBYTE)] = 0;
179
typeshift[ord(TIFF_SHORT)] = 0;
180
typeshift[ord(TIFF_SSHORT)] = 0;
181
swabflag = bigendian;
185
static off_t ReadDirectory(int, unsigned, off_t);
186
static void ReadError(char*);
187
static void Error(const char*, ...);
188
static void Fatal(const char*, ...);
191
dump(int fd, off_t diroff)
195
lseek(fd, (off_t) 0, 0);
196
if (read(fd, (char*) &hdr, sizeof (hdr)) != sizeof (hdr))
197
ReadError("TIFF header");
199
* Setup the byte order handling.
201
if (hdr.tiff_magic != TIFF_BIGENDIAN && hdr.tiff_magic != TIFF_LITTLEENDIAN &&
203
/* MDI is sensitive to the host byte order, unlike TIFF */
204
MDI_BIGENDIAN != hdr.tiff_magic )
206
MDI_LITTLEENDIAN != hdr.tiff_magic )
208
Fatal("Not a TIFF or MDI file, bad magic number %u (%#x)",
209
hdr.tiff_magic, hdr.tiff_magic);
210
InitByteOrder(hdr.tiff_magic);
212
* Swap header if required.
215
TIFFSwabShort(&hdr.tiff_version);
216
TIFFSwabLong(&hdr.tiff_diroff);
219
* Now check version (if needed, it's been byte-swapped).
220
* Note that this isn't actually a version number, it's a
221
* magic number that doesn't change (stupid).
223
if (hdr.tiff_version != TIFF_VERSION)
224
Fatal("Not a TIFF file, bad version number %u (%#x)",
225
hdr.tiff_version, hdr.tiff_version);
226
printf("Magic: %#x <%s-endian> Version: %#x\n",
228
hdr.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
231
diroff = hdr.tiff_diroff;
232
for (i = 0; diroff != 0; i++) {
235
diroff = ReadDirectory(fd, i, diroff);
239
static int datawidth[] = {
245
8, /* TIFF_RATIONAL */
247
1, /* TIFF_UNDEFINED */
250
8, /* TIFF_SRATIONAL */
255
#define NWIDTHS (sizeof (datawidth) / sizeof (datawidth[0]))
256
static int TIFFFetchData(int, TIFFDirEntry*, void*);
257
static void PrintTag(FILE*, uint16);
258
static void PrintType(FILE*, uint16);
259
static void PrintData(FILE*, uint16, uint32, unsigned char*);
262
* Read the next TIFF directory from a file
263
* and convert it to the internal format.
264
* We read directories sequentially.
267
ReadDirectory(int fd, unsigned ix, off_t off)
269
register TIFFDirEntry *dp;
270
register unsigned int n;
271
TIFFDirEntry *dir = 0;
274
uint32 nextdiroff = 0;
276
if (off == 0) /* no more directories */
278
if (lseek(fd, (off_t) off, 0) != off) {
279
Fatal("Seek error accessing TIFF directory");
282
if (read(fd, (char*) &dircount, sizeof (uint16)) != sizeof (uint16)) {
283
ReadError("directory count");
287
TIFFSwabShort(&dircount);
288
dir = (TIFFDirEntry *)_TIFFmalloc(dircount * sizeof (TIFFDirEntry));
290
Fatal("No space for TIFF directory");
293
n = read(fd, (char*) dir, dircount*sizeof (*dp));
294
if (n != dircount*sizeof (*dp)) {
297
"Could only read %u of %u entries in directory at offset %#lx",
298
n, dircount, (unsigned long) off);
301
if (read(fd, (char*) &nextdiroff, sizeof (uint32)) != sizeof (uint32))
304
TIFFSwabLong(&nextdiroff);
305
printf("Directory %u: offset %lu (%#lx) next %lu (%#lx)\n", ix,
306
(unsigned long)off, (unsigned long)off,
307
(unsigned long)nextdiroff, (unsigned long)nextdiroff);
308
for (dp = dir, n = dircount; n > 0; n--, dp++) {
310
TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
311
TIFFSwabArrayOfLong(&dp->tdir_count, 2);
313
PrintTag(stdout, dp->tdir_tag);
315
PrintType(stdout, dp->tdir_type);
317
printf("%lu<", (unsigned long) dp->tdir_count);
318
if (dp->tdir_type >= NWIDTHS) {
322
space = TIFFSafeMultiply(int, dp->tdir_count, datawidth[dp->tdir_type]);
325
Error("Invalid count for tag %u", dp->tdir_tag);
329
switch (dp->tdir_type) {
340
unsigned char data[4];
341
_TIFFmemcpy(data, &dp->tdir_offset, 4);
343
TIFFSwabLong((uint32*) data);
345
dp->tdir_type, dp->tdir_count, data);
350
unsigned char *data = (unsigned char *)_TIFFmalloc(space);
352
if (TIFFFetchData(fd, dp, data)) {
353
if (dp->tdir_count > maxitems) {
354
PrintData(stdout, dp->tdir_type,
358
PrintData(stdout, dp->tdir_type,
359
dp->tdir_count, data);
363
Error("No space for data for tag %u",
370
_TIFFfree((char *)dir);
374
static struct tagname {
378
{ TIFFTAG_SUBFILETYPE, "SubFileType" },
379
{ TIFFTAG_OSUBFILETYPE, "OldSubFileType" },
380
{ TIFFTAG_IMAGEWIDTH, "ImageWidth" },
381
{ TIFFTAG_IMAGELENGTH, "ImageLength" },
382
{ TIFFTAG_BITSPERSAMPLE, "BitsPerSample" },
383
{ TIFFTAG_COMPRESSION, "Compression" },
384
{ TIFFTAG_PHOTOMETRIC, "Photometric" },
385
{ TIFFTAG_THRESHHOLDING, "Threshholding" },
386
{ TIFFTAG_CELLWIDTH, "CellWidth" },
387
{ TIFFTAG_CELLLENGTH, "CellLength" },
388
{ TIFFTAG_FILLORDER, "FillOrder" },
389
{ TIFFTAG_DOCUMENTNAME, "DocumentName" },
390
{ TIFFTAG_IMAGEDESCRIPTION, "ImageDescription" },
391
{ TIFFTAG_MAKE, "Make" },
392
{ TIFFTAG_MODEL, "Model" },
393
{ TIFFTAG_STRIPOFFSETS, "StripOffsets" },
394
{ TIFFTAG_ORIENTATION, "Orientation" },
395
{ TIFFTAG_SAMPLESPERPIXEL, "SamplesPerPixel" },
396
{ TIFFTAG_ROWSPERSTRIP, "RowsPerStrip" },
397
{ TIFFTAG_STRIPBYTECOUNTS, "StripByteCounts" },
398
{ TIFFTAG_MINSAMPLEVALUE, "MinSampleValue" },
399
{ TIFFTAG_MAXSAMPLEVALUE, "MaxSampleValue" },
400
{ TIFFTAG_XRESOLUTION, "XResolution" },
401
{ TIFFTAG_YRESOLUTION, "YResolution" },
402
{ TIFFTAG_PLANARCONFIG, "PlanarConfig" },
403
{ TIFFTAG_PAGENAME, "PageName" },
404
{ TIFFTAG_XPOSITION, "XPosition" },
405
{ TIFFTAG_YPOSITION, "YPosition" },
406
{ TIFFTAG_FREEOFFSETS, "FreeOffsets" },
407
{ TIFFTAG_FREEBYTECOUNTS, "FreeByteCounts" },
408
{ TIFFTAG_GRAYRESPONSEUNIT, "GrayResponseUnit" },
409
{ TIFFTAG_GRAYRESPONSECURVE,"GrayResponseCurve" },
410
{ TIFFTAG_GROUP3OPTIONS, "Group3Options" },
411
{ TIFFTAG_GROUP4OPTIONS, "Group4Options" },
412
{ TIFFTAG_RESOLUTIONUNIT, "ResolutionUnit" },
413
{ TIFFTAG_PAGENUMBER, "PageNumber" },
414
{ TIFFTAG_COLORRESPONSEUNIT,"ColorResponseUnit" },
415
{ TIFFTAG_TRANSFERFUNCTION, "TransferFunction" },
416
{ TIFFTAG_SOFTWARE, "Software" },
417
{ TIFFTAG_DATETIME, "DateTime" },
418
{ TIFFTAG_ARTIST, "Artist" },
419
{ TIFFTAG_HOSTCOMPUTER, "HostComputer" },
420
{ TIFFTAG_PREDICTOR, "Predictor" },
421
{ TIFFTAG_WHITEPOINT, "Whitepoint" },
422
{ TIFFTAG_PRIMARYCHROMATICITIES,"PrimaryChromaticities" },
423
{ TIFFTAG_COLORMAP, "Colormap" },
424
{ TIFFTAG_HALFTONEHINTS, "HalftoneHints" },
425
{ TIFFTAG_TILEWIDTH, "TileWidth" },
426
{ TIFFTAG_TILELENGTH, "TileLength" },
427
{ TIFFTAG_TILEOFFSETS, "TileOffsets" },
428
{ TIFFTAG_TILEBYTECOUNTS, "TileByteCounts" },
429
{ TIFFTAG_BADFAXLINES, "BadFaxLines" },
430
{ TIFFTAG_CLEANFAXDATA, "CleanFaxData" },
431
{ TIFFTAG_CONSECUTIVEBADFAXLINES, "ConsecutiveBadFaxLines" },
432
{ TIFFTAG_SUBIFD, "SubIFD" },
433
{ TIFFTAG_INKSET, "InkSet" },
434
{ TIFFTAG_INKNAMES, "InkNames" },
435
{ TIFFTAG_NUMBEROFINKS, "NumberOfInks" },
436
{ TIFFTAG_DOTRANGE, "DotRange" },
437
{ TIFFTAG_TARGETPRINTER, "TargetPrinter" },
438
{ TIFFTAG_EXTRASAMPLES, "ExtraSamples" },
439
{ TIFFTAG_SAMPLEFORMAT, "SampleFormat" },
440
{ TIFFTAG_SMINSAMPLEVALUE, "SMinSampleValue" },
441
{ TIFFTAG_SMAXSAMPLEVALUE, "SMaxSampleValue" },
442
{ TIFFTAG_JPEGPROC, "JPEGProcessingMode" },
443
{ TIFFTAG_JPEGIFOFFSET, "JPEGInterchangeFormat" },
444
{ TIFFTAG_JPEGIFBYTECOUNT, "JPEGInterchangeFormatLength" },
445
{ TIFFTAG_JPEGRESTARTINTERVAL,"JPEGRestartInterval" },
446
{ TIFFTAG_JPEGLOSSLESSPREDICTORS,"JPEGLosslessPredictors" },
447
{ TIFFTAG_JPEGPOINTTRANSFORM,"JPEGPointTransform" },
448
{ TIFFTAG_JPEGTABLES, "JPEGTables" },
449
{ TIFFTAG_JPEGQTABLES, "JPEGQTables" },
450
{ TIFFTAG_JPEGDCTABLES, "JPEGDCTables" },
451
{ TIFFTAG_JPEGACTABLES, "JPEGACTables" },
452
{ TIFFTAG_YCBCRCOEFFICIENTS,"YCbCrCoefficients" },
453
{ TIFFTAG_YCBCRSUBSAMPLING, "YCbCrSubsampling" },
454
{ TIFFTAG_YCBCRPOSITIONING, "YCbCrPositioning" },
455
{ TIFFTAG_REFERENCEBLACKWHITE, "ReferenceBlackWhite" },
456
{ TIFFTAG_REFPTS, "IgReferencePoints (Island Graphics)" },
457
{ TIFFTAG_REGIONTACKPOINT, "IgRegionTackPoint (Island Graphics)" },
458
{ TIFFTAG_REGIONWARPCORNERS,"IgRegionWarpCorners (Island Graphics)" },
459
{ TIFFTAG_REGIONAFFINE, "IgRegionAffine (Island Graphics)" },
460
{ TIFFTAG_MATTEING, "OBSOLETE Matteing (Silicon Graphics)" },
461
{ TIFFTAG_DATATYPE, "OBSOLETE DataType (Silicon Graphics)" },
462
{ TIFFTAG_IMAGEDEPTH, "ImageDepth (Silicon Graphics)" },
463
{ TIFFTAG_TILEDEPTH, "TileDepth (Silicon Graphics)" },
464
{ 32768, "OLD BOGUS Matteing tag" },
465
{ TIFFTAG_COPYRIGHT, "Copyright" },
466
{ TIFFTAG_ICCPROFILE, "ICC Profile" },
467
{ TIFFTAG_JBIGOPTIONS, "JBIG Options" },
468
{ TIFFTAG_STONITS, "StoNits" },
470
#define NTAGS (sizeof (tagnames) / sizeof (tagnames[0]))
473
PrintTag(FILE* fd, uint16 tag)
475
register struct tagname *tp;
477
for (tp = tagnames; tp < &tagnames[NTAGS]; tp++)
478
if (tp->tag == tag) {
479
fprintf(fd, "%s (%u)", tp->name, tag);
482
fprintf(fd, "%u (%#x)", tag, tag);
486
PrintType(FILE* fd, uint16 type)
488
static char *typenames[] = {
503
#define NTYPES (sizeof (typenames) / sizeof (typenames[0]))
506
fprintf(fd, "%s (%u)", typenames[type], type);
508
fprintf(fd, "%u (%#x)", type, type);
515
PrintASCII(FILE* fd, uint32 cc, const unsigned char* cp)
517
for (; cc > 0; cc--, cp++) {
524
for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++)
528
fprintf(fd, "\\%c", *tp);
530
fprintf(fd, "\\%03o", *cp);
537
PrintData(FILE* fd, uint16 type, uint32 count, unsigned char* data)
544
fprintf(fd, bytefmt, sep, *data++), sep = " ";
548
fprintf(fd, sbytefmt, sep, *(char *)data++), sep = " ";
552
fprintf(fd, bytefmt, sep, *data++), sep = " ";
555
PrintASCII(fd, count, data);
558
uint16 *wp = (uint16*)data;
560
fprintf(fd, shortfmt, sep, *wp++), sep = " ";
564
int16 *wp = (int16*)data;
566
fprintf(fd, sshortfmt, sep, *wp++), sep = " ";
570
uint32 *lp = (uint32*)data;
571
while (count-- > 0) {
572
fprintf(fd, longfmt, sep, (unsigned long) *lp++);
578
int32 *lp = (int32*)data;
580
fprintf(fd, slongfmt, sep, (long) *lp++), sep = " ";
583
case TIFF_RATIONAL: {
584
uint32 *lp = (uint32*)data;
585
while (count-- > 0) {
587
fprintf(fd, "%sNan (%lu/%lu)", sep,
588
(unsigned long) lp[0],
589
(unsigned long) lp[1]);
591
fprintf(fd, rationalfmt, sep,
592
(double)lp[0] / (double)lp[1]);
598
case TIFF_SRATIONAL: {
599
int32 *lp = (int32*)data;
600
while (count-- > 0) {
602
fprintf(fd, "%sNan (%ld/%ld)", sep,
603
(long) lp[0], (long) lp[1]);
605
fprintf(fd, srationalfmt, sep,
606
(double)lp[0] / (double)lp[1]);
613
float *fp = (float *)data;
615
fprintf(fd, floatfmt, sep, *fp++), sep = " ";
619
double *dp = (double *)data;
621
fprintf(fd, doublefmt, sep, *dp++), sep = " ";
625
uint32 *lp = (uint32*)data;
626
while (count-- > 0) {
627
fprintf(fd, ifdfmt, sep, (unsigned long) *lp++);
636
* Fetch a contiguous directory item.
639
TIFFFetchData(int fd, TIFFDirEntry* dir, void* cp)
643
w = (dir->tdir_type < NWIDTHS ? datawidth[dir->tdir_type] : 0);
644
cc = dir->tdir_count * w;
645
if (lseek(fd, (off_t)dir->tdir_offset, 0) != (off_t)-1
646
&& read(fd, cp, cc) == cc) {
648
switch (dir->tdir_type) {
651
TIFFSwabArrayOfShort((uint16*) cp,
658
TIFFSwabArrayOfLong((uint32*) cp,
662
TIFFSwabArrayOfLong((uint32*) cp,
666
TIFFSwabArrayOfDouble((double*) cp,
673
Error("Error while reading data for tag %u", dir->tdir_tag);
678
ReadError(char* what)
680
Fatal("Error while reading %s", what);
686
vError(FILE* fd, const char* fmt, va_list ap)
688
fprintf(fd, "%s: ", curfile);
689
vfprintf(fd, fmt, ap);
694
Error(const char* fmt, ...)
698
vError(stderr, fmt, ap);
703
Fatal(const char* fmt, ...)
707
vError(stderr, fmt, ap);
712
/* vim: set ts=8 sts=8 sw=8 noet: */