1 : /**********************************************************************
2 : *
3 : * geo_set.c -- Public routines for GEOTIFF GeoKey access.
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 "geotiff.h" /* public interface */
15 : #include "geo_tiffp.h" /* external TIFF interface */
16 : #include "geo_keyp.h" /* private interface */
17 :
18 : #include <assert.h>
19 :
20 : /**
21 : This function writes a geokey_t value to a GeoTIFF file.
22 :
23 : @param gtif The geotiff information handle from GTIFNew().
24 :
25 : @param keyID The geokey_t name (such as ProjectedCSTypeGeoKey).
26 : This must come from the list of legal geokey_t values
27 : (an enumeration) listed below.
28 :
29 : @param val The <b>val</b> argument is a pointer to the
30 : variable into which the value should be read. The type of the variable
31 : varies depending on the geokey_t given. While there is no ready mapping
32 : of geokey_t values onto types, in general code values are of type <i>short</i>,
33 : citations are strings, and everything else is of type <i>double</i>. Note
34 : that pointer's to <i>int</i> should never be passed to GTIFKeyGet() for
35 : integer values as they will be shorts, and the int's may not be properly
36 : initialized (and will be grossly wrong on MSB systems).
37 :
38 : @param index Indicates how far into the list of values
39 : for this geokey to offset. Should normally be zero.
40 :
41 : @param count Indicates how many values
42 : to read. At this time all keys except for strings have only one value,
43 : so <b>index</b> should be zero, and <b>count</b> should be one.<p>
44 :
45 : The <b>key</b> indicates the key name to be written to the
46 : file and should from the geokey_t enumeration
47 : (eg. <tt>ProjectedCSTypeGeoKey</tt>). The full list of possible geokey_t
48 : values can be found in geokeys.inc, or in the online documentation for
49 : GTIFKeyGet().<p>
50 :
51 : The <b>type</b> should be one of TYPE_SHORT, TYPE_ASCII, or TYPE_DOUBLE and
52 : will indicate the type of value being passed at the end of the argument
53 : list (the key value). The <b>count</b> should be one except for strings
54 : when it should be the length of the string (or zero to for this to be
55 : computed internally). As a special case a <b>count</b> of -1 can be
56 : used to request an existing key be deleted, in which no value is passed.<p>
57 :
58 : The actual value is passed at the end of the argument list, and should be
59 : a short, a double, or a char * value. Note that short and double values
60 : are passed by value rather than as pointers when count is 1, but as pointers
61 : if count is larger than 1.<p>
62 :
63 : Note that key values aren't actually flushed to the file until
64 : GTIFWriteKeys() is called. Till then
65 : the new values are just kept with the GTIF structure.<p>
66 :
67 : <b>Example:</b><p>
68 :
69 : <pre>
70 : GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1,
71 : RasterPixelIsArea);
72 : GTIFKeySet(gtif, GTCitationGeoKey, TYPE_ASCII, 0,
73 : "UTM 11 North / NAD27" );
74 : </pre>
75 :
76 : */
77 :
78 6755 : int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
79 : {
80 : va_list ap;
81 6755 : int index = gtif->gt_keyindex[ keyID ];
82 6755 : int newvalues = 0;
83 : GeoKey *key;
84 6755 : char *data = NULL;
85 6755 : char *val = NULL;
86 : pinfo_t sval;
87 : double dval;
88 :
89 6755 : va_start(ap, count);
90 : /* pass singleton keys by value */
91 6780 : if (count>1 && type!=TYPE_ASCII)
92 : {
93 25 : val = va_arg(ap, char*);
94 : }
95 6730 : else if( count == -1 )
96 : {
97 : /* delete the indicated tag */
98 0 : va_end(ap);
99 :
100 0 : if( index < 1 )
101 0 : return 0;
102 :
103 0 : if (gtif->gt_keys[index].gk_type == TYPE_ASCII)
104 : {
105 0 : _GTIFFree (gtif->gt_keys[index].gk_data);
106 : }
107 :
108 0 : while( index < gtif->gt_num_keys )
109 : {
110 0 : _GTIFmemcpy( gtif->gt_keys + index,
111 0 : gtif->gt_keys + index + 1,
112 : sizeof(GeoKey) );
113 0 : gtif->gt_keyindex[gtif->gt_keys[index].gk_key] = index;
114 0 : index++;
115 : }
116 :
117 0 : gtif->gt_num_keys--;
118 0 : gtif->gt_nshorts -= sizeof(KeyEntry)/sizeof(pinfo_t);
119 0 : gtif->gt_keyindex[keyID] = 0;
120 0 : gtif->gt_flags |= FLAG_FILE_MODIFIED;
121 :
122 0 : return 1;
123 : }
124 6730 : else switch (type)
125 : {
126 3972 : case TYPE_SHORT: sval=(pinfo_t) va_arg(ap, int); val=(char *)&sval; break;
127 1599 : case TYPE_DOUBLE: dval=va_arg(ap, dblparam_t); val=(char *)&dval; break;
128 : case TYPE_ASCII:
129 1159 : val=va_arg(ap, char*);
130 1159 : count = strlen(val) + 1; /* force = string length */
131 1159 : break;
132 : default:
133 0 : assert( FALSE );
134 : break;
135 : }
136 6755 : va_end(ap);
137 :
138 : /* We assume here that there are no multi-valued SHORTS ! */
139 6755 : if (index)
140 : {
141 : /* Key already exists */
142 80 : key = gtif->gt_keys+index;
143 80 : if (type!=key->gk_type || count > key->gk_count)
144 : {
145 : /* need to reset data pointer */
146 25 : key->gk_type = type;
147 25 : key->gk_count = count;
148 25 : key->gk_size = _gtiff_size[ type ];
149 25 : newvalues = 1;
150 : }
151 : }
152 : else
153 : {
154 : /* We need to create the key */
155 6675 : if (gtif->gt_num_keys == MAX_KEYS) return 0;
156 6675 : key = gtif->gt_keys + ++gtif->gt_num_keys;
157 6675 : index = gtif->gt_num_keys;
158 6675 : gtif->gt_keyindex[ keyID ] = index;
159 6675 : key->gk_key = keyID;
160 6675 : key->gk_type = type;
161 6675 : key->gk_count = count;
162 6675 : key->gk_size = _gtiff_size[ type ];
163 6675 : if (gtif->gt_keymin > keyID) gtif->gt_keymin=keyID;
164 6675 : if (gtif->gt_keymax < keyID) gtif->gt_keymax=keyID;
165 6675 : newvalues = 1;
166 : }
167 :
168 6755 : if (newvalues)
169 : {
170 6700 : switch (type)
171 : {
172 : case TYPE_SHORT:
173 3962 : if (count > 1) return 0;
174 3962 : data = (char *)&key->gk_data; /* store value *in* data */
175 3962 : break;
176 : case TYPE_DOUBLE:
177 1579 : key->gk_data = (char *)(gtif->gt_double + gtif->gt_ndoubles);
178 1579 : data = key->gk_data;
179 1579 : gtif->gt_ndoubles += count;
180 1579 : break;
181 : case TYPE_ASCII:
182 1159 : break;
183 : default:
184 0 : va_end(ap);
185 0 : return 0;
186 : }
187 6700 : gtif->gt_nshorts += sizeof(KeyEntry)/sizeof(pinfo_t);
188 : }
189 :
190 : /* this fixes a bug where if a request is made to write a duplicate
191 : key, we must initialize the data to a valid value.
192 : Bryan Wells (bryan@athena.bangor.autometric.com) */
193 :
194 : else /* no new values, but still have something to write */
195 : {
196 55 : switch (type)
197 : {
198 : case TYPE_SHORT:
199 10 : if (count > 1) return 0;
200 10 : data = (char *)&key->gk_data; /* store value *in* data */
201 10 : break;
202 : case TYPE_DOUBLE:
203 45 : data = key->gk_data;
204 45 : break;
205 : case TYPE_ASCII:
206 0 : break;
207 : default:
208 0 : return 0;
209 : }
210 : }
211 :
212 6755 : switch (type)
213 : {
214 : case TYPE_ASCII:
215 : /* throw away existing data and allocate room for new data */
216 1159 : if (key->gk_data != 0)
217 : {
218 25 : _GTIFFree(key->gk_data);
219 : }
220 1159 : key->gk_data = (char *)_GTIFcalloc(count);
221 1159 : key->gk_count = count;
222 1159 : data = key->gk_data;
223 : break;
224 : default:
225 : break;
226 : }
227 :
228 6755 : _GTIFmemcpy(data, val, count*key->gk_size);
229 :
230 6755 : gtif->gt_flags |= FLAG_FILE_MODIFIED;
231 6755 : return 1;
232 : }
|