1/* $Id: tiffinfo.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_STRINGS_H 34# include <strings.h> 35#endif 36 37#ifdef HAVE_UNISTD_H 38# include <unistd.h> 39#endif 40 41#include "tiffio.h" 42 43#define streq(a,b) (strcasecmp(a,b) == 0) 44 45int showdata = 0; /* show data */ 46int rawdata = 0; /* show raw/decoded data */ 47int showwords = 0; /* show data as bytes/words */ 48int readdata = 0; /* read data in file */ 49int stoponerr = 1; /* stop on first read error */ 50 51static void usage(void); 52static void tiffinfo(TIFF*, uint16, long); 53 54int 55main(int argc, char* argv[]) 56{ 57 int dirnum = -1, multiplefiles, c; 58 uint16 order = 0; 59 TIFF* tif; 60 extern int optind; 61 extern char* optarg; 62 long flags = 0; 63 uint32 diroff = 0; 64 int chopstrips = 0; /* disable strip chopping */ 65 66 while ((c = getopt(argc, argv, "f:o:cdDSjilmrsvwz0123456789")) != -1) 67 switch (c) { 68 case '0': case '1': case '2': case '3': 69 case '4': case '5': case '6': case '7': 70 case '8': case '9': 71 dirnum = atoi(&argv[optind-1][1]); 72 break; 73 case 'd': 74 showdata++; 75 /* fall thru... */ 76 case 'D': 77 readdata++; 78 break; 79 case 'c': 80 flags |= TIFFPRINT_COLORMAP | TIFFPRINT_CURVES; 81 break; 82 case 'f': /* fill order */ 83 if (streq(optarg, "lsb2msb")) 84 order = FILLORDER_LSB2MSB; 85 else if (streq(optarg, "msb2lsb")) 86 order = FILLORDER_MSB2LSB; 87 else 88 usage(); 89 break; 90 case 'i': 91 stoponerr = 0; 92 break; 93 case 'o': 94 diroff = strtoul(optarg, NULL, 0); 95 break; 96 case 'j': 97 flags |= TIFFPRINT_JPEGQTABLES | 98 TIFFPRINT_JPEGACTABLES | 99 TIFFPRINT_JPEGDCTABLES; 100 break; 101 case 'r': 102 rawdata = 1; 103 break; 104 case 's': 105 flags |= TIFFPRINT_STRIPS; 106 break; 107 case 'w': 108 showwords = 1; 109 break; 110 case 'z': 111 chopstrips = 1; 112 break; 113 case '?': 114 usage(); 115 /*NOTREACHED*/ 116 } 117 if (optind >= argc) 118 usage(); 119 multiplefiles = (argc - optind > 1); 120 for (; optind < argc; optind++) { 121 if (multiplefiles) 122 printf("%s:\n", argv[optind]); 123 tif = TIFFOpen(argv[optind], chopstrips ? "rC" : "rc"); 124 if (tif != NULL) { 125 if (dirnum != -1) { 126 if (TIFFSetDirectory(tif, (tdir_t) dirnum)) 127 tiffinfo(tif, order, flags); 128 } else if (diroff != 0) { 129 if (TIFFSetSubDirectory(tif, diroff)) 130 tiffinfo(tif, order, flags); 131 } else { 132 do { 133 uint32 offset; 134 135 tiffinfo(tif, order, flags); 136 if (TIFFGetField(tif, TIFFTAG_EXIFIFD, 137 &offset)) { 138 if (TIFFReadEXIFDirectory(tif, offset)) 139 tiffinfo(tif, order, flags); 140 } 141 } while (TIFFReadDirectory(tif)); 142 } 143 TIFFClose(tif); 144 } 145 } 146 return (0); 147} 148 149char* stuff[] = { 150"usage: tiffinfo [options] input...", 151"where options are:", 152" -D read data", 153" -i ignore read errors", 154" -c display data for grey/color response curve or colormap", 155" -d display raw/decoded image data", 156" -f lsb2msb force lsb-to-msb FillOrder for input", 157" -f msb2lsb force msb-to-lsb FillOrder for input", 158" -j show JPEG tables", 159" -o offset set initial directory offset", 160" -r read/display raw image data instead of decoded data", 161" -s display strip offsets and byte counts", 162" -w display raw data in words rather than bytes", 163" -z enable strip chopping", 164" -# set initial directory (first directory is # 0)", 165NULL 166}; 167 168static void 169usage(void) 170{ 171 char buf[BUFSIZ]; 172 int i; 173 174 setbuf(stderr, buf); 175 fprintf(stderr, "%s\n\n", TIFFGetVersion()); 176 for (i = 0; stuff[i] != NULL; i++) 177 fprintf(stderr, "%s\n", stuff[i]); 178 exit(-1); 179} 180 181static void 182ShowStrip(tstrip_t strip, unsigned char* pp, uint32 nrow, tsize_t scanline) 183{ 184 register tsize_t cc; 185 186 printf("Strip %lu:\n", (unsigned long) strip); 187 while (nrow-- > 0) { 188 for (cc = 0; cc < scanline; cc++) { 189 printf(" %02x", *pp++); 190 if (((cc+1) % 24) == 0) 191 putchar('\n'); 192 } 193 putchar('\n'); 194 } 195} 196 197void 198TIFFReadContigStripData(TIFF* tif) 199{ 200 unsigned char *buf; 201 tsize_t scanline = TIFFScanlineSize(tif); 202 203 buf = (unsigned char *)_TIFFmalloc(TIFFStripSize(tif)); 204 if (buf) { 205 uint32 row, h; 206 uint32 rowsperstrip = (uint32)-1; 207 208 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); 209 TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); 210 for (row = 0; row < h; row += rowsperstrip) { 211 uint32 nrow = (row+rowsperstrip > h ? 212 h-row : rowsperstrip); 213 tstrip_t strip = TIFFComputeStrip(tif, row, 0); 214 if (TIFFReadEncodedStrip(tif, strip, buf, nrow*scanline) < 0) { 215 if (stoponerr) 216 break; 217 } else if (showdata) 218 ShowStrip(strip, buf, nrow, scanline); 219 } 220 _TIFFfree(buf); 221 } 222} 223 224void 225TIFFReadSeparateStripData(TIFF* tif) 226{ 227 unsigned char *buf; 228 tsize_t scanline = TIFFScanlineSize(tif); 229 230 buf = (unsigned char *)_TIFFmalloc(TIFFStripSize(tif)); 231 if (buf) { 232 uint32 row, h; 233 uint32 rowsperstrip = (uint32)-1; 234 tsample_t s, samplesperpixel; 235 236 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); 237 TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); 238 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); 239 for (row = 0; row < h; row += rowsperstrip) { 240 for (s = 0; s < samplesperpixel; s++) { 241 uint32 nrow = (row+rowsperstrip > h ? 242 h-row : rowsperstrip); 243 tstrip_t strip = TIFFComputeStrip(tif, row, s); 244 if (TIFFReadEncodedStrip(tif, strip, buf, nrow*scanline) < 0) { 245 if (stoponerr) 246 break; 247 } else if (showdata) 248 ShowStrip(strip, buf, nrow, scanline); 249 } 250 } 251 _TIFFfree(buf); 252 } 253} 254 255static void 256ShowTile(uint32 row, uint32 col, tsample_t sample, 257 unsigned char* pp, uint32 nrow, uint32 rowsize) 258{ 259 uint32 cc; 260 261 printf("Tile (%lu,%lu", (unsigned long) row, (unsigned long) col); 262 if (sample != (tsample_t) -1) 263 printf(",%u", sample); 264 printf("):\n"); 265 while (nrow-- > 0) { 266 for (cc = 0; cc < rowsize; cc++) { 267 printf(" %02x", *pp++); 268 if (((cc+1) % 24) == 0) 269 putchar('\n'); 270 } 271 putchar('\n'); 272 } 273} 274 275void 276TIFFReadContigTileData(TIFF* tif) 277{ 278 unsigned char *buf; 279 tsize_t rowsize = TIFFTileRowSize(tif); 280 281 buf = (unsigned char *)_TIFFmalloc(TIFFTileSize(tif)); 282 if (buf) { 283 uint32 tw, th, w, h; 284 uint32 row, col; 285 286 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); 287 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); 288 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); 289 TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); 290 for (row = 0; row < h; row += th) { 291 for (col = 0; col < w; col += tw) { 292 if (TIFFReadTile(tif, buf, col, row, 0, 0) < 0) { 293 if (stoponerr) 294 break; 295 } else if (showdata) 296 ShowTile(row, col, (tsample_t) -1, buf, th, rowsize); 297 } 298 } 299 _TIFFfree(buf); 300 } 301} 302 303void 304TIFFReadSeparateTileData(TIFF* tif) 305{ 306 unsigned char *buf; 307 tsize_t rowsize = TIFFTileRowSize(tif); 308 309 buf = (unsigned char *)_TIFFmalloc(TIFFTileSize(tif)); 310 if (buf) { 311 uint32 tw, th, w, h; 312 uint32 row, col; 313 tsample_t s, samplesperpixel; 314 315 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); 316 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); 317 TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw); 318 TIFFGetField(tif, TIFFTAG_TILELENGTH, &th); 319 TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); 320 for (row = 0; row < h; row += th) { 321 for (col = 0; col < w; col += tw) { 322 for (s = 0; s < samplesperpixel; s++) { 323 if (TIFFReadTile(tif, buf, col, row, 0, s) < 0) { 324 if (stoponerr) 325 break; 326 } else if (showdata) 327 ShowTile(row, col, s, buf, th, rowsize); 328 } 329 } 330 } 331 _TIFFfree(buf); 332 } 333} 334 335void 336TIFFReadData(TIFF* tif) 337{ 338 uint16 config; 339 340 TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &config); 341 if (TIFFIsTiled(tif)) { 342 if (config == PLANARCONFIG_CONTIG) 343 TIFFReadContigTileData(tif); 344 else 345 TIFFReadSeparateTileData(tif); 346 } else { 347 if (config == PLANARCONFIG_CONTIG) 348 TIFFReadContigStripData(tif); 349 else 350 TIFFReadSeparateStripData(tif); 351 } 352} 353 354static void 355ShowRawBytes(unsigned char* pp, uint32 n) 356{ 357 uint32 i; 358 359 for (i = 0; i < n; i++) { 360 printf(" %02x", *pp++); 361 if (((i+1) % 24) == 0) 362 printf("\n "); 363 } 364 putchar('\n'); 365} 366 367static void 368ShowRawWords(uint16* pp, uint32 n) 369{ 370 uint32 i; 371 372 for (i = 0; i < n; i++) { 373 printf(" %04x", *pp++); 374 if (((i+1) % 15) == 0) 375 printf("\n "); 376 } 377 putchar('\n'); 378} 379 380void 381TIFFReadRawData(TIFF* tif, int bitrev) 382{ 383 tstrip_t nstrips = TIFFNumberOfStrips(tif); 384 const char* what = TIFFIsTiled(tif) ? "Tile" : "Strip"; 385 uint32* stripbc; 386 387 TIFFGetField(tif, TIFFTAG_STRIPBYTECOUNTS, &stripbc); 388 if (nstrips > 0) { 389 uint32 bufsize = stripbc[0]; 390 tdata_t buf = _TIFFmalloc(bufsize); 391 tstrip_t s; 392 393 for (s = 0; s < nstrips; s++) { 394 if (stripbc[s] > bufsize) { 395 buf = _TIFFrealloc(buf, stripbc[s]); 396 bufsize = stripbc[s]; 397 } 398 if (buf == NULL) { 399 fprintf(stderr, 400 "Cannot allocate buffer to read strip %lu\n", 401 (unsigned long) s); 402 break; 403 } 404 if (TIFFReadRawStrip(tif, s, buf, stripbc[s]) < 0) { 405 fprintf(stderr, "Error reading strip %lu\n", 406 (unsigned long) s); 407 if (stoponerr) 408 break; 409 } else if (showdata) { 410 if (bitrev) { 411 TIFFReverseBits(buf, stripbc[s]); 412 printf("%s %lu: (bit reversed)\n ", 413 what, (unsigned long) s); 414 } else 415 printf("%s %lu:\n ", what, 416 (unsigned long) s); 417 if (showwords) 418 ShowRawWords((uint16*) buf, stripbc[s]>>1); 419 else 420 ShowRawBytes((unsigned char*) buf, stripbc[s]); 421 } 422 } 423 if (buf != NULL) 424 _TIFFfree(buf); 425 } 426} 427 428static void 429tiffinfo(TIFF* tif, uint16 order, long flags) 430{ 431 TIFFPrintDirectory(tif, stdout, flags); 432 if (!readdata) 433 return; 434 if (rawdata) { 435 if (order) { 436 uint16 o; 437 TIFFGetFieldDefaulted(tif, 438 TIFFTAG_FILLORDER, &o); 439 TIFFReadRawData(tif, o != order); 440 } else 441 TIFFReadRawData(tif, 0); 442 } else { 443 if (order) 444 TIFFSetField(tif, TIFFTAG_FILLORDER, order); 445 TIFFReadData(tif); 446 } 447} 448 449/* vim: set ts=8 sts=8 sw=8 noet: */ 450/* 451 * Local Variables: 452 * mode: c 453 * c-basic-offset: 8 454 * fill-column: 78 455 * End: 456 */ 457