Better fix
[wxWidgets.git] / src / tiff / tools / tiffdump.c
CommitLineData
8414a40c
VZ
1/* $Id$ */
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: */