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 619 : 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 619 : if (!(gt->gt_flags & FLAG_FILE_MODIFIED)) return 1;
44 :
45 619 : if( gt->gt_tif == NULL )
46 0 : return 0;
47 :
48 619 : tempData.tk_asciiParams = 0;
49 619 : tempData.tk_asciiParamsLength = 0;
50 619 : tempData.tk_asciiParamsOffset = 0;
51 :
52 : /* Sort the Keys into numerical order */
53 619 : if (!SortKeys(gt,sortkeys))
54 : {
55 : /* XXX error: a key was not recognized */
56 : }
57 :
58 : /* Set up header of ProjectionInfo tag */
59 619 : header = (KeyHeader *)gt->gt_short;
60 619 : header->hdr_num_keys = (pinfo_t) gt->gt_num_keys;
61 619 : header->hdr_version = GvCurrentVersion;
62 619 : header->hdr_rev_major = GvCurrentRevision;
63 619 : header->hdr_rev_minor = GvCurrentMinorRev;
64 :
65 : /* Sum up the ASCII tag lengths */
66 5005 : for (i = 0; i < gt->gt_num_keys; i++)
67 : {
68 4386 : keyptr = gt->gt_keys + sortkeys[i];
69 4386 : if (keyptr->gk_type == TYPE_ASCII)
70 : {
71 714 : tempData.tk_asciiParamsLength += keyptr->gk_count;
72 : }
73 : }
74 619 : if (tempData.tk_asciiParamsLength > 0)
75 : {
76 617 : tempData.tk_asciiParams =
77 617 : (char *)_GTIFcalloc(tempData.tk_asciiParamsLength + 1);
78 617 : tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
79 : }
80 :
81 : /* Set up the rest of SHORT array properly */
82 619 : keyptr = gt->gt_keys;
83 619 : entptr = (KeyEntry*)(gt->gt_short + 4);
84 5005 : for (i=0; i< gt->gt_num_keys; i++,entptr++)
85 : {
86 4386 : if (!WriteKey(gt,&tempData,entptr,keyptr+sortkeys[i])) return 0;
87 : }
88 :
89 : /* Write out the Key Directory */
90 619 : (gt->gt_methods.set)(gt->gt_tif, GTIFF_GEOKEYDIRECTORY, gt->gt_nshorts, gt->gt_short );
91 :
92 : /* Write out the params directories */
93 619 : if (gt->gt_ndoubles)
94 526 : (gt->gt_methods.set)(gt->gt_tif, GTIFF_DOUBLEPARAMS, gt->gt_ndoubles, gt->gt_double );
95 619 : if (tempData.tk_asciiParamsLength > 0)
96 : {
97 : /* just to be safe */
98 617 : tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
99 1234 : (gt->gt_methods.set)(gt->gt_tif,
100 617 : GTIFF_ASCIIPARAMS, 0, tempData.tk_asciiParams);
101 : }
102 :
103 619 : gt->gt_flags &= ~FLAG_FILE_MODIFIED;
104 :
105 619 : if (tempData.tk_asciiParamsLength > 0)
106 : {
107 617 : _GTIFFree (tempData.tk_asciiParams);
108 : }
109 619 : 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 4386 : static int WriteKey(GTIF* gt, TempKeyData* tempData,
124 : KeyEntry* entptr, GeoKey* keyptr)
125 : {
126 : int count;
127 :
128 4386 : entptr->ent_key = (pinfo_t) keyptr->gk_key;
129 4386 : entptr->ent_count = (pinfo_t) keyptr->gk_count;
130 4386 : count = entptr->ent_count;
131 :
132 4386 : if (count==1 && keyptr->gk_type==TYPE_SHORT)
133 : {
134 2595 : entptr->ent_location = GTIFF_LOCAL;
135 2595 : entptr->ent_val_offset = *(pinfo_t*)&keyptr->gk_data;
136 2595 : return 1;
137 : }
138 :
139 1791 : 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 1077 : entptr->ent_location = GTIFF_DOUBLEPARAMS;
148 1077 : entptr->ent_val_offset = (pinfo_t)
149 1077 : ((double*)keyptr->gk_data - gt->gt_double);
150 1077 : break;
151 : case TYPE_ASCII:
152 714 : entptr->ent_location = GTIFF_ASCIIPARAMS;
153 714 : entptr->ent_val_offset = (pinfo_t) tempData->tk_asciiParamsOffset;
154 1428 : _GTIFmemcpy (tempData->tk_asciiParams + tempData->tk_asciiParamsOffset
155 714 : , keyptr->gk_data, keyptr->gk_count);
156 714 : tempData->tk_asciiParams[tempData->tk_asciiParamsOffset+keyptr->gk_count-1] = '|';
157 714 : tempData->tk_asciiParamsOffset += keyptr->gk_count;
158 714 : break;
159 : default:
160 0 : return 0; /* failure */
161 : }
162 :
163 1791 : 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 619 : static int SortKeys(GTIF* gt,int *sortkeys)
174 : {
175 : int loc;
176 619 : int nkeys=0;
177 : geokey_t key,kmin,kmax;
178 619 : int *index = gt->gt_keyindex;
179 :
180 619 : kmin = (geokey_t) gt->gt_keymin;
181 619 : kmax = (geokey_t) gt->gt_keymax;
182 737518 : for (key=kmin; key<=kmax; key++)
183 : {
184 736899 : if ( (loc=index[key]) != 0 )
185 : {
186 4386 : sortkeys[nkeys] = loc;
187 4386 : nkeys++;
188 : }
189 : }
190 :
191 619 : return nkeys==gt->gt_num_keys;
192 : }
193 :
|