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