/* * Copyright (c) 1988-1997 Sam Leffler * Copyright (c) 1991-1997 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler and Silicon Graphics may not be used in any advertising or * publicity relating to the software without the specific, prior written * permission of Sam Leffler and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include "libport.h" #include "tif_config.h" #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include "tiffiop.h" #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_IO_H #include #endif #include "tiffio.h" #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 #endif #ifndef O_BINARY #define O_BINARY 0 #endif static union { TIFFHeaderClassic classic; TIFFHeaderBig big; TIFFHeaderCommon common; } hdr; static char *appname; static char *curfile; static int swabflag; static int bigendian; static int bigtiff; static uint32_t maxitems = 24; /* maximum indirect data items to print */ static const char bytefmt[] = "%s%#02" PRIx8; /* BYTE */ static const char sbytefmt[] = "%s%" PRId8; /* SBYTE */ static const char shortfmtd[] = "%s%" PRIu16; /* SHORT */ static const char shortfmth[] = "%s%#" PRIx16; static const char sshortfmtd[] = "%s%" PRId16; /* SSHORT */ static const char sshortfmth[] = "%s%#" PRIx16; static const char longfmtd[] = "%s%" PRIu32; /* LONG */ static const char longfmth[] = "%s%#" PRIx32; static const char slongfmtd[] = "%s%" PRId32; /* SLONG */ static const char slongfmth[] = "%s%#" PRIx32; static const char ifdfmt[] = "%s%#04" PRIx32; /* IFD offset */ static const char long8fmt[] = "%s%" PRIu64; /* LONG8 */ static const char slong8fmt[] = "%s%" PRId64; /* SLONG8 */ static const char ifd8fmt[] = "%s%#08" PRIx64; /* IFD offset8 */ static const char rationalfmt[] = "%s%g"; /* RATIONAL */ static const char srationalfmt[] = "%s%g"; /* SRATIONAL */ static const char floatfmt[] = "%s%g"; /* FLOAT */ static const char doublefmt[] = "%s%g"; /* DOUBLE */ unsigned int hex_mode; static void dump(int, uint64_t); #if !HAVE_DECL_OPTARG extern int optind; extern char *optarg; #endif void usage() { fprintf(stderr, "\nDisplay directory information from TIFF files\n\n"); fprintf(stderr, "usage: %s [-h] [-o offset] [-m maxitems] file.tif ...\n", appname); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { int one = 1, fd; int multiplefiles = (argc > 1); int c; uint64_t diroff = 0; hex_mode = 0; bigendian = (*(char *)&one == 0); appname = argv[0]; while ((c = getopt(argc, argv, "m:o:h")) != -1) { switch (c) { case 'h': /* print values in hex */ hex_mode = 1; break; case 'o': diroff = (uint64_t)strtoul(optarg, NULL, 0); break; case 'm': maxitems = strtoul(optarg, NULL, 0); break; default: usage(); } } if (optind >= argc) usage(); for (; optind < argc; optind++) { fd = open(argv[optind], O_RDONLY | O_BINARY, 0); if (fd < 0) { perror(argv[0]); return (EXIT_FAILURE); } if (multiplefiles) printf("%s:\n", argv[optind]); curfile = argv[optind]; swabflag = 0; bigtiff = 0; dump(fd, diroff); close(fd); } return (EXIT_SUCCESS); } #define ord(e) ((int)e) static uint64_t ReadDirectory(int, unsigned, uint64_t); static void ReadError(char *); static void Error(const char *, ...); static void Fatal(const char *, ...); static void dump(int fd, uint64_t diroff) { unsigned i, j; uint64_t *visited_diroff = NULL; unsigned int count_visited_dir = 0; _TIFF_lseek_f(fd, (_TIFF_off_t)0, 0); if (read(fd, (char *)&hdr, sizeof(TIFFHeaderCommon)) != sizeof(TIFFHeaderCommon)) ReadError("TIFF header"); if (hdr.common.tiff_magic != TIFF_BIGENDIAN && hdr.common.tiff_magic != TIFF_LITTLEENDIAN && #if HOST_BIGENDIAN /* MDI is sensitive to the host byte order, unlike TIFF */ MDI_BIGENDIAN != hdr.common.tiff_magic #else MDI_LITTLEENDIAN != hdr.common.tiff_magic #endif ) { Fatal("Not a TIFF or MDI file, bad magic number %u (%#x)", hdr.common.tiff_magic, hdr.common.tiff_magic); } if (hdr.common.tiff_magic == TIFF_BIGENDIAN || hdr.common.tiff_magic == MDI_BIGENDIAN) swabflag = !bigendian; else swabflag = bigendian; if (swabflag) TIFFSwabShort(&hdr.common.tiff_version); if (hdr.common.tiff_version == 42) { if (read(fd, ((char *)&hdr.classic) + offsetof(TIFFHeaderClassic, tiff_diroff), 4) != 4) ReadError("TIFF header"); if (swabflag) TIFFSwabLong(&hdr.classic.tiff_diroff); printf("Magic: %#x <%s-endian> Version: %#x <%s>\n", hdr.classic.tiff_magic, hdr.classic.tiff_magic == TIFF_BIGENDIAN ? "big" : "little", 42, "ClassicTIFF"); if (diroff == 0) diroff = hdr.classic.tiff_diroff; } else if (hdr.common.tiff_version == 43) { if (read(fd, ((char *)&hdr.big) + offsetof(TIFFHeaderBig, tiff_offsetsize), 12) != 12) ReadError("TIFF header"); if (swabflag) { TIFFSwabShort(&hdr.big.tiff_offsetsize); TIFFSwabShort(&hdr.big.tiff_unused); TIFFSwabLong8(&hdr.big.tiff_diroff); } printf("Magic: %#x <%s-endian> Version: %#x <%s>\n", hdr.big.tiff_magic, hdr.big.tiff_magic == TIFF_BIGENDIAN ? "big" : "little", 43, "BigTIFF"); printf("OffsetSize: %#x Unused: %#x\n", hdr.big.tiff_offsetsize, hdr.big.tiff_unused); if (diroff == 0) diroff = hdr.big.tiff_diroff; bigtiff = 1; } else Fatal("Not a TIFF file, bad version number %u (%#x)", hdr.common.tiff_version, hdr.common.tiff_version); for (i = 0; diroff != 0; i++) { for (j = 0; j < count_visited_dir; j++) { if (visited_diroff[j] == diroff) { free(visited_diroff); Fatal("Cycle detected in chaining of TIFF directories!"); } } { size_t alloc_size; alloc_size = TIFFSafeMultiply(tmsize_t, (count_visited_dir + 1), sizeof(uint64_t)); if (alloc_size == 0) { if (visited_diroff) free(visited_diroff); visited_diroff = 0; } else { visited_diroff = (uint64_t *)realloc(visited_diroff, alloc_size); } } if (!visited_diroff) Fatal("Out of memory"); visited_diroff[count_visited_dir] = diroff; count_visited_dir++; if (i > 0) putchar('\n'); diroff = ReadDirectory(fd, i, diroff); } if (visited_diroff) free(visited_diroff); } static const int datawidth[] = { 0, /* 00 = undefined */ 1, /* 01 = TIFF_BYTE */ 1, /* 02 = TIFF_ASCII */ 2, /* 03 = TIFF_SHORT */ 4, /* 04 = TIFF_LONG */ 8, /* 05 = TIFF_RATIONAL */ 1, /* 06 = TIFF_SBYTE */ 1, /* 07 = TIFF_UNDEFINED */ 2, /* 08 = TIFF_SSHORT */ 4, /* 09 = TIFF_SLONG */ 8, /* 10 = TIFF_SRATIONAL */ 4, /* 11 = TIFF_FLOAT */ 8, /* 12 = TIFF_DOUBLE */ 4, /* 13 = TIFF_IFD */ 0, /* 14 = undefined */ 0, /* 15 = undefined */ 8, /* 16 = TIFF_LONG8 */ 8, /* 17 = TIFF_SLONG8 */ 8, /* 18 = TIFF_IFD8 */ }; #define NWIDTHS (sizeof(datawidth) / sizeof(datawidth[0])) static void PrintTag(FILE *, uint16_t); static void PrintType(FILE *, uint16_t); static void PrintData(FILE *, uint16_t, uint32_t, unsigned char *); /* * Read the next TIFF directory from a file * and convert it to the internal format. * We read directories sequentially. */ static uint64_t ReadDirectory(int fd, unsigned int ix, uint64_t off) { uint16_t dircount; uint32_t direntrysize; void *dirmem = NULL; uint64_t nextdiroff = 0; uint32_t n; uint8_t *dp; if (off == 0) /* no more directories */ goto done; if (_TIFF_lseek_f(fd, (_TIFF_off_t)off, SEEK_SET) != (_TIFF_off_t)off) { Fatal("Seek error accessing TIFF directory"); goto done; } if (!bigtiff) { if (read(fd, (char *)&dircount, sizeof(uint16_t)) != sizeof(uint16_t)) { ReadError("directory count"); goto done; } if (swabflag) TIFFSwabShort(&dircount); direntrysize = 12; } else { uint64_t dircount64 = 0; if (read(fd, (char *)&dircount64, sizeof(uint64_t)) != sizeof(uint64_t)) { ReadError("directory count"); goto done; } if (swabflag) TIFFSwabLong8(&dircount64); if (dircount64 > 0xFFFF) { Error("Sanity check on directory count failed"); goto done; } dircount = (uint16_t)dircount64; direntrysize = 20; } dirmem = _TIFFmalloc(TIFFSafeMultiply(tmsize_t, dircount, direntrysize)); if (dirmem == NULL) { Fatal("No space for TIFF directory"); goto done; } n = read(fd, (char *)dirmem, dircount * direntrysize); if (n != dircount * direntrysize) { n /= direntrysize; Error("Could only read %" PRIu32 " of %" PRIu16 " entries in directory at offset %#" PRIu64, n, dircount, off); dircount = n; nextdiroff = 0; } else { if (!bigtiff) { uint32_t nextdiroff32; if (read(fd, (char *)&nextdiroff32, sizeof(uint32_t)) != sizeof(uint32_t)) nextdiroff32 = 0; if (swabflag) TIFFSwabLong(&nextdiroff32); nextdiroff = nextdiroff32; } else { if (read(fd, (char *)&nextdiroff, sizeof(uint64_t)) != sizeof(uint64_t)) nextdiroff = 0; if (swabflag) TIFFSwabLong8(&nextdiroff); } } printf("Directory %u: offset %" PRIu64 " (%#" PRIx64 ") next %" PRIu64 " (%#" PRIx64 ")\n", ix, off, off, nextdiroff, nextdiroff); for (dp = (uint8_t *)dirmem, n = dircount; n > 0; n--) { uint16_t tag; uint16_t type; uint16_t typewidth; uint64_t count; uint64_t datasize; int datafits; void *datamem; uint64_t dataoffset; int datatruncated; int datasizeoverflow; tag = *(uint16_t *)dp; if (swabflag) TIFFSwabShort(&tag); dp += sizeof(uint16_t); type = *(uint16_t *)dp; dp += sizeof(uint16_t); if (swabflag) TIFFSwabShort(&type); PrintTag(stdout, tag); putchar(' '); PrintType(stdout, type); putchar(' '); if (!bigtiff) { uint32_t count32; count32 = *(uint32_t *)dp; if (swabflag) TIFFSwabLong(&count32); dp += sizeof(uint32_t); count = count32; } else { memcpy(&count, dp, sizeof(uint64_t)); if (swabflag) TIFFSwabLong8(&count); dp += sizeof(uint64_t); } printf("%" PRIu64 "<", count); if (type >= NWIDTHS) typewidth = 0; else typewidth = datawidth[type]; datasize = TIFFSafeMultiply(tmsize_t, count, typewidth); datasizeoverflow = (typewidth > 0 && datasize / typewidth != count); datafits = 1; datamem = dp; dataoffset = 0; datatruncated = 0; if (!bigtiff) { if (datasizeoverflow || datasize > 4) { uint32_t dataoffset32; datafits = 0; datamem = NULL; dataoffset32 = *(uint32_t *)dp; if (swabflag) TIFFSwabLong(&dataoffset32); dataoffset = dataoffset32; } dp += sizeof(uint32_t); } else { if (datasizeoverflow || datasize > 8) { datafits = 0; datamem = NULL; memcpy(&dataoffset, dp, sizeof(uint64_t)); if (swabflag) TIFFSwabLong8(&dataoffset); } dp += sizeof(uint64_t); } if (datasizeoverflow || datasize > 0x10000) { datatruncated = 1; count = 0x10000 / typewidth; datasize = TIFFSafeMultiply(tmsize_t, count, typewidth); } if (count > maxitems) { datatruncated = 1; count = maxitems; datasize = TIFFSafeMultiply(tmsize_t, count, typewidth); } if (!datafits) { datamem = _TIFFmalloc(datasize); if (datamem) { if (_TIFF_lseek_f(fd, (_TIFF_off_t)dataoffset, 0) != (_TIFF_off_t)dataoffset) { Error("Seek error accessing tag %u value", tag); _TIFFfree(datamem); datamem = NULL; } else if (read(fd, datamem, (size_t)datasize) != (tmsize_t)datasize) { Error("Read error accessing tag %u value", tag); _TIFFfree(datamem); datamem = NULL; } } else Error("No space for data for tag %u", tag); } if (datamem) { if (swabflag) { switch (type) { case TIFF_BYTE: case TIFF_ASCII: case TIFF_SBYTE: case TIFF_UNDEFINED: break; case TIFF_SHORT: case TIFF_SSHORT: TIFFSwabArrayOfShort((uint16_t *)datamem, (tmsize_t)count); break; case TIFF_LONG: case TIFF_SLONG: case TIFF_FLOAT: case TIFF_IFD: TIFFSwabArrayOfLong((uint32_t *)datamem, (tmsize_t)count); break; case TIFF_RATIONAL: case TIFF_SRATIONAL: TIFFSwabArrayOfLong((uint32_t *)datamem, (tmsize_t)count * 2); break; case TIFF_DOUBLE: case TIFF_LONG8: case TIFF_SLONG8: case TIFF_IFD8: TIFFSwabArrayOfLong8((uint64_t *)datamem, (tmsize_t)count); break; } } PrintData(stdout, type, (uint32_t)count, datamem); if (datatruncated) printf(" ..."); if (!datafits) { _TIFFfree(datamem); datamem = NULL; } } printf(">\n"); } done: if (dirmem) _TIFFfree((char *)dirmem); return (nextdiroff); } static const struct tagname { uint16_t tag; const char *name; } tagnames[] = { {TIFFTAG_SUBFILETYPE, "SubFileType"}, {TIFFTAG_OSUBFILETYPE, "OldSubFileType"}, {TIFFTAG_IMAGEWIDTH, "ImageWidth"}, {TIFFTAG_IMAGELENGTH, "ImageLength"}, {TIFFTAG_BITSPERSAMPLE, "BitsPerSample"}, {TIFFTAG_COMPRESSION, "Compression"}, {TIFFTAG_PHOTOMETRIC, "Photometric"}, {TIFFTAG_THRESHHOLDING, "Threshholding"}, {TIFFTAG_CELLWIDTH, "CellWidth"}, {TIFFTAG_CELLLENGTH, "CellLength"}, {TIFFTAG_FILLORDER, "FillOrder"}, {TIFFTAG_DOCUMENTNAME, "DocumentName"}, {TIFFTAG_IMAGEDESCRIPTION, "ImageDescription"}, {TIFFTAG_MAKE, "Make"}, {TIFFTAG_MODEL, "Model"}, {TIFFTAG_STRIPOFFSETS, "StripOffsets"}, {TIFFTAG_ORIENTATION, "Orientation"}, {TIFFTAG_SAMPLESPERPIXEL, "SamplesPerPixel"}, {TIFFTAG_ROWSPERSTRIP, "RowsPerStrip"}, {TIFFTAG_STRIPBYTECOUNTS, "StripByteCounts"}, {TIFFTAG_MINSAMPLEVALUE, "MinSampleValue"}, {TIFFTAG_MAXSAMPLEVALUE, "MaxSampleValue"}, {TIFFTAG_XRESOLUTION, "XResolution"}, {TIFFTAG_YRESOLUTION, "YResolution"}, {TIFFTAG_PLANARCONFIG, "PlanarConfig"}, {TIFFTAG_PAGENAME, "PageName"}, {TIFFTAG_XPOSITION, "XPosition"}, {TIFFTAG_YPOSITION, "YPosition"}, {TIFFTAG_FREEOFFSETS, "FreeOffsets"}, {TIFFTAG_FREEBYTECOUNTS, "FreeByteCounts"}, {TIFFTAG_GRAYRESPONSEUNIT, "GrayResponseUnit"}, {TIFFTAG_GRAYRESPONSECURVE, "GrayResponseCurve"}, {TIFFTAG_GROUP3OPTIONS, "Group3Options"}, {TIFFTAG_GROUP4OPTIONS, "Group4Options"}, {TIFFTAG_RESOLUTIONUNIT, "ResolutionUnit"}, {TIFFTAG_PAGENUMBER, "PageNumber"}, {TIFFTAG_COLORRESPONSEUNIT, "ColorResponseUnit"}, {TIFFTAG_TRANSFERFUNCTION, "TransferFunction"}, {TIFFTAG_SOFTWARE, "Software"}, {TIFFTAG_DATETIME, "DateTime"}, {TIFFTAG_ARTIST, "Artist"}, {TIFFTAG_HOSTCOMPUTER, "HostComputer"}, {TIFFTAG_PREDICTOR, "Predictor"}, {TIFFTAG_WHITEPOINT, "Whitepoint"}, {TIFFTAG_PRIMARYCHROMATICITIES, "PrimaryChromaticities"}, {TIFFTAG_COLORMAP, "Colormap"}, {TIFFTAG_HALFTONEHINTS, "HalftoneHints"}, {TIFFTAG_TILEWIDTH, "TileWidth"}, {TIFFTAG_TILELENGTH, "TileLength"}, {TIFFTAG_TILEOFFSETS, "TileOffsets"}, {TIFFTAG_TILEBYTECOUNTS, "TileByteCounts"}, {TIFFTAG_BADFAXLINES, "BadFaxLines"}, {TIFFTAG_CLEANFAXDATA, "CleanFaxData"}, {TIFFTAG_CONSECUTIVEBADFAXLINES, "ConsecutiveBadFaxLines"}, {TIFFTAG_SUBIFD, "SubIFD"}, {TIFFTAG_INKSET, "InkSet"}, {TIFFTAG_INKNAMES, "InkNames"}, {TIFFTAG_NUMBEROFINKS, "NumberOfInks"}, {TIFFTAG_DOTRANGE, "DotRange"}, {TIFFTAG_TARGETPRINTER, "TargetPrinter"}, {TIFFTAG_EXTRASAMPLES, "ExtraSamples"}, {TIFFTAG_SAMPLEFORMAT, "SampleFormat"}, {TIFFTAG_SMINSAMPLEVALUE, "SMinSampleValue"}, {TIFFTAG_SMAXSAMPLEVALUE, "SMaxSampleValue"}, {TIFFTAG_JPEGPROC, "JPEGProcessingMode"}, {TIFFTAG_JPEGIFOFFSET, "JPEGInterchangeFormat"}, {TIFFTAG_JPEGIFBYTECOUNT, "JPEGInterchangeFormatLength"}, {TIFFTAG_JPEGRESTARTINTERVAL, "JPEGRestartInterval"}, {TIFFTAG_JPEGLOSSLESSPREDICTORS, "JPEGLosslessPredictors"}, {TIFFTAG_JPEGPOINTTRANSFORM, "JPEGPointTransform"}, {TIFFTAG_JPEGTABLES, "JPEGTables"}, {TIFFTAG_JPEGQTABLES, "JPEGQTables"}, {TIFFTAG_JPEGDCTABLES, "JPEGDCTables"}, {TIFFTAG_JPEGACTABLES, "JPEGACTables"}, {TIFFTAG_YCBCRCOEFFICIENTS, "YCbCrCoefficients"}, {TIFFTAG_YCBCRSUBSAMPLING, "YCbCrSubsampling"}, {TIFFTAG_YCBCRPOSITIONING, "YCbCrPositioning"}, {TIFFTAG_REFERENCEBLACKWHITE, "ReferenceBlackWhite"}, {TIFFTAG_REFPTS, "IgReferencePoints (Island Graphics)"}, {TIFFTAG_REGIONTACKPOINT, "IgRegionTackPoint (Island Graphics)"}, {TIFFTAG_REGIONWARPCORNERS, "IgRegionWarpCorners (Island Graphics)"}, {TIFFTAG_REGIONAFFINE, "IgRegionAffine (Island Graphics)"}, {TIFFTAG_MATTEING, "OBSOLETE Matteing (Silicon Graphics)"}, {TIFFTAG_DATATYPE, "OBSOLETE DataType (Silicon Graphics)"}, {TIFFTAG_IMAGEDEPTH, "ImageDepth (Silicon Graphics)"}, {TIFFTAG_TILEDEPTH, "TileDepth (Silicon Graphics)"}, {32768, "OLD BOGUS Matteing tag"}, {TIFFTAG_COPYRIGHT, "Copyright"}, {TIFFTAG_ICCPROFILE, "ICC Profile"}, {TIFFTAG_JBIGOPTIONS, "JBIG Options"}, {TIFFTAG_STONITS, "StoNits"}, {TIFFTAG_GDAL_METADATA, "GDALMetadata"}, {TIFFTAG_GDAL_NODATA, "GDALNoDataValue"}, }; #define NTAGS (sizeof(tagnames) / sizeof(tagnames[0])) static void PrintTag(FILE *fd, uint16_t tag) { const struct tagname *tp; for (tp = tagnames; tp < &tagnames[NTAGS]; tp++) if (tp->tag == tag) { fprintf(fd, "%s (%u)", tp->name, tag); return; } fprintf(fd, "%u (%#x)", tag, tag); } static void PrintType(FILE *fd, uint16_t type) { static const char *typenames[] = { "0", "BYTE", "ASCII", "SHORT", "LONG", "RATIONAL", "SBYTE", "UNDEFINED", "SSHORT", "SLONG", "SRATIONAL", "FLOAT", "DOUBLE", "IFD", "14", "15", "LONG8", "SLONG8", "IFD8"}; #define NTYPES (sizeof(typenames) / sizeof(typenames[0])) if (type < NTYPES) fprintf(fd, "%s (%u)", typenames[type], type); else fprintf(fd, "%u (%#x)", type, type); } #undef NTYPES #include static void PrintASCII(FILE *fd, uint32_t cc, const unsigned char *cp) { for (; cc > 0; cc--, cp++) { const char *tp; if (isprint(*cp)) { fputc(*cp, fd); continue; } for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++) if (*tp++ == *cp) break; if (*tp) fprintf(fd, "\\%c", *tp); else if (*cp) fprintf(fd, "\\%03o", *cp); else fprintf(fd, "\\0"); } } static void PrintData(FILE *fd, uint16_t type, uint32_t count, unsigned char *data) { char *sep = ""; switch (type) { case TIFF_BYTE: while (count-- > 0) fprintf(fd, bytefmt, sep, *data++), sep = " "; break; case TIFF_SBYTE: while (count-- > 0) fprintf(fd, sbytefmt, sep, *(char *)data++), sep = " "; break; case TIFF_UNDEFINED: while (count-- > 0) fprintf(fd, bytefmt, sep, *data++), sep = " "; break; case TIFF_ASCII: PrintASCII(fd, count, data); break; case TIFF_SHORT: { uint16_t *wp = (uint16_t *)data; while (count-- > 0) fprintf(fd, hex_mode ? shortfmth : shortfmtd, sep, *wp++), sep = " "; break; } case TIFF_SSHORT: { int16_t *wp = (int16_t *)data; while (count-- > 0) fprintf(fd, hex_mode ? sshortfmth : sshortfmtd, sep, *wp++), sep = " "; break; } case TIFF_LONG: { uint32_t *lp = (uint32_t *)data; while (count-- > 0) { fprintf(fd, hex_mode ? longfmth : longfmtd, sep, *lp++); sep = " "; } break; } case TIFF_SLONG: { int32_t *lp = (int32_t *)data; while (count-- > 0) fprintf(fd, hex_mode ? slongfmth : slongfmtd, sep, *lp++), sep = " "; break; } case TIFF_LONG8: { uint64_t *llp = (uint64_t *)data; while (count-- > 0) { uint64_t val; memcpy(&val, llp, sizeof(uint64_t)); llp++; fprintf(fd, long8fmt, sep, val); sep = " "; } break; } case TIFF_SLONG8: { int64_t *llp = (int64_t *)data; while (count-- > 0) { int64_t val; memcpy(&val, llp, sizeof(int64_t)); llp++; fprintf(fd, slong8fmt, sep, val); sep = " "; } break; } case TIFF_RATIONAL: { uint32_t *lp = (uint32_t *)data; while (count-- > 0) { if (lp[1] == 0) fprintf(fd, "%sNan (%" PRIu32 "/%" PRIu32 ")", sep, lp[0], lp[1]); else fprintf(fd, rationalfmt, sep, (double)lp[0] / (double)lp[1]); sep = " "; lp += 2; } break; } case TIFF_SRATIONAL: { int32_t *lp = (int32_t *)data; while (count-- > 0) { if (lp[1] == 0) fprintf(fd, "%sNan (%" PRId32 "/%" PRId32 ")", sep, lp[0], lp[1]); else fprintf(fd, srationalfmt, sep, (double)lp[0] / (double)lp[1]); sep = " "; lp += 2; } break; } case TIFF_FLOAT: { float *fp = (float *)data; while (count-- > 0) fprintf(fd, floatfmt, sep, *fp++), sep = " "; break; } case TIFF_DOUBLE: { double *dp = (double *)data; while (count-- > 0) fprintf(fd, doublefmt, sep, *dp++), sep = " "; break; } case TIFF_IFD: { uint32_t *lp = (uint32_t *)data; while (count-- > 0) { fprintf(fd, ifdfmt, sep, *lp++); sep = " "; } break; } case TIFF_IFD8: { uint64_t *llp = (uint64_t *)data; while (count-- > 0) { fprintf(fd, ifd8fmt, sep, *llp++); sep = " "; sep = " "; } break; } } } static void ReadError(char *what) { Fatal("Error while reading %s", what); } #include static void vError(FILE *fd, const char *fmt, va_list ap) { fprintf(fd, "%s: ", curfile); vfprintf(fd, fmt, ap); fprintf(fd, ".\n"); } static void Error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vError(stderr, fmt, ap); va_end(ap); } static void Fatal(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vError(stderr, fmt, ap); va_end(ap); exit(EXIT_FAILURE); }