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 895 : int GTIFWriteKeys(GTIF *gt)
35 : {
36 : int i;
37 : GeoKey *keyptr;
38 : KeyEntry *entptr;
39 : KeyHeader *header;
40 : TempKeyData tempData;
41 : int sortkeys[MAX_KEYS];
42 :
43 895 : if (!(gt->gt_flags & FLAG_FILE_MODIFIED)) return 1;
44 :
45 895 : if( gt->gt_tif == NULL )
46 0 : return 0;
47 :
48 895 : tempData.tk_asciiParams = 0;
49 895 : tempData.tk_asciiParamsLength = 0;
50 895 : tempData.tk_asciiParamsOffset = 0;
51 :
52 : /* Sort the Keys into numerical order */
53 895 : if (!SortKeys(gt,sortkeys))
54 : {
55 : /* XXX error: a key was not recognized */
56 : }
57 :
58 : /* Set up header of ProjectionInfo tag */
59 895 : header = (KeyHeader *)gt->gt_short;
60 895 : header->hdr_num_keys = (pinfo_t) gt->gt_num_keys;
61 895 : header->hdr_version = GvCurrentVersion;
62 895 : header->hdr_rev_major = GvCurrentRevision;
63 895 : header->hdr_rev_minor = GvCurrentMinorRev;
64 :
65 : /* Sum up the ASCII tag lengths */
66 7570 : for (i = 0; i < gt->gt_num_keys; i++)
67 : {
68 6675 : keyptr = gt->gt_keys + sortkeys[i];
69 6675 : if (keyptr->gk_type == TYPE_ASCII)
70 : {
71 1134 : tempData.tk_asciiParamsLength += keyptr->gk_count;
72 : }
73 : }
74 895 : if (tempData.tk_asciiParamsLength > 0)
75 : {
76 893 : tempData.tk_asciiParams =
77 893 : (char *)_GTIFcalloc(tempData.tk_asciiParamsLength + 1);
78 893 : tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
79 : }
80 :
81 : /* Set up the rest of SHORT array properly */
82 895 : keyptr = gt->gt_keys;
83 895 : entptr = (KeyEntry*)(gt->gt_short + 4);
84 7570 : for (i=0; i< gt->gt_num_keys; i++,entptr++)
85 : {
86 6675 : if (!WriteKey(gt,&tempData,entptr,keyptr+sortkeys[i])) return 0;
87 : }
88 :
89 : /* Write out the Key Directory */
90 895 : (gt->gt_methods.set)(gt->gt_tif, GTIFF_GEOKEYDIRECTORY, gt->gt_nshorts, gt->gt_short );
91 :
92 : /* Write out the params directories */
93 895 : if (gt->gt_ndoubles)
94 717 : (gt->gt_methods.set)(gt->gt_tif, GTIFF_DOUBLEPARAMS, gt->gt_ndoubles, gt->gt_double );
95 895 : if (tempData.tk_asciiParamsLength > 0)
96 : {
97 : /* just to be safe */
98 893 : tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
99 1786 : (gt->gt_methods.set)(gt->gt_tif,
100 893 : GTIFF_ASCIIPARAMS, 0, tempData.tk_asciiParams);
101 : }
102 :
103 895 : gt->gt_flags &= ~FLAG_FILE_MODIFIED;
104 :
105 895 : if (tempData.tk_asciiParamsLength > 0)
106 : {
107 893 : _GTIFFree (tempData.tk_asciiParams);
108 : }
109 895 : return 1;
110 : }
111 :
112 : /**********************************************************************
113 : *
114 : * Private Routines
115 : *
116 : **********************************************************************/
117 :
118 : /*
119 : * Given GeoKey, write out the KeyEntry entries, returning 0 if failure.
120 : * This is the exact complement of ReadKey().
121 : */
122 :
123 6675 : static int WriteKey(GTIF* gt, TempKeyData* tempData,
124 : KeyEntry* entptr, GeoKey* keyptr)
125 : {
126 : int count;
127 :
128 6675 : entptr->ent_key = (pinfo_t) keyptr->gk_key;
129 6675 : entptr->ent_count = (pinfo_t) keyptr->gk_count;
130 6675 : count = entptr->ent_count;
131 :
132 6675 : if (count==1 && keyptr->gk_type==TYPE_SHORT)
133 : {
134 3962 : entptr->ent_location = GTIFF_LOCAL;
135 3962 : entptr->ent_val_offset = *(pinfo_t*)&keyptr->gk_data;
136 3962 : return 1;
137 : }
138 :
139 2713 : switch (keyptr->gk_type)
140 : {
141 : case TYPE_SHORT:
142 0 : entptr->ent_location = GTIFF_GEOKEYDIRECTORY;
143 0 : entptr->ent_val_offset = (pinfo_t)
144 0 : ((pinfo_t*)keyptr->gk_data - gt->gt_short);
145 0 : break;
146 : case TYPE_DOUBLE:
147 1579 : entptr->ent_location = GTIFF_DOUBLEPARAMS;
148 1579 : entptr->ent_val_offset = (pinfo_t)
149 1579 : ((double*)keyptr->gk_data - gt->gt_double);
150 1579 : break;
151 : case TYPE_ASCII:
152 1134 : entptr->ent_location = GTIFF_ASCIIPARAMS;
153 1134 : entptr->ent_val_offset = (pinfo_t) tempData->tk_asciiParamsOffset;
154 3402 : _GTIFmemcpy (tempData->tk_asciiParams + tempData->tk_asciiParamsOffset
155 2268 : , keyptr->gk_data, keyptr->gk_count);
156 1134 : tempData->tk_asciiParams[tempData->tk_asciiParamsOffset+keyptr->gk_count-1] = '|';
157 1134 : tempData->tk_asciiParamsOffset += keyptr->gk_count;
158 1134 : break;
159 : default:
160 0 : return 0; /* failure */
161 : }
162 :
163 2713 : return 1; /* success */
164 : }
165 :
166 :
167 : /*
168 : * Numerically sort the GeoKeys.
169 : * We just do a linear search through
170 : * the list and pull out the keys that were set.
171 : */
172 :
173 895 : static int SortKeys(GTIF* gt,int *sortkeys)
174 : {
175 : int i, did_work;
176 :
177 7570 : for( i = 0; i < gt->gt_num_keys; i++ )
178 6675 : sortkeys[i] = i+1;
179 :
180 : do { /* simple bubble sort */
181 3171 : did_work = 0;
182 26904 : for( i = 0; i < gt->gt_num_keys-1; i++ )
183 : {
184 47466 : if( gt->gt_keys[sortkeys[i]].gk_key
185 23733 : > gt->gt_keys[sortkeys[i+1]].gk_key )
186 : {
187 : /* swap keys in sort list */
188 7998 : int j = sortkeys[i];
189 7998 : sortkeys[i] = sortkeys[i+1];
190 7998 : sortkeys[i+1] = j;
191 :
192 7998 : did_work = 1;
193 : }
194 : }
195 3171 : } while( did_work );
196 :
197 895 : return 1;
198 : }
199 :
|