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