1 : /**********************************************************************
2 : *
3 : * geo_print.c -- Key-dumping routines for GEOTIFF files.
4 : *
5 : * Written By: Niles D. Ritter.
6 : *
7 : * copyright (c) 1995 Niles D. Ritter
8 : *
9 : * Permission granted to use this software, so long as this copyright
10 : * notice accompanies any products derived therefrom.
11 : *
12 : * Revision History;
13 : *
14 : * 20 June, 1995 Niles D. Ritter New
15 : * 7 July, 1995 NDR Fix indexing
16 : * 27 July, 1995 NDR Added Import utils
17 : * 28 July, 1995 NDR Made parser more strict.
18 : * 29 Sep, 1995 NDR Fixed matrix printing.
19 : *
20 : **********************************************************************/
21 :
22 : #include "geotiff.h" /* public interface */
23 : #include "geo_tiffp.h" /* external TIFF interface */
24 : #include "geo_keyp.h" /* private interface */
25 : #include "geokeys.h"
26 :
27 : #include <stdio.h> /* for sprintf */
28 :
29 : #define FMT_GEOTIFF "Geotiff_Information:"
30 : #define FMT_VERSION "Version: %hd"
31 : #define FMT_REV "Key_Revision: %1hd.%hd"
32 : #define FMT_TAGS "Tagged_Information:"
33 : #define FMT_TAGEND "End_Of_Tags."
34 : #define FMT_KEYS "Keyed_Information:"
35 : #define FMT_KEYEND "End_Of_Keys."
36 : #define FMT_GEOEND "End_Of_Geotiff."
37 : #define FMT_DOUBLE "%-17.15g"
38 : #define FMT_SHORT "%-11hd"
39 :
40 : static void DefaultPrint(char *string, void *aux);
41 : static void PrintKey(GeoKey *key, GTIFPrintMethod print,void *aux);
42 : static void PrintGeoTags(GTIF *gtif,GTIFReadMethod scan,void *aux);
43 : static void PrintTag(int tag, int nrows, double *data, int ncols,
44 : GTIFPrintMethod print,void *aux);
45 : static void DefaultRead(char *string, void *aux);
46 : static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux);
47 : static int ReadTag(GTIF *gt,GTIFReadMethod scan,void *aux);
48 :
49 : /*
50 : * Print off the directory info, using whatever method is specified
51 : * (defaults to fprintf if null). The "aux" parameter is provided for user
52 : * defined method for passing parameters or whatever.
53 : *
54 : * The output format is a "GeoTIFF meta-data" file, which may be
55 : * used to import information with the GTIFFImport() routine.
56 : */
57 :
58 0 : void GTIFPrint(GTIF *gtif, GTIFPrintMethod print,void *aux)
59 : {
60 : int i;
61 0 : int numkeys = gtif->gt_num_keys;
62 0 : GeoKey *key = gtif->gt_keys;
63 : char message[1024];
64 :
65 0 : if (!print) print = (GTIFPrintMethod) &DefaultPrint;
66 0 : if (!aux) aux=stdout;
67 :
68 0 : sprintf(message,FMT_GEOTIFF "\n");
69 0 : print(message,aux);
70 0 : sprintf(message, "Version: %hd" ,gtif->gt_version);
71 0 : sprintf(message, FMT_VERSION,gtif->gt_version);
72 0 : print(" ",aux); print(message,aux); print("\n",aux);
73 0 : sprintf(message, FMT_REV,gtif->gt_rev_major,
74 0 : gtif->gt_rev_minor);
75 0 : print(" ",aux); print(message,aux); print("\n",aux);
76 :
77 0 : sprintf(message," %s\n",FMT_TAGS); print(message,aux);
78 0 : PrintGeoTags(gtif,print,aux);
79 0 : sprintf(message," %s\n",FMT_TAGEND); print(message,aux);
80 :
81 0 : sprintf(message," %s\n",FMT_KEYS); print(message,aux);
82 0 : for (i=0; i<numkeys; i++)
83 0 : PrintKey(++key,print,aux);
84 0 : sprintf(message," %s\n",FMT_KEYEND); print(message,aux);
85 :
86 0 : sprintf(message," %s\n",FMT_GEOEND); print(message,aux);
87 0 : }
88 :
89 0 : static void PrintGeoTags(GTIF *gt, GTIFPrintMethod print,void *aux)
90 : {
91 : double *data;
92 : int count;
93 0 : tiff_t *tif=gt->gt_tif;
94 :
95 0 : if( tif == NULL )
96 0 : return;
97 :
98 0 : if ((gt->gt_methods.get)(tif, GTIFF_TIEPOINTS, &count, &data ))
99 0 : PrintTag(GTIFF_TIEPOINTS,count/3, data, 3, print, aux);
100 0 : if ((gt->gt_methods.get)(tif, GTIFF_PIXELSCALE, &count, &data ))
101 0 : PrintTag(GTIFF_PIXELSCALE,count/3, data, 3, print, aux);
102 0 : if ((gt->gt_methods.get)(tif, GTIFF_TRANSMATRIX, &count, &data ))
103 0 : PrintTag(GTIFF_TRANSMATRIX,count/4, data, 4, print, aux);
104 : }
105 :
106 0 : static void PrintTag(int tag, int nrows, double *dptr, int ncols,
107 : GTIFPrintMethod print,void *aux)
108 : {
109 : int i,j;
110 0 : double *data=dptr;
111 : char message[1024];
112 :
113 0 : print(" ",aux);
114 0 : print(GTIFTagName(tag),aux);
115 0 : sprintf(message," (%d,%d):\n",nrows,ncols);
116 0 : print(message,aux);
117 0 : for (i=0;i<nrows;i++)
118 : {
119 0 : print(" ",aux);
120 0 : for (j=0;j<ncols;j++)
121 : {
122 0 : sprintf(message,FMT_DOUBLE,*data++);
123 0 : print(message,aux);
124 :
125 0 : if( j < ncols-1 )
126 0 : print(" ",aux);
127 : }
128 0 : print("\n",aux);
129 : }
130 0 : _GTIFFree(dptr); /* free up the allocated memory */
131 0 : }
132 :
133 :
134 0 : static void PrintKey(GeoKey *key, GTIFPrintMethod print, void *aux)
135 : {
136 : char *data;
137 0 : geokey_t keyid = (geokey_t) key->gk_key;
138 0 : int count = key->gk_count;
139 : int vals_now,i;
140 : pinfo_t *sptr;
141 : double *dptr;
142 : char message[40];
143 :
144 0 : print(" ",aux);
145 0 : print(GTIFKeyName(keyid),aux);
146 :
147 0 : sprintf(message," (%s,%d): ",GTIFTypeName(key->gk_type),count);
148 0 : print(message,aux);
149 :
150 0 : if (key->gk_type==TYPE_SHORT && count==1)
151 0 : data = (char *)&key->gk_data;
152 : else
153 0 : data = key->gk_data;
154 :
155 0 : switch (key->gk_type)
156 : {
157 : case TYPE_ASCII:
158 : {
159 : int in_char, out_char;
160 :
161 0 : print("\"",aux);
162 :
163 0 : in_char = 0;
164 0 : out_char = 0;
165 0 : while( in_char < count-1 )
166 : {
167 0 : char ch = ((char *) data)[in_char++];
168 :
169 0 : if( ch == '\n' )
170 : {
171 0 : message[out_char++] = '\\';
172 0 : message[out_char++] = 'n';
173 : }
174 0 : else if( ch == '\\' )
175 : {
176 0 : message[out_char++] = '\\';
177 0 : message[out_char++] = '\\';
178 : }
179 : else
180 0 : message[out_char++] = ch;
181 :
182 : /* flush message if buffer full */
183 0 : if( out_char >= sizeof(message)-3 )
184 : {
185 0 : message[out_char] = '\0';
186 0 : print(message,aux);
187 0 : out_char = 0;
188 : }
189 : }
190 :
191 0 : message[out_char]='\0';
192 0 : print(message,aux);
193 :
194 0 : print("\"\n",aux);
195 : }
196 0 : break;
197 :
198 : case TYPE_DOUBLE:
199 0 : for (dptr = (double *)data; count > 0; count-= vals_now)
200 : {
201 0 : vals_now = count > 3? 3: count;
202 0 : for (i=0; i<vals_now; i++,dptr++)
203 : {
204 0 : sprintf(message,FMT_DOUBLE ,*dptr);
205 0 : print(message,aux);
206 : }
207 0 : print("\n",aux);
208 : }
209 0 : break;
210 :
211 : case TYPE_SHORT:
212 0 : sptr = (pinfo_t *)data;
213 0 : if (count==1)
214 : {
215 0 : print( GTIFValueName(keyid,*sptr), aux );
216 0 : print( "\n", aux );
217 : }
218 : else
219 0 : for (; count > 0; count-= vals_now)
220 : {
221 0 : vals_now = count > 3? 3: count;
222 0 : for (i=0; i<vals_now; i++,sptr++)
223 : {
224 0 : sprintf(message,FMT_SHORT,*sptr);
225 0 : print(message,aux);
226 : }
227 0 : print("\n",aux);
228 : }
229 0 : break;
230 :
231 : default:
232 0 : sprintf(message, "Unknown Type (%d)\n",key->gk_type);
233 0 : print(message,aux);
234 : break;
235 : }
236 0 : }
237 :
238 0 : static void DefaultPrint(char *string, void *aux)
239 : {
240 : /* Pretty boring */
241 0 : fprintf((FILE *)aux,"%s",string);
242 0 : }
243 :
244 :
245 : /*
246 : * Importing metadata file
247 : */
248 :
249 : /*
250 : * Import the directory info, using whatever method is specified
251 : * (defaults to fscanf if null). The "aux" parameter is provided for user
252 : * defined method for passing file or whatever.
253 : *
254 : * The input format is a "GeoTIFF meta-data" file, which may be
255 : * generated by the GTIFFPrint() routine.
256 : */
257 :
258 0 : int GTIFImport(GTIF *gtif, GTIFReadMethod scan,void *aux)
259 : {
260 : int status;
261 : char message[1024];
262 :
263 0 : if (!scan) scan = (GTIFReadMethod) &DefaultRead;
264 0 : if (!aux) aux=stdin;
265 :
266 0 : scan(message,aux);
267 0 : if (strncmp(message,FMT_GEOTIFF,8)) return 0;
268 0 : scan(message,aux);
269 0 : if (!sscanf(message,FMT_VERSION,(short int*)>if->gt_version)) return 0;
270 0 : scan(message,aux);
271 0 : if (sscanf(message,FMT_REV,(short int*)>if->gt_rev_major,
272 0 : (short int*)>if->gt_rev_minor) !=2) return 0;
273 :
274 0 : scan(message,aux);
275 0 : if (strncmp(message,FMT_TAGS,8)) return 0;
276 0 : while ((status=ReadTag(gtif,scan,aux))>0);
277 0 : if (status < 0) return 0;
278 :
279 0 : scan(message,aux);
280 0 : if (strncmp(message,FMT_KEYS,8)) return 0;
281 0 : while ((status=ReadKey(gtif,scan,aux))>0);
282 :
283 0 : return (status==0); /* success */
284 : }
285 :
286 0 : static int StringError(char *string)
287 : {
288 0 : fprintf(stderr,"Parsing Error at \'%s\'\n",string);
289 0 : return -1;
290 : }
291 :
292 : #define SKIPWHITE(vptr) \
293 : while (*vptr && (*vptr==' '||*vptr=='\t')) vptr++
294 : #define FINDCHAR(vptr,c) \
295 : while (*vptr && *vptr!=(c)) vptr++
296 :
297 0 : static int ReadTag(GTIF *gt,GTIFReadMethod scan,void *aux)
298 : {
299 : int i,j,tag;
300 : char *vptr;
301 : char tagname[100];
302 : double *data,*dptr;
303 : int count,nrows,ncols,num;
304 : char message[1024];
305 :
306 0 : scan(message,aux);
307 0 : if (!strncmp(message,FMT_TAGEND,8)) return 0;
308 :
309 0 : num=sscanf(message,"%[^( ] (%d,%d):\n",tagname,&nrows,&ncols);
310 0 : if (num!=3) return StringError(message);
311 :
312 0 : tag = GTIFTagCode(tagname);
313 0 : if (tag < 0) return StringError(tagname);
314 :
315 0 : count = nrows*ncols;
316 :
317 0 : data = (double *) _GTIFcalloc(count * sizeof(double));
318 0 : dptr = data;
319 :
320 0 : for (i=0;i<nrows;i++)
321 : {
322 0 : scan(message,aux);
323 0 : vptr = message;
324 0 : for (j=0;j<ncols;j++)
325 : {
326 0 : if (!sscanf(vptr,"%lg",dptr++))
327 0 : return StringError(vptr);
328 0 : FINDCHAR(vptr,' ');
329 0 : SKIPWHITE(vptr);
330 : }
331 : }
332 0 : (gt->gt_methods.set)(gt->gt_tif, (pinfo_t) tag, count, data );
333 :
334 0 : _GTIFFree( data );
335 :
336 0 : return 1;
337 : }
338 :
339 :
340 0 : static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux)
341 : {
342 : tagtype_t ktype;
343 : int count,outcount;
344 : int vals_now,i;
345 : geokey_t key;
346 : int icode;
347 : pinfo_t code;
348 : short *sptr;
349 : char name[1000];
350 : char type[20];
351 : double data[100];
352 : double *dptr;
353 : char *vptr;
354 : int num;
355 : char message[2048];
356 :
357 0 : scan(message,aux);
358 0 : if (!strncmp(message,FMT_KEYEND,8)) return 0;
359 :
360 0 : num=sscanf(message,"%[^( ] (%[^,],%d):\n",name,type,&count);
361 0 : if (num!=3) return StringError(message);
362 :
363 0 : vptr = message;
364 0 : FINDCHAR(vptr,':');
365 0 : if (!*vptr) return StringError(message);
366 0 : vptr+=2;
367 :
368 0 : if( GTIFKeyCode(name) < 0 )
369 0 : return StringError(name);
370 : else
371 0 : key = (geokey_t) GTIFKeyCode(name);
372 :
373 0 : if( GTIFTypeCode(type) < 0 )
374 0 : return StringError(type);
375 : else
376 0 : ktype = (tagtype_t) GTIFTypeCode(type);
377 :
378 : /* skip white space */
379 0 : SKIPWHITE(vptr);
380 0 : if (!*vptr) return StringError(message);
381 :
382 0 : switch (ktype)
383 : {
384 : case TYPE_ASCII:
385 : {
386 : char *cdata;
387 0 : int out_char = 0;
388 :
389 0 : FINDCHAR(vptr,'"');
390 0 : if (!*vptr) return StringError(message);
391 :
392 0 : cdata = (char *) _GTIFcalloc( count+1 );
393 :
394 0 : vptr++;
395 0 : while( out_char < count-1 )
396 : {
397 0 : if( *vptr == '\0' )
398 0 : break;
399 :
400 0 : else if( vptr[0] == '\\' && vptr[1] == 'n' )
401 : {
402 0 : cdata[out_char++] = '\n';
403 0 : vptr += 2;
404 : }
405 0 : else if( vptr[0] == '\\' && vptr[1] == '\\' )
406 : {
407 0 : cdata[out_char++] = '\\';
408 0 : vptr += 2;
409 : }
410 : else
411 0 : cdata[out_char++] = *(vptr++);
412 : }
413 :
414 0 : if( out_char < count-1 ) return StringError(message);
415 0 : if( *vptr != '"' ) return StringError(message);
416 :
417 0 : cdata[count-1] = '\0';
418 0 : GTIFKeySet(gt,key,ktype,count,cdata);
419 :
420 0 : _GTIFFree( cdata );
421 : }
422 0 : break;
423 :
424 : case TYPE_DOUBLE:
425 0 : outcount = count;
426 0 : for (dptr = data; count > 0; count-= vals_now)
427 : {
428 0 : vals_now = count > 3? 3: count;
429 0 : for (i=0; i<vals_now; i++,dptr++)
430 : {
431 0 : if (!sscanf(vptr,"%lg" ,dptr))
432 0 : StringError(vptr);
433 0 : FINDCHAR(vptr,' ');
434 0 : SKIPWHITE(vptr);
435 : }
436 0 : if (vals_now<count)
437 : {
438 0 : scan(message,aux);
439 0 : vptr = message;
440 : }
441 : }
442 0 : if (outcount==1)
443 0 : GTIFKeySet(gt,key,ktype,outcount,data[0]);
444 : else
445 0 : GTIFKeySet(gt,key,ktype,outcount,data);
446 0 : break;
447 :
448 : case TYPE_SHORT:
449 0 : if (count==1)
450 : {
451 0 : icode = GTIFValueCode(key,vptr);
452 0 : if (icode < 0) return StringError(vptr);
453 0 : code = (pinfo_t) icode;
454 0 : GTIFKeySet(gt,key,ktype,count,code);
455 : }
456 : else /* multi-valued short - no such thing yet */
457 : {
458 0 : sptr = (short *)data;
459 0 : outcount = count;
460 0 : for (; count > 0; count-= vals_now)
461 : {
462 0 : vals_now = count > 3? 3: count;
463 0 : for (i=0; i<vals_now; i++,sptr++)
464 : {
465 : int work_int;
466 :
467 : /* note: FMT_SHORT (%11hd) not supported on IRIX */
468 0 : sscanf(message,"%11d",&work_int);
469 0 : *sptr = (short) work_int;
470 0 : scan(message,aux);
471 : }
472 0 : if (vals_now<count)
473 : {
474 0 : scan(message,aux);
475 0 : vptr = message;
476 : }
477 : }
478 0 : GTIFKeySet(gt,key,ktype,outcount,sptr);
479 : }
480 0 : break;
481 :
482 : default:
483 0 : return -1;
484 : }
485 0 : return 1;
486 : }
487 :
488 :
489 0 : static void DefaultRead(char *string, void *aux)
490 : {
491 : /* Pretty boring */
492 0 : fscanf((FILE *)aux,"%[^\n]\n",string);
493 0 : }
494 :
|