xref: /libtiff-4.0.7/contrib/tags/xtif_dir.c (revision bfbc7176)
1 /*
2  * xtif_dir.c
3  *
4  * Extended TIFF Directory Tag Support.
5  *
6  *  You may use this file as a template to add your own
7  *  extended tags to the library. Only the parts of the code
8  *  marked with "XXX" require modification. Three example tags
9  *  are shown; you should replace them with your own.
10  *
11  *  Author: Niles D. Ritter
12  */
13 
14 #include "xtiffiop.h"
15 #include <stdio.h>
16 
17 /*  Tiff info structure.
18  *
19  *     Entry format:
20  *        { TAGNUMBER, ReadCount, WriteCount, DataType, FIELDNUM,
21  *          OkToChange, PassDirCountOnSet, AsciiName }
22  *
23  *     For ReadCount, WriteCount, -1 = unknown; used for mult-valued
24  *         tags and ASCII.
25  */
26 
27 static const TIFFFieldInfo xtiffFieldInfo[] = {
28 
29   /* XXX Replace these example tags with your own extended tags */
30     { TIFFTAG_EXAMPLE_MULTI,	-1,-1, TIFF_DOUBLE,	FIELD_EXAMPLE_MULTI,
31       TRUE,	TRUE,	"MyMultivaluedTag" },
32     { TIFFTAG_EXAMPLE_SINGLE,	 1, 1, TIFF_LONG,	FIELD_EXAMPLE_SINGLE,
33       TRUE,	FALSE,	"MySingleLongTag" },
34     { TIFFTAG_EXAMPLE_ASCII,	-1,-1, TIFF_ASCII,	FIELD_EXAMPLE_ASCII,
35       TRUE,	FALSE,	"MyAsciiTag" },
36 };
37 #define	N(a)	(sizeof (a) / sizeof (a[0]))
38 
39 
40 static void
_XTIFFPrintDirectory(TIFF * tif,FILE * fd,long flags)41 _XTIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
42 {
43 	xtiff *xt = XTIFFDIR(tif);
44 	XTIFFDirectory *xd = &xt->xtif_dir;
45 	int i,num;
46 
47 	/* call the inherited method */
48 	if (PARENT(xt,printdir))
49 		(PARENT(xt,printdir))(tif,fd,flags);
50 
51 	/* XXX Add field printing here. Replace the three example
52          *    tags implemented below with your own.
53          */
54 
55 	fprintf(fd,"--My Example Tags--\n");
56 
57 	/* Our first example tag may have a lot of values, so we
58          * will only print them out if the TIFFPRINT_MYMULTIDOUBLES
59          * flag is passed into the print method.
60          */
61 	if (TIFFFieldSet(tif,FIELD_EXAMPLE_MULTI))
62 	{
63 		fprintf(fd, "  My Multi-Valued Doubles:");
64 		if (flags & TIFFPRINT_MYMULTIDOUBLES)
65 		{
66 			double *value = xd->xd_example_multi;
67 
68 			num = xd->xd_num_multi;
69 			fprintf(fd,"(");
70 			for (i=0;i<num;i++) fprintf(fd, " %lg", *value++);
71 			fprintf(fd,")\n");
72 		} else
73 			fprintf(fd, "(present)\n");
74 	}
75 
76 	if (TIFFFieldSet(tif,FIELD_EXAMPLE_SINGLE))
77 	{
78 		fprintf(fd, "  My Single Long Tag:  %lu\n", xd->xd_example_single);
79 	}
80 
81 	if (TIFFFieldSet(tif,FIELD_EXAMPLE_ASCII))
82 	{
83 		_TIFFprintAsciiTag(fd,"My ASCII Tag",
84 			 xd->xd_example_ascii);
85 	}
86 }
87 
88 static int
_XTIFFVSetField(TIFF * tif,ttag_t tag,va_list ap)89 _XTIFFVSetField(TIFF* tif, ttag_t tag, va_list ap)
90 {
91 	xtiff *xt = XTIFFDIR(tif);
92 	XTIFFDirectory* xd = &xt->xtif_dir;
93 	int status = 1;
94 	uint32 v32=0;
95 	int i=0, v=0;
96 	va_list ap1 = ap;
97 
98 	/* va_start is called by the calling routine */
99 
100 	switch (tag) {
101 		/*
102                  * XXX put your extended tags here; replace the implemented
103                  *     example tags with your own.
104                  */
105 	case TIFFTAG_EXAMPLE_MULTI:
106 		/* multi-valued tags need to store the count as well */
107 		xd->xd_num_multi = (uint16) va_arg(ap, int);
108 		_TIFFsetDoubleArray(&xd->xd_example_multi, va_arg(ap, double*),
109 			(long) xd->xd_num_multi);
110 		break;
111 	case TIFFTAG_EXAMPLE_SINGLE:
112 		xd->xd_example_single = va_arg(ap, uint32);
113 		break;
114 	case TIFFTAG_EXAMPLE_ASCII:
115 		_TIFFsetString(&xd->xd_example_ascii, va_arg(ap, char*));
116 		break;
117 	default:
118 		/* call the inherited method */
119 		return (PARENT(xt,vsetfield))(tif,tag,ap);
120 		break;
121 	}
122 	if (status) {
123 		/* we have to override the print method here,
124  		 * after the compression tags have gotten to it.
125 		 * This makes sense because the only time we would
126 		 * need the extended print method is if an extended
127 		 * tag is set by the reader.
128 		 */
129 		if (!(xt->xtif_flags & XTIFFP_PRINT))
130 		{
131 	        	PARENT(xt,printdir) =  TIFFMEMBER(tif,printdir);
132       		  	TIFFMEMBER(tif,printdir) = _XTIFFPrintDirectory;
133 			xt->xtif_flags |= XTIFFP_PRINT;
134 		}
135 		TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit);
136 		tif->tif_flags |= TIFF_DIRTYDIRECT;
137 	}
138 	va_end(ap);
139 	return (status);
140 badvalue:
141 	TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%d: Bad value for \"%s\"", v,
142 	    _TIFFFieldWithTag(tif, tag)->field_name);
143 	va_end(ap);
144 	return (0);
145 badvalue32:
146 	TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "%ld: Bad value for \"%s\"", v32,
147 	    _TIFFFieldWithTag(tif, tag)->field_name);
148 	va_end(ap);
149 	return (0);
150 }
151 
152 
153 static int
_XTIFFVGetField(TIFF * tif,ttag_t tag,va_list ap)154 _XTIFFVGetField(TIFF* tif, ttag_t tag, va_list ap)
155 {
156 	xtiff *xt = XTIFFDIR(tif);
157 	XTIFFDirectory* xd = &xt->xtif_dir;
158 
159 	switch (tag) {
160 		/*
161                  * XXX put your extended tags here; replace the implemented
162                  *     example tags with your own.
163                  */
164 	case TIFFTAG_EXAMPLE_MULTI:
165 		*va_arg(ap, uint16*) = xd->xd_num_multi;
166 		*va_arg(ap, double**) = xd->xd_example_multi;
167 		break;
168 	case TIFFTAG_EXAMPLE_ASCII:
169 		*va_arg(ap, char**) = xd->xd_example_ascii;
170 		break;
171 	case TIFFTAG_EXAMPLE_SINGLE:
172 		*va_arg(ap, uint32*) = xd->xd_example_single;
173 		break;
174 	default:
175 		/* return inherited method */
176 		return (PARENT(xt,vgetfield))(tif,tag,ap);
177 		break;
178 	}
179 	return (1);
180 }
181 
182 #define	CleanupField(member) {		\
183     if (xd->member) {			\
184 	_TIFFfree(xd->member);		\
185 	xd->member = 0;			\
186     }					\
187 }
188 /*
189  * Release storage associated with a directory.
190  */
191 static void
_XTIFFFreeDirectory(xtiff * xt)192 _XTIFFFreeDirectory(xtiff* xt)
193 {
194 	XTIFFDirectory* xd = &xt->xtif_dir;
195 
196 	/*
197 	 *  XXX - Purge all Your allocated memory except
198 	 *  for the xtiff directory itself. This includes
199 	 *  all fields that require a _TIFFsetXXX call in
200 	 *  _XTIFFVSetField().
201 	 */
202 
203 	CleanupField(xd_example_multi);
204 	CleanupField(xd_example_ascii);
205 
206 }
207 #undef CleanupField
208 
_XTIFFLocalDefaultDirectory(TIFF * tif)209 static void _XTIFFLocalDefaultDirectory(TIFF *tif)
210 {
211 	xtiff *xt = XTIFFDIR(tif);
212 	XTIFFDirectory* xd = &xt->xtif_dir;
213 
214 	/* Install the extended Tag field info */
215 	_TIFFMergeFieldInfo(tif, xtiffFieldInfo, N(xtiffFieldInfo));
216 
217 	/*
218 	 *  free up any dynamically allocated arrays
219 	 *  before the new directory is read in.
220 	 */
221 
222 	_XTIFFFreeDirectory(xt);
223 	_TIFFmemset(xt,0,sizeof(xtiff));
224 
225 	/* Override the tag access methods */
226 
227 	PARENT(xt,vsetfield) =  TIFFMEMBER(tif,vsetfield);
228 	TIFFMEMBER(tif,vsetfield) = _XTIFFVSetField;
229 	PARENT(xt,vgetfield) =  TIFFMEMBER(tif,vgetfield);
230 	TIFFMEMBER(tif,vgetfield) = _XTIFFVGetField;
231 
232 	/*
233 	 * XXX Set up any default values here.
234 	 */
235 
236 	xd->xd_example_single = 234;
237 }
238 
239 
240 
241 /**********************************************************************
242  *    Nothing below this line should need to be changed.
243  **********************************************************************/
244 
245 static TIFFExtendProc _ParentExtender;
246 
247 /*
248  *  This is the callback procedure, and is
249  *  called by the DefaultDirectory method
250  *  every time a new TIFF directory is opened.
251  */
252 
253 static void
_XTIFFDefaultDirectory(TIFF * tif)254 _XTIFFDefaultDirectory(TIFF *tif)
255 {
256 	xtiff *xt;
257 
258 	/* Allocate Directory Structure if first time, and install it */
259 	if (!(tif->tif_flags & XTIFF_INITIALIZED))
260 	{
261 		xt = _TIFFmalloc(sizeof(xtiff));
262 		if (!xt)
263 		{
264 			/* handle memory allocation failure here ! */
265 			return;
266 		}
267 		_TIFFmemset(xt,0,sizeof(xtiff));
268 		/*
269 		 * Install into TIFF structure.
270 		 */
271 		TIFFMEMBER(tif,clientdir) = (tidata_t)xt;
272 		tif->tif_flags |= XTIFF_INITIALIZED; /* dont do this again! */
273 	}
274 
275 	/* set up our own defaults */
276 	_XTIFFLocalDefaultDirectory(tif);
277 
278 	/* Since an XTIFF client module may have overridden
279 	 * the default directory method, we call it now to
280 	 * allow it to set up the rest of its own methods.
281          */
282 
283 	if (_ParentExtender)
284 		(*_ParentExtender)(tif);
285 
286 }
287 
288 /*
289  *  XTIFF Initializer -- sets up the callback
290  *   procedure for the TIFF module.
291  */
292 
293 static
_XTIFFInitialize(void)294 void _XTIFFInitialize(void)
295 {
296 	static first_time=1;
297 
298 	if (! first_time) return; /* Been there. Done that. */
299 	first_time = 0;
300 
301 	/* Grab the inherited method and install */
302 	_ParentExtender = TIFFSetTagExtender(_XTIFFDefaultDirectory);
303 }
304 
305 
306 /*
307  * Public File I/O Routines.
308  */
309 TIFF*
XTIFFOpen(const char * name,const char * mode)310 XTIFFOpen(const char* name, const char* mode)
311 {
312 	/* Set up the callback */
313 	_XTIFFInitialize();
314 
315 	/* Open the file; the callback will set everything up
316 	 */
317 	return TIFFOpen(name, mode);
318 }
319 
320 TIFF*
XTIFFFdOpen(int fd,const char * name,const char * mode)321 XTIFFFdOpen(int fd, const char* name, const char* mode)
322 {
323 	/* Set up the callback */
324 	_XTIFFInitialize();
325 
326 	/* Open the file; the callback will set everything up
327 	 */
328 	return TIFFFdOpen(fd, name, mode);
329 }
330 
331 
332 void
XTIFFClose(TIFF * tif)333 XTIFFClose(TIFF *tif)
334 {
335 	xtiff *xt = XTIFFDIR(tif);
336 
337 	/* call inherited function first */
338 	TIFFClose(tif);
339 
340 	/* Free up extended allocated memory */
341 	_XTIFFFreeDirectory(xt);
342 	_TIFFfree(xt);
343 }
344 /*
345  * Local Variables:
346  * mode: c
347  * c-basic-offset: 8
348  * fill-column: 78
349  * End:
350  */
351