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 : print("\n",aux);
126 : }
127 0 : _GTIFFree(dptr); /* free up the allocated memory */
128 0 : }
129 :
130 :
131 0 : static void PrintKey(GeoKey *key, GTIFPrintMethod print, void *aux)
132 : {
133 : char *data;
134 0 : geokey_t keyid = (geokey_t) key->gk_key;
135 0 : int count = key->gk_count;
136 : int vals_now,i;
137 : pinfo_t *sptr;
138 : double *dptr;
139 : char message[40];
140 :
141 0 : print(" ",aux);
142 0 : print(GTIFKeyName(keyid),aux);
143 :
144 0 : sprintf(message," (%s,%d): ",GTIFTypeName(key->gk_type),count);
145 0 : print(message,aux);
146 :
147 0 : if (key->gk_type==TYPE_SHORT && count==1)
148 0 : data = (char *)&key->gk_data;
149 : else
150 0 : data = key->gk_data;
151 :
152 0 : switch (key->gk_type)
153 : {
154 : case TYPE_ASCII:
155 : {
156 : int in_char, out_char;
157 :
158 0 : print("\"",aux);
159 :
160 0 : in_char = 0;
161 0 : out_char = 0;
162 0 : while( in_char < count-1 )
163 : {
164 0 : char ch = ((char *) data)[in_char++];
165 :
166 0 : if( ch == '\n' )
167 : {
168 0 : message[out_char++] = '\\';
169 0 : message[out_char++] = 'n';
170 : }
171 0 : else if( ch == '\\' )
172 : {
173 0 : message[out_char++] = '\\';
174 0 : message[out_char++] = '\\';
175 : }
176 : else
177 0 : message[out_char++] = ch;
178 :
179 : /* flush message if buffer full */
180 0 : if( out_char >= sizeof(message)-3 )
181 : {
182 0 : message[out_char] = '\0';
183 0 : print(message,aux);
184 0 : out_char = 0;
185 : }
186 : }
187 :
188 0 : message[out_char]='\0';
189 0 : print(message,aux);
190 :
191 0 : print("\"\n",aux);
192 : }
193 0 : break;
194 :
195 : case TYPE_DOUBLE:
196 0 : for (dptr = (double *)data; count > 0; count-= vals_now)
197 : {
198 0 : vals_now = count > 3? 3: count;
199 0 : for (i=0; i<vals_now; i++,dptr++)
200 : {
201 0 : sprintf(message,FMT_DOUBLE ,*dptr);
202 0 : print(message,aux);
203 : }
204 0 : print("\n",aux);
205 : }
206 0 : break;
207 :
208 : case TYPE_SHORT:
209 0 : sptr = (pinfo_t *)data;
210 0 : if (count==1)
211 : {
212 0 : print( GTIFValueName(keyid,*sptr), aux );
213 0 : print( "\n", aux );
214 : }
215 : else
216 0 : for (; count > 0; count-= vals_now)
217 : {
218 0 : vals_now = count > 3? 3: count;
219 0 : for (i=0; i<vals_now; i++,sptr++)
220 : {
221 0 : sprintf(message,FMT_SHORT,*sptr);
222 0 : print(message,aux);
223 : }
224 0 : print("\n",aux);
225 : }
226 0 : break;
227 :
228 : default:
229 0 : sprintf(message, "Unknown Type (%d)\n",key->gk_type);
230 0 : print(message,aux);
231 : break;
232 : }
233 0 : }
234 :
235 0 : static void DefaultPrint(char *string, void *aux)
236 : {
237 : /* Pretty boring */
238 0 : fprintf((FILE *)aux,"%s",string);
239 0 : }
240 :
241 :
242 : /*
243 : * Importing metadata file
244 : */
245 :
246 : /*
247 : * Import the directory info, using whatever method is specified
248 : * (defaults to fscanf if null). The "aux" parameter is provided for user
249 : * defined method for passing file or whatever.
250 : *
251 : * The input format is a "GeoTIFF meta-data" file, which may be
252 : * generated by the GTIFFPrint() routine.
253 : */
254 :
255 0 : int GTIFImport(GTIF *gtif, GTIFReadMethod scan,void *aux)
256 : {
257 : int status;
258 : char message[1024];
259 :
260 0 : if (!scan) scan = (GTIFReadMethod) &DefaultRead;
261 0 : if (!aux) aux=stdin;
262 :
263 0 : scan(message,aux);
264 0 : if (strncmp(message,FMT_GEOTIFF,8)) return 0;
265 0 : scan(message,aux);
266 0 : if (!sscanf(message,FMT_VERSION,>if->gt_version)) return 0;
267 0 : scan(message,aux);
268 0 : if (sscanf(message,FMT_REV,>if->gt_rev_major,
269 0 : >if->gt_rev_minor) !=2) return 0;
270 :
271 0 : scan(message,aux);
272 0 : if (strncmp(message,FMT_TAGS,8)) return 0;
273 0 : while ((status=ReadTag(gtif,scan,aux))>0);
274 0 : if (status < 0) return 0;
275 :
276 0 : scan(message,aux);
277 0 : if (strncmp(message,FMT_KEYS,8)) return 0;
278 0 : while ((status=ReadKey(gtif,scan,aux))>0);
279 :
280 0 : return (status==0); /* success */
281 : }
282 :
283 0 : static int StringError(char *string)
284 : {
285 0 : fprintf(stderr,"Parsing Error at \'%s\'\n",string);
286 0 : return -1;
287 : }
288 :
289 : #define SKIPWHITE(vptr) \
290 : while (*vptr && (*vptr==' '||*vptr=='\t')) vptr++
291 : #define FINDCHAR(vptr,c) \
292 : while (*vptr && *vptr!=(c)) vptr++
293 :
294 0 : static int ReadTag(GTIF *gt,GTIFReadMethod scan,void *aux)
295 : {
296 : int i,j,tag;
297 : char *vptr;
298 : char tagname[100];
299 : double *data,*dptr;
300 : int count,nrows,ncols,num;
301 : char message[1024];
302 :
303 0 : scan(message,aux);
304 0 : if (!strncmp(message,FMT_TAGEND,8)) return 0;
305 :
306 0 : num=sscanf(message,"%[^( ] (%d,%d):\n",tagname,&nrows,&ncols);
307 0 : if (num!=3) return StringError(message);
308 :
309 0 : tag = GTIFTagCode(tagname);
310 0 : if (tag < 0) return StringError(tagname);
311 :
312 0 : count = nrows*ncols;
313 :
314 0 : data = (double *) _GTIFcalloc(count * sizeof(double));
315 0 : dptr = data;
316 :
317 0 : for (i=0;i<nrows;i++)
318 : {
319 0 : scan(message,aux);
320 0 : vptr = message;
321 0 : for (j=0;j<ncols;j++)
322 : {
323 0 : if (!sscanf(vptr,"%lg",dptr++))
324 0 : return StringError(vptr);
325 0 : FINDCHAR(vptr,' ');
326 0 : SKIPWHITE(vptr);
327 : }
328 : }
329 0 : (gt->gt_methods.set)(gt->gt_tif, (pinfo_t) tag, count, data );
330 :
331 0 : _GTIFFree( data );
332 :
333 0 : return 1;
334 : }
335 :
336 :
337 0 : static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux)
338 : {
339 : tagtype_t ktype;
340 : int count,outcount;
341 : int vals_now,i;
342 : geokey_t key;
343 : int icode;
344 : pinfo_t code;
345 : short *sptr;
346 : char name[1000];
347 : char type[20];
348 : double data[100];
349 : double *dptr;
350 : char *vptr;
351 : int num;
352 : char message[2048];
353 :
354 0 : scan(message,aux);
355 0 : if (!strncmp(message,FMT_KEYEND,8)) return 0;
356 :
357 0 : num=sscanf(message,"%[^( ] (%[^,],%d):\n",name,type,&count);
358 0 : if (num!=3) return StringError(message);
359 :
360 0 : vptr = message;
361 0 : FINDCHAR(vptr,':');
362 0 : if (!*vptr) return StringError(message);
363 0 : vptr+=2;
364 :
365 0 : if( GTIFKeyCode(name) < 0 )
366 0 : return StringError(name);
367 : else
368 0 : key = (geokey_t) GTIFKeyCode(name);
369 :
370 0 : if( GTIFTypeCode(type) < 0 )
371 0 : return StringError(type);
372 : else
373 0 : ktype = (tagtype_t) GTIFTypeCode(type);
374 :
375 : /* skip white space */
376 0 : SKIPWHITE(vptr);
377 0 : if (!*vptr) return StringError(message);
378 :
379 0 : switch (ktype)
380 : {
381 : case TYPE_ASCII:
382 : {
383 : char *cdata;
384 0 : int out_char = 0;
385 :
386 0 : FINDCHAR(vptr,'"');
387 0 : if (!*vptr) return StringError(message);
388 :
389 0 : cdata = (char *) _GTIFcalloc( count+1 );
390 :
391 0 : vptr++;
392 0 : while( out_char < count-1 )
393 : {
394 0 : if( *vptr == '\0' )
395 0 : break;
396 :
397 0 : else if( vptr[0] == '\\' && vptr[1] == 'n' )
398 : {
399 0 : cdata[out_char++] = '\n';
400 0 : vptr += 2;
401 : }
402 0 : else if( vptr[0] == '\\' && vptr[1] == '\\' )
403 : {
404 0 : cdata[out_char++] = '\\';
405 0 : vptr += 2;
406 : }
407 : else
408 0 : cdata[out_char++] = *(vptr++);
409 : }
410 :
411 0 : if( out_char < count-1 ) return StringError(message);
412 0 : if( *vptr != '"' ) return StringError(message);
413 :
414 0 : cdata[count-1] = '\0';
415 0 : GTIFKeySet(gt,key,ktype,count,cdata);
416 :
417 0 : _GTIFFree( cdata );
418 : }
419 0 : break;
420 :
421 : case TYPE_DOUBLE:
422 0 : outcount = count;
423 0 : for (dptr = data; count > 0; count-= vals_now)
424 : {
425 0 : vals_now = count > 3? 3: count;
426 0 : for (i=0; i<vals_now; i++,dptr++)
427 : {
428 0 : if (!sscanf(vptr,"%lg" ,dptr))
429 0 : StringError(vptr);
430 0 : FINDCHAR(vptr,' ');
431 0 : SKIPWHITE(vptr);
432 : }
433 0 : if (vals_now<count)
434 : {
435 0 : scan(message,aux);
436 0 : vptr = message;
437 : }
438 : }
439 0 : if (outcount==1)
440 0 : GTIFKeySet(gt,key,ktype,outcount,data[0]);
441 : else
442 0 : GTIFKeySet(gt,key,ktype,outcount,data);
443 0 : break;
444 :
445 : case TYPE_SHORT:
446 0 : if (count==1)
447 : {
448 0 : icode = GTIFValueCode(key,vptr);
449 0 : if (icode < 0) return StringError(vptr);
450 0 : code = (pinfo_t) icode;
451 0 : GTIFKeySet(gt,key,ktype,count,code);
452 : }
453 : else /* multi-valued short - no such thing yet */
454 : {
455 0 : sptr = (short *)data;
456 0 : outcount = count;
457 0 : for (; count > 0; count-= vals_now)
458 : {
459 0 : vals_now = count > 3? 3: count;
460 0 : for (i=0; i<vals_now; i++,sptr++)
461 : {
462 : int work_int;
463 :
464 : /* note: FMT_SHORT (%11hd) not supported on IRIX */
465 0 : sscanf(message,"%11d",&work_int);
466 0 : *sptr = (short) work_int;
467 0 : scan(message,aux);
468 : }
469 0 : if (vals_now<count)
470 : {
471 0 : scan(message,aux);
472 0 : vptr = message;
473 : }
474 : }
475 0 : GTIFKeySet(gt,key,ktype,outcount,sptr);
476 : }
477 0 : break;
478 :
479 : default:
480 0 : return -1;
481 : }
482 0 : return 1;
483 : }
484 :
485 :
486 0 : static void DefaultRead(char *string, void *aux)
487 : {
488 : /* Pretty boring */
489 0 : fscanf((FILE *)aux,"%[^\n]\n",string);
490 0 : }
491 :
|