1/* $Id: tif_print.c,v 1.62 2015-08-19 02:31:04 bfriesen Exp $ */
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/*
28 * TIFF Library.
29 *
30 * Directory Printing Support
31 */
32#include "tiffiop.h"
33#include <stdio.h>
34
35#include <ctype.h>
36
37static void
38_TIFFprintAsciiBounded(FILE* fd, const char* cp, size_t max_chars);
39
40static const char *photoNames[] = {
41    "min-is-white",				/* PHOTOMETRIC_MINISWHITE */
42    "min-is-black",				/* PHOTOMETRIC_MINISBLACK */
43    "RGB color",				/* PHOTOMETRIC_RGB */
44    "palette color (RGB from colormap)",	/* PHOTOMETRIC_PALETTE */
45    "transparency mask",			/* PHOTOMETRIC_MASK */
46    "separated",				/* PHOTOMETRIC_SEPARATED */
47    "YCbCr",					/* PHOTOMETRIC_YCBCR */
48    "7 (0x7)",
49    "CIE L*a*b*",				/* PHOTOMETRIC_CIELAB */
50    "ICC L*a*b*",				/* PHOTOMETRIC_ICCLAB */
51    "ITU L*a*b*" 				/* PHOTOMETRIC_ITULAB */
52};
53#define	NPHOTONAMES	(sizeof (photoNames) / sizeof (photoNames[0]))
54
55static const char *orientNames[] = {
56    "0 (0x0)",
57    "row 0 top, col 0 lhs",			/* ORIENTATION_TOPLEFT */
58    "row 0 top, col 0 rhs",			/* ORIENTATION_TOPRIGHT */
59    "row 0 bottom, col 0 rhs",			/* ORIENTATION_BOTRIGHT */
60    "row 0 bottom, col 0 lhs",			/* ORIENTATION_BOTLEFT */
61    "row 0 lhs, col 0 top",			/* ORIENTATION_LEFTTOP */
62    "row 0 rhs, col 0 top",			/* ORIENTATION_RIGHTTOP */
63    "row 0 rhs, col 0 bottom",			/* ORIENTATION_RIGHTBOT */
64    "row 0 lhs, col 0 bottom",			/* ORIENTATION_LEFTBOT */
65};
66#define	NORIENTNAMES	(sizeof (orientNames) / sizeof (orientNames[0]))
67
68static void
69_TIFFPrintField(FILE* fd, const TIFFField *fip,
70		uint32 value_count, void *raw_data)
71{
72	uint32 j;
73
74	fprintf(fd, "  %s: ", fip->field_name);
75
76	for(j = 0; j < value_count; j++) {
77		if(fip->field_type == TIFF_BYTE)
78			fprintf(fd, "%u", ((uint8 *) raw_data)[j]);
79		else if(fip->field_type == TIFF_UNDEFINED)
80			fprintf(fd, "0x%x",
81			    (unsigned int) ((unsigned char *) raw_data)[j]);
82		else if(fip->field_type == TIFF_SBYTE)
83			fprintf(fd, "%d", ((int8 *) raw_data)[j]);
84		else if(fip->field_type == TIFF_SHORT)
85			fprintf(fd, "%u", ((uint16 *) raw_data)[j]);
86		else if(fip->field_type == TIFF_SSHORT)
87			fprintf(fd, "%d", ((int16 *) raw_data)[j]);
88		else if(fip->field_type == TIFF_LONG)
89			fprintf(fd, "%lu",
90			    (unsigned long)((uint32 *) raw_data)[j]);
91		else if(fip->field_type == TIFF_SLONG)
92			fprintf(fd, "%ld", (long)((int32 *) raw_data)[j]);
93		else if(fip->field_type == TIFF_IFD)
94			fprintf(fd, "0x%lx",
95				(unsigned long)((uint32 *) raw_data)[j]);
96		else if(fip->field_type == TIFF_RATIONAL
97			|| fip->field_type == TIFF_SRATIONAL
98			|| fip->field_type == TIFF_FLOAT)
99			fprintf(fd, "%f", ((float *) raw_data)[j]);
100		else if(fip->field_type == TIFF_LONG8)
101#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
102			fprintf(fd, "%I64u",
103			    (unsigned __int64)((uint64 *) raw_data)[j]);
104#else
105			fprintf(fd, "%llu",
106			    (unsigned long long)((uint64 *) raw_data)[j]);
107#endif
108		else if(fip->field_type == TIFF_SLONG8)
109#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
110			fprintf(fd, "%I64d", (__int64)((int64 *) raw_data)[j]);
111#else
112			fprintf(fd, "%lld", (long long)((int64 *) raw_data)[j]);
113#endif
114		else if(fip->field_type == TIFF_IFD8)
115#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
116			fprintf(fd, "0x%I64x",
117				(unsigned __int64)((uint64 *) raw_data)[j]);
118#else
119			fprintf(fd, "0x%llx",
120				(unsigned long long)((uint64 *) raw_data)[j]);
121#endif
122		else if(fip->field_type == TIFF_FLOAT)
123			fprintf(fd, "%f", ((float *)raw_data)[j]);
124		else if(fip->field_type == TIFF_DOUBLE)
125			fprintf(fd, "%f", ((double *) raw_data)[j]);
126		else if(fip->field_type == TIFF_ASCII) {
127			fprintf(fd, "%s", (char *) raw_data);
128			break;
129		}
130		else {
131			fprintf(fd, "<unsupported data type in TIFFPrint>");
132			break;
133		}
134
135		if(j < value_count - 1)
136			fprintf(fd, ",");
137	}
138
139	fprintf(fd, "\n");
140}
141
142static int
143_TIFFPrettyPrintField(TIFF* tif, const TIFFField *fip, FILE* fd, uint32 tag,
144		      uint32 value_count, void *raw_data)
145{
146        (void) tif;
147
148	/* do not try to pretty print auto-defined fields */
149	if (strncmp(fip->field_name,"Tag ", 4) == 0) {
150		return 0;
151	}
152
153	switch (tag)
154	{
155		case TIFFTAG_INKSET:
156			if (value_count == 2 && fip->field_type == TIFF_SHORT) {
157				fprintf(fd, "  Ink Set: ");
158				switch (*((uint16*)raw_data)) {
159				case INKSET_CMYK:
160					fprintf(fd, "CMYK\n");
161					break;
162				default:
163					fprintf(fd, "%u (0x%x)\n",
164						*((uint16*)raw_data),
165						*((uint16*)raw_data));
166					break;
167				}
168				return 1;
169			}
170			return 0;
171
172		case TIFFTAG_DOTRANGE:
173			if (value_count == 2 && fip->field_type == TIFF_SHORT) {
174				fprintf(fd, "  Dot Range: %u-%u\n",
175					((uint16*)raw_data)[0], ((uint16*)raw_data)[1]);
176				return 1;
177			}
178			return 0;
179
180		case TIFFTAG_WHITEPOINT:
181			if (value_count == 2 && fip->field_type == TIFF_RATIONAL) {
182				fprintf(fd, "  White Point: %g-%g\n",
183					((float *)raw_data)[0], ((float *)raw_data)[1]);
184				return 1;
185			}
186			return 0;
187
188		case TIFFTAG_XMLPACKET:
189		{
190			uint32 i;
191
192			fprintf(fd, "  XMLPacket (XMP Metadata):\n" );
193			for(i = 0; i < value_count; i++)
194				fputc(((char *)raw_data)[i], fd);
195			fprintf( fd, "\n" );
196			return 1;
197		}
198		case TIFFTAG_RICHTIFFIPTC:
199			/*
200			 * XXX: for some weird reason RichTIFFIPTC tag
201			 * defined as array of LONG values.
202			 */
203			fprintf(fd,
204			    "  RichTIFFIPTC Data: <present>, %lu bytes\n",
205			    (unsigned long) value_count * 4);
206			return 1;
207
208		case TIFFTAG_PHOTOSHOP:
209			fprintf(fd, "  Photoshop Data: <present>, %lu bytes\n",
210			    (unsigned long) value_count);
211			return 1;
212
213		case TIFFTAG_ICCPROFILE:
214			fprintf(fd, "  ICC Profile: <present>, %lu bytes\n",
215			    (unsigned long) value_count);
216			return 1;
217
218		case TIFFTAG_STONITS:
219			if (value_count == 1 && fip->field_type == TIFF_DOUBLE) {
220				fprintf(fd,
221					"  Sample to Nits conversion factor: %.4e\n",
222					*((double*)raw_data));
223				return 1;
224			}
225			return 0;
226	}
227
228	return 0;
229}
230
231/*
232 * Print the contents of the current directory
233 * to the specified stdio file stream.
234 */
235void
236TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
237{
238	TIFFDirectory *td = &tif->tif_dir;
239	char *sep;
240	uint16 i;
241	long l, n;
242
243#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
244	fprintf(fd, "TIFF Directory at offset 0x%I64x (%I64u)\n",
245		(unsigned __int64) tif->tif_diroff,
246		(unsigned __int64) tif->tif_diroff);
247#else
248	fprintf(fd, "TIFF Directory at offset 0x%llx (%llu)\n",
249		(unsigned long long) tif->tif_diroff,
250		(unsigned long long) tif->tif_diroff);
251#endif
252	if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) {
253		fprintf(fd, "  Subfile Type:");
254		sep = " ";
255		if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) {
256			fprintf(fd, "%sreduced-resolution image", sep);
257			sep = "/";
258		}
259		if (td->td_subfiletype & FILETYPE_PAGE) {
260			fprintf(fd, "%smulti-page document", sep);
261			sep = "/";
262		}
263		if (td->td_subfiletype & FILETYPE_MASK)
264			fprintf(fd, "%stransparency mask", sep);
265		fprintf(fd, " (%lu = 0x%lx)\n",
266		    (long) td->td_subfiletype, (long) td->td_subfiletype);
267	}
268	if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) {
269		fprintf(fd, "  Image Width: %lu Image Length: %lu",
270		    (unsigned long) td->td_imagewidth, (unsigned long) td->td_imagelength);
271		if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH))
272			fprintf(fd, " Image Depth: %lu",
273			    (unsigned long) td->td_imagedepth);
274		fprintf(fd, "\n");
275	}
276	if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) {
277		fprintf(fd, "  Tile Width: %lu Tile Length: %lu",
278		    (unsigned long) td->td_tilewidth, (unsigned long) td->td_tilelength);
279		if (TIFFFieldSet(tif,FIELD_TILEDEPTH))
280			fprintf(fd, " Tile Depth: %lu",
281			    (unsigned long) td->td_tiledepth);
282		fprintf(fd, "\n");
283	}
284	if (TIFFFieldSet(tif,FIELD_RESOLUTION)) {
285		fprintf(fd, "  Resolution: %g, %g",
286		    td->td_xresolution, td->td_yresolution);
287		if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) {
288			switch (td->td_resolutionunit) {
289			case RESUNIT_NONE:
290				fprintf(fd, " (unitless)");
291				break;
292			case RESUNIT_INCH:
293				fprintf(fd, " pixels/inch");
294				break;
295			case RESUNIT_CENTIMETER:
296				fprintf(fd, " pixels/cm");
297				break;
298			default:
299				fprintf(fd, " (unit %u = 0x%x)",
300				    td->td_resolutionunit,
301				    td->td_resolutionunit);
302				break;
303			}
304		}
305		fprintf(fd, "\n");
306	}
307	if (TIFFFieldSet(tif,FIELD_POSITION))
308		fprintf(fd, "  Position: %g, %g\n",
309		    td->td_xposition, td->td_yposition);
310	if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE))
311		fprintf(fd, "  Bits/Sample: %u\n", td->td_bitspersample);
312	if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) {
313		fprintf(fd, "  Sample Format: ");
314		switch (td->td_sampleformat) {
315		case SAMPLEFORMAT_VOID:
316			fprintf(fd, "void\n");
317			break;
318		case SAMPLEFORMAT_INT:
319			fprintf(fd, "signed integer\n");
320			break;
321		case SAMPLEFORMAT_UINT:
322			fprintf(fd, "unsigned integer\n");
323			break;
324		case SAMPLEFORMAT_IEEEFP:
325			fprintf(fd, "IEEE floating point\n");
326			break;
327		case SAMPLEFORMAT_COMPLEXINT:
328			fprintf(fd, "complex signed integer\n");
329			break;
330		case SAMPLEFORMAT_COMPLEXIEEEFP:
331			fprintf(fd, "complex IEEE floating point\n");
332			break;
333		default:
334			fprintf(fd, "%u (0x%x)\n",
335			    td->td_sampleformat, td->td_sampleformat);
336			break;
337		}
338	}
339	if (TIFFFieldSet(tif,FIELD_COMPRESSION)) {
340		const TIFFCodec* c = TIFFFindCODEC(td->td_compression);
341		fprintf(fd, "  Compression Scheme: ");
342		if (c)
343			fprintf(fd, "%s\n", c->name);
344		else
345			fprintf(fd, "%u (0x%x)\n",
346			    td->td_compression, td->td_compression);
347	}
348	if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) {
349		fprintf(fd, "  Photometric Interpretation: ");
350		if (td->td_photometric < NPHOTONAMES)
351			fprintf(fd, "%s\n", photoNames[td->td_photometric]);
352		else {
353			switch (td->td_photometric) {
354			case PHOTOMETRIC_LOGL:
355				fprintf(fd, "CIE Log2(L)\n");
356				break;
357			case PHOTOMETRIC_LOGLUV:
358				fprintf(fd, "CIE Log2(L) (u',v')\n");
359				break;
360			default:
361				fprintf(fd, "%u (0x%x)\n",
362				    td->td_photometric, td->td_photometric);
363				break;
364			}
365		}
366	}
367	if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) {
368		fprintf(fd, "  Extra Samples: %u<", td->td_extrasamples);
369		sep = "";
370		for (i = 0; i < td->td_extrasamples; i++) {
371			switch (td->td_sampleinfo[i]) {
372			case EXTRASAMPLE_UNSPECIFIED:
373				fprintf(fd, "%sunspecified", sep);
374				break;
375			case EXTRASAMPLE_ASSOCALPHA:
376				fprintf(fd, "%sassoc-alpha", sep);
377				break;
378			case EXTRASAMPLE_UNASSALPHA:
379				fprintf(fd, "%sunassoc-alpha", sep);
380				break;
381			default:
382				fprintf(fd, "%s%u (0x%x)", sep,
383				    td->td_sampleinfo[i], td->td_sampleinfo[i]);
384				break;
385			}
386			sep = ", ";
387		}
388		fprintf(fd, ">\n");
389	}
390	if (TIFFFieldSet(tif,FIELD_INKNAMES)) {
391		char* cp;
392		fprintf(fd, "  Ink Names: ");
393		i = td->td_samplesperpixel;
394		sep = "";
395		for (cp = td->td_inknames;
396		     i > 0 && cp < td->td_inknames + td->td_inknameslen;
397		     cp = strchr(cp,'\0')+1, i--) {
398			size_t max_chars =
399				td->td_inknameslen - (cp - td->td_inknames);
400			fputs(sep, fd);
401			_TIFFprintAsciiBounded(fd, cp, max_chars);
402			sep = ", ";
403		}
404                fputs("\n", fd);
405	}
406	if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) {
407		fprintf(fd, "  Thresholding: ");
408		switch (td->td_threshholding) {
409		case THRESHHOLD_BILEVEL:
410			fprintf(fd, "bilevel art scan\n");
411			break;
412		case THRESHHOLD_HALFTONE:
413			fprintf(fd, "halftone or dithered scan\n");
414			break;
415		case THRESHHOLD_ERRORDIFFUSE:
416			fprintf(fd, "error diffused\n");
417			break;
418		default:
419			fprintf(fd, "%u (0x%x)\n",
420			    td->td_threshholding, td->td_threshholding);
421			break;
422		}
423	}
424	if (TIFFFieldSet(tif,FIELD_FILLORDER)) {
425		fprintf(fd, "  FillOrder: ");
426		switch (td->td_fillorder) {
427		case FILLORDER_MSB2LSB:
428			fprintf(fd, "msb-to-lsb\n");
429			break;
430		case FILLORDER_LSB2MSB:
431			fprintf(fd, "lsb-to-msb\n");
432			break;
433		default:
434			fprintf(fd, "%u (0x%x)\n",
435			    td->td_fillorder, td->td_fillorder);
436			break;
437		}
438	}
439	if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING))
440        {
441		fprintf(fd, "  YCbCr Subsampling: %u, %u\n",
442			td->td_ycbcrsubsampling[0], td->td_ycbcrsubsampling[1] );
443	}
444	if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) {
445		fprintf(fd, "  YCbCr Positioning: ");
446		switch (td->td_ycbcrpositioning) {
447		case YCBCRPOSITION_CENTERED:
448			fprintf(fd, "centered\n");
449			break;
450		case YCBCRPOSITION_COSITED:
451			fprintf(fd, "cosited\n");
452			break;
453		default:
454			fprintf(fd, "%u (0x%x)\n",
455			    td->td_ycbcrpositioning, td->td_ycbcrpositioning);
456			break;
457		}
458	}
459	if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS))
460		fprintf(fd, "  Halftone Hints: light %u dark %u\n",
461		    td->td_halftonehints[0], td->td_halftonehints[1]);
462	if (TIFFFieldSet(tif,FIELD_ORIENTATION)) {
463		fprintf(fd, "  Orientation: ");
464		if (td->td_orientation < NORIENTNAMES)
465			fprintf(fd, "%s\n", orientNames[td->td_orientation]);
466		else
467			fprintf(fd, "%u (0x%x)\n",
468			    td->td_orientation, td->td_orientation);
469	}
470	if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL))
471		fprintf(fd, "  Samples/Pixel: %u\n", td->td_samplesperpixel);
472	if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) {
473		fprintf(fd, "  Rows/Strip: ");
474		if (td->td_rowsperstrip == (uint32) -1)
475			fprintf(fd, "(infinite)\n");
476		else
477			fprintf(fd, "%lu\n", (unsigned long) td->td_rowsperstrip);
478	}
479	if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE))
480		fprintf(fd, "  Min Sample Value: %u\n", td->td_minsamplevalue);
481	if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE))
482		fprintf(fd, "  Max Sample Value: %u\n", td->td_maxsamplevalue);
483	if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE)) {
484		int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1;
485		fprintf(fd, "  SMin Sample Value:");
486		for (i = 0; i < count; ++i)
487			fprintf(fd, " %g", td->td_sminsamplevalue[i]);
488		fprintf(fd, "\n");
489	}
490	if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE)) {
491		int count = (tif->tif_flags & TIFF_PERSAMPLE) ? td->td_samplesperpixel : 1;
492		fprintf(fd, "  SMax Sample Value:");
493		for (i = 0; i < count; ++i)
494			fprintf(fd, " %g", td->td_smaxsamplevalue[i]);
495		fprintf(fd, "\n");
496	}
497	if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) {
498		fprintf(fd, "  Planar Configuration: ");
499		switch (td->td_planarconfig) {
500		case PLANARCONFIG_CONTIG:
501			fprintf(fd, "single image plane\n");
502			break;
503		case PLANARCONFIG_SEPARATE:
504			fprintf(fd, "separate image planes\n");
505			break;
506		default:
507			fprintf(fd, "%u (0x%x)\n",
508			    td->td_planarconfig, td->td_planarconfig);
509			break;
510		}
511	}
512	if (TIFFFieldSet(tif,FIELD_PAGENUMBER))
513		fprintf(fd, "  Page Number: %u-%u\n",
514		    td->td_pagenumber[0], td->td_pagenumber[1]);
515	if (TIFFFieldSet(tif,FIELD_COLORMAP)) {
516		fprintf(fd, "  Color Map: ");
517		if (flags & TIFFPRINT_COLORMAP) {
518			fprintf(fd, "\n");
519			n = 1L<<td->td_bitspersample;
520			for (l = 0; l < n; l++)
521				fprintf(fd, "   %5lu: %5u %5u %5u\n",
522				    l,
523				    td->td_colormap[0][l],
524				    td->td_colormap[1][l],
525				    td->td_colormap[2][l]);
526		} else
527			fprintf(fd, "(present)\n");
528	}
529	if (TIFFFieldSet(tif,FIELD_REFBLACKWHITE)) {
530		fprintf(fd, "  Reference Black/White:\n");
531		for (i = 0; i < 3; i++)
532		fprintf(fd, "    %2d: %5g %5g\n", i,
533			td->td_refblackwhite[2*i+0],
534			td->td_refblackwhite[2*i+1]);
535	}
536	if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) {
537		fprintf(fd, "  Transfer Function: ");
538		if (flags & TIFFPRINT_CURVES) {
539			fprintf(fd, "\n");
540			n = 1L<<td->td_bitspersample;
541			for (l = 0; l < n; l++) {
542				fprintf(fd, "    %2lu: %5u",
543				    l, td->td_transferfunction[0][l]);
544				for (i = 1; i < td->td_samplesperpixel; i++)
545					fprintf(fd, " %5u",
546					    td->td_transferfunction[i][l]);
547				fputc('\n', fd);
548			}
549		} else
550			fprintf(fd, "(present)\n");
551	}
552	if (TIFFFieldSet(tif, FIELD_SUBIFD) && (td->td_subifd)) {
553		fprintf(fd, "  SubIFD Offsets:");
554		for (i = 0; i < td->td_nsubifd; i++)
555#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
556			fprintf(fd, " %5I64u",
557				(unsigned __int64) td->td_subifd[i]);
558#else
559			fprintf(fd, " %5llu",
560				(unsigned long long) td->td_subifd[i]);
561#endif
562		fputc('\n', fd);
563	}
564
565	/*
566	** Custom tag support.
567	*/
568	{
569		int  i;
570		short count;
571
572		count = (short) TIFFGetTagListCount(tif);
573		for(i = 0; i < count; i++) {
574			uint32 tag = TIFFGetTagListEntry(tif, i);
575			const TIFFField *fip;
576			uint32 value_count;
577			int mem_alloc = 0;
578			void *raw_data;
579
580			fip = TIFFFieldWithTag(tif, tag);
581			if(fip == NULL)
582				continue;
583
584			if(fip->field_passcount) {
585				if (fip->field_readcount == TIFF_VARIABLE2 ) {
586					if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1)
587						continue;
588				} else if (fip->field_readcount == TIFF_VARIABLE ) {
589					uint16 small_value_count;
590					if(TIFFGetField(tif, tag, &small_value_count, &raw_data) != 1)
591						continue;
592					value_count = small_value_count;
593				} else {
594					assert (fip->field_readcount == TIFF_VARIABLE
595						|| fip->field_readcount == TIFF_VARIABLE2);
596					continue;
597				}
598			} else {
599				if (fip->field_readcount == TIFF_VARIABLE
600				    || fip->field_readcount == TIFF_VARIABLE2)
601					value_count = 1;
602				else if (fip->field_readcount == TIFF_SPP)
603					value_count = td->td_samplesperpixel;
604				else
605					value_count = fip->field_readcount;
606				if (fip->field_tag == TIFFTAG_DOTRANGE
607				    && strcmp(fip->field_name,"DotRange") == 0) {
608					/* TODO: This is an evil exception and should not have been
609					   handled this way ... likely best if we move it into
610					   the directory structure with an explicit field in
611					   libtiff 4.1 and assign it a FIELD_ value */
612					static uint16 dotrange[2];
613					raw_data = dotrange;
614					TIFFGetField(tif, tag, dotrange+0, dotrange+1);
615				} else if (fip->field_type == TIFF_ASCII
616					   || fip->field_readcount == TIFF_VARIABLE
617					   || fip->field_readcount == TIFF_VARIABLE2
618					   || fip->field_readcount == TIFF_SPP
619					   || value_count > 1) {
620					if(TIFFGetField(tif, tag, &raw_data) != 1)
621						continue;
622				} else {
623					raw_data = _TIFFmalloc(
624					    _TIFFDataSize(fip->field_type)
625					    * value_count);
626					mem_alloc = 1;
627					if(TIFFGetField(tif, tag, raw_data) != 1) {
628						_TIFFfree(raw_data);
629						continue;
630					}
631				}
632			}
633
634			/*
635			 * Catch the tags which needs to be specially handled
636			 * and pretty print them. If tag not handled in
637			 * _TIFFPrettyPrintField() fall down and print it as
638			 * any other tag.
639			 */
640			if (!_TIFFPrettyPrintField(tif, fip, fd, tag, value_count, raw_data))
641				_TIFFPrintField(fd, fip, value_count, raw_data);
642
643			if(mem_alloc)
644				_TIFFfree(raw_data);
645		}
646	}
647
648	if (tif->tif_tagmethods.printdir)
649		(*tif->tif_tagmethods.printdir)(tif, fd, flags);
650
651        _TIFFFillStriles( tif );
652
653	if ((flags & TIFFPRINT_STRIPS) &&
654	    TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) {
655		uint32 s;
656
657		fprintf(fd, "  %lu %s:\n",
658		    (long) td->td_nstrips,
659		    isTiled(tif) ? "Tiles" : "Strips");
660		for (s = 0; s < td->td_nstrips; s++)
661#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
662			fprintf(fd, "    %3lu: [%8I64u, %8I64u]\n",
663			    (unsigned long) s,
664			    (unsigned __int64) td->td_stripoffset[s],
665			    (unsigned __int64) td->td_stripbytecount[s]);
666#else
667			fprintf(fd, "    %3lu: [%8llu, %8llu]\n",
668			    (unsigned long) s,
669			    (unsigned long long) td->td_stripoffset[s],
670			    (unsigned long long) td->td_stripbytecount[s]);
671#endif
672	}
673}
674
675void
676_TIFFprintAscii(FILE* fd, const char* cp)
677{
678	_TIFFprintAsciiBounded( fd, cp, strlen(cp));
679}
680
681static void
682_TIFFprintAsciiBounded(FILE* fd, const char* cp, size_t max_chars)
683{
684	for (; max_chars > 0 && *cp != '\0'; cp++, max_chars--) {
685		const char* tp;
686
687		if (isprint((int)*cp)) {
688			fputc(*cp, fd);
689			continue;
690		}
691		for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++)
692			if (*tp++ == *cp)
693				break;
694		if (*tp)
695			fprintf(fd, "\\%c", *tp);
696		else
697			fprintf(fd, "\\%03o", *cp & 0xff);
698	}
699}
700
701void
702_TIFFprintAsciiTag(FILE* fd, const char* name, const char* value)
703{
704	fprintf(fd, "  %s: \"", name);
705	_TIFFprintAscii(fd, value);
706	fprintf(fd, "\"\n");
707}
708
709/* vim: set ts=8 sts=8 sw=8 noet: */
710/*
711 * Local Variables:
712 * mode: c
713 * c-basic-offset: 8
714 * fill-column: 78
715 * End:
716 */
717