Line data Source code
1 : /********************************************************************** 2 : * 3 : * geo_write.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 source code derived therefrom. 11 : * 12 : **********************************************************************/ 13 : 14 : #include "geotiffio.h" /* public interface */ 15 : #include "geo_tiffp.h" /* external TIFF interface */ 16 : #include "geo_keyp.h" /* private interface */ 17 : 18 : static int WriteKey(GTIF* gt, TempKeyData* tempData, 19 : KeyEntry* entptr, GeoKey* keyptr); 20 : static int SortKeys(GTIF* gt,int *sortkeys); 21 : 22 : 23 : /** 24 : This function flushes all the GeoTIFF keys that have been set with the 25 : GTIFKeySet() function into the associated 26 : TIFF file. 27 : 28 : @param gt The GeoTIFF handle returned by GTIFNew. 29 : 30 : GTIFWriteKeys() should be called before 31 : GTIFFree() is used to deallocate a GeoTIFF access handle. 32 : */ 33 : 34 2999 : int GTIFWriteKeys(GTIF *gt) 35 : { 36 : 37 2999 : if (!(gt->gt_flags & FLAG_FILE_MODIFIED)) return 1; 38 : 39 2989 : if( gt->gt_tif == NULL ) 40 0 : return 0; 41 : 42 : TempKeyData tempData; 43 2989 : tempData.tk_asciiParams = 0; 44 2989 : tempData.tk_asciiParamsLength = 0; 45 2989 : tempData.tk_asciiParamsOffset = 0; 46 : 47 : /* Sort the Keys into numerical order */ 48 : int sortkeys[MAX_KEYS]; 49 2989 : if (!SortKeys(gt,sortkeys)) 50 : { 51 : /* XXX error: a key was not recognized */ 52 : } 53 : 54 : /* Set up header of ProjectionInfo tag */ 55 2989 : KeyHeader *header = (KeyHeader *)gt->gt_short; 56 2989 : header->hdr_num_keys = (pinfo_t) gt->gt_num_keys; 57 2989 : header->hdr_version = gt->gt_version; 58 2989 : header->hdr_rev_major = gt->gt_rev_major; 59 2989 : header->hdr_rev_minor = gt->gt_rev_minor; 60 : 61 : /* Sum up the ASCII tag lengths */ 62 24288 : for (int i = 0; i < gt->gt_num_keys; i++) 63 : { 64 21299 : GeoKey *keyptr = gt->gt_keys + sortkeys[i]; 65 21299 : if (keyptr->gk_type == TYPE_ASCII) 66 : { 67 3737 : tempData.tk_asciiParamsLength += keyptr->gk_count; 68 : } 69 : } 70 2989 : if (tempData.tk_asciiParamsLength > 0) 71 : { 72 2872 : tempData.tk_asciiParams = 73 2872 : (char *)_GTIFcalloc(tempData.tk_asciiParamsLength + 1); 74 2872 : if( tempData.tk_asciiParams == NULL ) 75 0 : return 0; 76 2872 : tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0'; 77 : } 78 : 79 : /* Set up the rest of SHORT array properly */ 80 2989 : GeoKey *keyptr = gt->gt_keys; 81 2989 : KeyEntry *entptr = (KeyEntry*)(gt->gt_short + 4); 82 24288 : for (int i=0; i< gt->gt_num_keys; i++,entptr++) 83 : { 84 21299 : if (!WriteKey(gt,&tempData,entptr,keyptr+sortkeys[i])) 85 : { 86 0 : if (tempData.tk_asciiParamsLength > 0) 87 : { 88 0 : _GTIFFree (tempData.tk_asciiParams); 89 : } 90 0 : return 0; 91 : } 92 : } 93 : 94 : /* Write out the Key Directory */ 95 2989 : (gt->gt_methods.set)(gt->gt_tif, GTIFF_GEOKEYDIRECTORY, gt->gt_nshorts, gt->gt_short ); 96 : 97 : /* Write out the params directories */ 98 2989 : if (gt->gt_ndoubles) 99 2097 : (gt->gt_methods.set)(gt->gt_tif, GTIFF_DOUBLEPARAMS, gt->gt_ndoubles, gt->gt_double ); 100 2989 : if (tempData.tk_asciiParamsLength > 0) 101 : { 102 : /* just to be safe */ 103 2872 : tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0'; 104 2872 : (gt->gt_methods.set)(gt->gt_tif, 105 2872 : GTIFF_ASCIIPARAMS, 0, tempData.tk_asciiParams); 106 : } 107 : 108 2989 : gt->gt_flags &= ~FLAG_FILE_MODIFIED; 109 : 110 2989 : if (tempData.tk_asciiParamsLength > 0) 111 : { 112 2872 : _GTIFFree (tempData.tk_asciiParams); 113 : } 114 2989 : return 1; 115 : } 116 : 117 : /********************************************************************** 118 : * 119 : * Private Routines 120 : * 121 : **********************************************************************/ 122 : 123 : /* 124 : * Given GeoKey, write out the KeyEntry entries, returning 0 if failure. 125 : * This is the exact complement of ReadKey(). 126 : */ 127 : 128 21299 : static int WriteKey(GTIF* gt, TempKeyData* tempData, 129 : KeyEntry* entptr, GeoKey* keyptr) 130 : { 131 21299 : entptr->ent_key = (pinfo_t) keyptr->gk_key; 132 21299 : entptr->ent_count = (pinfo_t) keyptr->gk_count; 133 21299 : const int count = entptr->ent_count; 134 : 135 21299 : if (count==1 && keyptr->gk_type==TYPE_SHORT) 136 : { 137 13024 : entptr->ent_location = GTIFF_LOCAL; 138 13024 : memcpy(&(entptr->ent_val_offset), &keyptr->gk_data, sizeof(pinfo_t)); 139 13024 : return 1; 140 : } 141 : 142 8275 : switch (keyptr->gk_type) 143 : { 144 0 : case TYPE_SHORT: 145 0 : entptr->ent_location = GTIFF_GEOKEYDIRECTORY; 146 0 : entptr->ent_val_offset = (pinfo_t) 147 0 : ((pinfo_t*)keyptr->gk_data - gt->gt_short); 148 0 : break; 149 4538 : case TYPE_DOUBLE: 150 4538 : entptr->ent_location = GTIFF_DOUBLEPARAMS; 151 4538 : entptr->ent_val_offset = (pinfo_t) 152 4538 : ((double*)keyptr->gk_data - gt->gt_double); 153 4538 : break; 154 3737 : case TYPE_ASCII: 155 3737 : if( tempData->tk_asciiParams == NULL ) 156 0 : return 0; 157 3737 : entptr->ent_location = GTIFF_ASCIIPARAMS; 158 3737 : entptr->ent_val_offset = (pinfo_t) tempData->tk_asciiParamsOffset; 159 3737 : _GTIFmemcpy (tempData->tk_asciiParams + tempData->tk_asciiParamsOffset 160 3737 : , keyptr->gk_data, keyptr->gk_count); 161 3737 : tempData->tk_asciiParams[tempData->tk_asciiParamsOffset+keyptr->gk_count-1] = '|'; 162 3737 : tempData->tk_asciiParamsOffset += keyptr->gk_count; 163 3737 : break; 164 0 : default: 165 0 : return 0; /* failure */ 166 : } 167 : 168 8275 : return 1; /* success */ 169 : } 170 : 171 : 172 : /* 173 : * Numerically sort the GeoKeys. 174 : * We just do a linear search through 175 : * the list and pull out the keys that were set. 176 : */ 177 : 178 2989 : static int SortKeys(GTIF* gt,int *sortkeys) 179 : { 180 : /* A bit convoluted to make Clang Static Analyzer happy */ 181 2989 : if( gt->gt_num_keys <= 0 ) 182 0 : return 1; 183 : 184 2989 : sortkeys[0] = 1; 185 21299 : for( int i = 1; i < gt->gt_num_keys; i++ ) 186 18310 : sortkeys[i] = i+1; 187 : 188 : int did_work; 189 : do { /* simple bubble sort */ 190 12557 : did_work = 0; 191 99940 : for( int i = 0; i < gt->gt_num_keys-1; i++ ) 192 : { 193 87383 : if( gt->gt_keys[sortkeys[i]].gk_key 194 87383 : > gt->gt_keys[sortkeys[i+1]].gk_key ) 195 : { 196 : /* swap keys in sort list */ 197 25614 : int j = sortkeys[i]; 198 25614 : sortkeys[i] = sortkeys[i+1]; 199 25614 : sortkeys[i+1] = j; 200 : 201 25614 : did_work = 1; 202 : } 203 : } 204 12557 : } while( did_work ); 205 : 206 2989 : return 1; 207 : }