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