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