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