Line data Source code
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 <assert.h> 15 : #include <stdarg.h> 16 : #include <string.h> 17 : 18 : #include "geotiff.h" /* public interface */ 19 : #include "geo_tiffp.h" /* external TIFF interface */ 20 : #include "geo_keyp.h" /* private interface */ 21 : 22 : /** 23 : This function writes a geokey_t value to a GeoTIFF file. 24 : 25 : @param gtif The geotiff information handle from GTIFNew(). 26 : 27 : @param keyID The geokey_t name (such as ProjectedCSTypeGeoKey). 28 : This must come from the list of legal geokey_t values 29 : (an enumeration) listed below. 30 : 31 : @param type Type of the key. 32 : 33 : @param count Indicates how many values 34 : to read. At this time all keys except for strings have only one value, 35 : so <b>index</b> should be zero, and <b>count</b> should be one.<p> 36 : 37 : The <b>keyID</b> indicates the key name to be written to the 38 : file and should from the geokey_t enumeration 39 : (eg. <tt>ProjectedCSTypeGeoKey</tt>). The full list of possible geokey_t 40 : values can be found in geokeys.inc, or in the online documentation for 41 : GTIFKeyGet().<p> 42 : 43 : The <b>type</b> should be one of TYPE_SHORT, TYPE_ASCII, or TYPE_DOUBLE and 44 : will indicate the type of value being passed at the end of the argument 45 : list (the key value). The <b>count</b> should be one except for strings 46 : when it should be the length of the string (or zero to for this to be 47 : computed internally). As a special case a <b>count</b> of -1 can be 48 : used to request an existing key be deleted, in which no value is passed.<p> 49 : 50 : The actual value is passed at the end of the argument list, and should be 51 : a short, a double, or a char * value. Note that short and double values 52 : are passed by value rather than as pointers when count is 1, but as pointers 53 : if count is larger than 1.<p> 54 : 55 : Note that key values aren't actually flushed to the file until 56 : GTIFWriteKeys() is called. Till then 57 : the new values are just kept with the GTIF structure.<p> 58 : 59 : <b>Example:</b><p> 60 : 61 : <pre> 62 : GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1, 63 : RasterPixelIsArea); 64 : GTIFKeySet(gtif, GTCitationGeoKey, TYPE_ASCII, 0, 65 : "UTM 11 North / NAD27" ); 66 : </pre> 67 : 68 : */ 69 : 70 21404 : int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...) 71 : { 72 : va_list ap; 73 21404 : int nIndex = gtif->gt_keyindex[ keyID ]; 74 : GeoKey *key; 75 21404 : char *data = NULL; 76 21404 : char *val = NULL; 77 : pinfo_t sval; 78 : double dval; 79 : 80 21404 : va_start(ap, count); 81 : /* pass singleton keys by value */ 82 21404 : if (count>1 && type!=TYPE_ASCII) 83 : { 84 15 : val = va_arg(ap, char*); 85 : } 86 21389 : else if( count == -1 ) 87 : { 88 : /* delete the indicated tag */ 89 0 : va_end(ap); 90 : 91 0 : if( nIndex < 1 ) 92 0 : return 0; 93 : 94 0 : if (gtif->gt_keys[nIndex].gk_type == TYPE_ASCII) 95 : { 96 0 : _GTIFFree (gtif->gt_keys[nIndex].gk_data); 97 : } 98 : 99 0 : while( nIndex < gtif->gt_num_keys ) 100 : { 101 0 : _GTIFmemcpy( gtif->gt_keys + nIndex, 102 0 : gtif->gt_keys + nIndex + 1, 103 : sizeof(GeoKey) ); 104 0 : gtif->gt_keyindex[gtif->gt_keys[nIndex].gk_key] = nIndex; 105 0 : nIndex++; 106 : } 107 : 108 0 : gtif->gt_num_keys--; 109 0 : gtif->gt_nshorts -= sizeof(KeyEntry)/sizeof(pinfo_t); 110 0 : gtif->gt_keyindex[keyID] = 0; 111 0 : gtif->gt_flags |= FLAG_FILE_MODIFIED; 112 : 113 0 : return 1; 114 : } 115 21389 : else switch (type) 116 : { 117 13056 : case TYPE_SHORT: 118 : /* cppcheck-suppress unreadVariable */ 119 13056 : sval=(pinfo_t) va_arg(ap, int); 120 13056 : val=(char *)&sval; 121 13056 : break; 122 4596 : case TYPE_DOUBLE: 123 : /* cppcheck-suppress unreadVariable */ 124 4596 : dval=va_arg(ap, dblparam_t); 125 4596 : val=(char *)&dval; 126 4596 : break; 127 3737 : case TYPE_ASCII: 128 3737 : val=va_arg(ap, char*); 129 3737 : count = (int)strlen(val) + 1; /* force = string length */ 130 3737 : break; 131 0 : default: 132 0 : assert( FALSE ); 133 : break; 134 : } 135 21404 : va_end(ap); 136 : 137 : /* We assume here that there are no multi-valued SHORTS ! */ 138 21404 : if (nIndex) 139 : { 140 : /* Key already exists */ 141 105 : key = gtif->gt_keys+nIndex; 142 105 : if (type!=key->gk_type || count > key->gk_count) 143 : { 144 : /* need to reset data pointer */ 145 0 : key->gk_type = type; 146 0 : key->gk_count = count; 147 0 : key->gk_size = _gtiff_size[ type ]; 148 : 149 0 : if( type == TYPE_DOUBLE ) 150 : { 151 0 : key->gk_data = (char *)(gtif->gt_double + gtif->gt_ndoubles); 152 0 : gtif->gt_ndoubles += count; 153 : } 154 : } 155 : } 156 : else 157 : { 158 : /* We need to create the key */ 159 21299 : if (gtif->gt_num_keys == MAX_KEYS) return 0; 160 21299 : key = gtif->gt_keys + ++gtif->gt_num_keys; 161 21299 : nIndex = gtif->gt_num_keys; 162 21299 : gtif->gt_keyindex[ keyID ] = nIndex; 163 21299 : key->gk_key = keyID; 164 21299 : key->gk_type = type; 165 21299 : key->gk_count = count; 166 21299 : key->gk_size = _gtiff_size[ type ]; 167 21299 : if ((geokey_t)gtif->gt_keymin > keyID) gtif->gt_keymin=keyID; 168 21299 : if ((geokey_t)gtif->gt_keymax < keyID) gtif->gt_keymax=keyID; 169 21299 : gtif->gt_nshorts += sizeof(KeyEntry)/sizeof(pinfo_t); 170 21299 : if( type == TYPE_DOUBLE ) 171 : { 172 4538 : key->gk_data = (char *)(gtif->gt_double + gtif->gt_ndoubles); 173 4538 : gtif->gt_ndoubles += count; 174 : } 175 : } 176 : 177 21404 : switch (type) 178 : { 179 13056 : case TYPE_SHORT: 180 13056 : if (count > 1) return 0; 181 13056 : data = (char *)&key->gk_data; /* store value *in* data */ 182 13056 : break; 183 4611 : case TYPE_DOUBLE: 184 4611 : data = key->gk_data; 185 4611 : break; 186 3737 : case TYPE_ASCII: 187 : /* throw away existing data and allocate room for new data */ 188 3737 : if (key->gk_data != 0) 189 : { 190 0 : _GTIFFree(key->gk_data); 191 : } 192 3737 : key->gk_data = (char *)_GTIFcalloc(count); 193 3737 : key->gk_count = count; 194 3737 : data = key->gk_data; 195 3737 : break; 196 0 : default: 197 0 : return 0; 198 : } 199 : 200 21404 : _GTIFmemcpy(data, val, count*key->gk_size); 201 : 202 21404 : gtif->gt_flags |= FLAG_FILE_MODIFIED; 203 21404 : return 1; 204 : } 205 : 206 : /* Set the version numbers of the GeoTIFF directory */ 207 18 : int GTIFSetVersionNumbers(GTIF* gtif, 208 : unsigned short version, 209 : unsigned short key_revision, 210 : unsigned short minor_revision) 211 : { 212 18 : gtif->gt_version = version; 213 18 : gtif->gt_rev_major = key_revision; 214 18 : gtif->gt_rev_minor = minor_revision; 215 18 : return 1; 216 : }