Coverage Report

Created: 2025-06-13 06:18

/src/gdal/frmts/gtiff/libgeotiff/geo_write.c
Line
Count
Source (jump to first uncovered line)
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
int GTIFWriteKeys(GTIF *gt)
35
0
{
36
37
0
    if (!(gt->gt_flags & FLAG_FILE_MODIFIED)) return 1;
38
39
0
    if( gt->gt_tif == NULL )
40
0
        return 0;
41
42
0
    TempKeyData tempData;
43
0
    tempData.tk_asciiParams = 0;
44
0
    tempData.tk_asciiParamsLength = 0;
45
0
    tempData.tk_asciiParamsOffset = 0;
46
47
    /*  Sort the Keys into numerical order */
48
0
    int sortkeys[MAX_KEYS];
49
0
    if (!SortKeys(gt,sortkeys))
50
0
    {
51
        /* XXX error: a key was not recognized */
52
0
    }
53
54
    /* Set up header of ProjectionInfo tag */
55
0
    KeyHeader *header = (KeyHeader *)gt->gt_short;
56
0
    header->hdr_num_keys = (pinfo_t) gt->gt_num_keys;
57
0
    header->hdr_version  = gt->gt_version;
58
0
    header->hdr_rev_major  = gt->gt_rev_major;
59
0
    header->hdr_rev_minor  = gt->gt_rev_minor;
60
61
    /* Sum up the ASCII tag lengths */
62
0
    for (int i = 0; i < gt->gt_num_keys; i++)
63
0
    {
64
0
        GeoKey *keyptr = gt->gt_keys + sortkeys[i];
65
0
        if (keyptr->gk_type == TYPE_ASCII)
66
0
        {
67
0
            tempData.tk_asciiParamsLength += keyptr->gk_count;
68
0
        }
69
0
    }
70
0
    if (tempData.tk_asciiParamsLength > 0)
71
0
    {
72
0
        tempData.tk_asciiParams =
73
0
            (char *)_GTIFcalloc(tempData.tk_asciiParamsLength + 1);
74
0
        if( tempData.tk_asciiParams == NULL )
75
0
            return 0;
76
0
        tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
77
0
    }
78
79
    /* Set up the rest of SHORT array properly */
80
0
    GeoKey *keyptr = gt->gt_keys;
81
0
    KeyEntry *entptr = (KeyEntry*)(gt->gt_short + 4);
82
0
    for (int i=0; i< gt->gt_num_keys; i++,entptr++)
83
0
    {
84
0
        if (!WriteKey(gt,&tempData,entptr,keyptr+sortkeys[i]))
85
0
        {
86
0
            if (tempData.tk_asciiParamsLength > 0)
87
0
            {
88
0
                _GTIFFree (tempData.tk_asciiParams);
89
0
            }
90
0
            return 0;
91
0
        }
92
0
    }
93
94
    /* Write out the Key Directory */
95
0
    (gt->gt_methods.set)(gt->gt_tif, GTIFF_GEOKEYDIRECTORY, gt->gt_nshorts, gt->gt_short );
96
97
    /* Write out the params directories */
98
0
    if (gt->gt_ndoubles)
99
0
        (gt->gt_methods.set)(gt->gt_tif, GTIFF_DOUBLEPARAMS, gt->gt_ndoubles, gt->gt_double );
100
0
    if (tempData.tk_asciiParamsLength > 0)
101
0
    {
102
        /* just to be safe */
103
0
        tempData.tk_asciiParams[tempData.tk_asciiParamsLength] = '\0';
104
0
        (gt->gt_methods.set)(gt->gt_tif,
105
0
                             GTIFF_ASCIIPARAMS, 0, tempData.tk_asciiParams);
106
0
    }
107
108
0
    gt->gt_flags &= ~FLAG_FILE_MODIFIED;
109
110
0
    if (tempData.tk_asciiParamsLength > 0)
111
0
    {
112
0
        _GTIFFree (tempData.tk_asciiParams);
113
0
    }
114
0
    return 1;
115
0
}
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
static int WriteKey(GTIF* gt, TempKeyData* tempData,
129
                    KeyEntry* entptr, GeoKey* keyptr)
130
0
{
131
0
    entptr->ent_key = (pinfo_t) keyptr->gk_key;
132
0
    entptr->ent_count = (pinfo_t) keyptr->gk_count;
133
0
    const int count = entptr->ent_count;
134
135
0
    if (count==1 && keyptr->gk_type==TYPE_SHORT)
136
0
    {
137
0
        entptr->ent_location = GTIFF_LOCAL;
138
0
        memcpy(&(entptr->ent_val_offset), &keyptr->gk_data, sizeof(pinfo_t));
139
0
        return 1;
140
0
    }
141
142
0
    switch (keyptr->gk_type)
143
0
    {
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
0
      case TYPE_DOUBLE:
150
0
        entptr->ent_location = GTIFF_DOUBLEPARAMS;
151
0
        entptr->ent_val_offset = (pinfo_t)
152
0
            ((double*)keyptr->gk_data - gt->gt_double);
153
0
        break;
154
0
      case TYPE_ASCII:
155
0
        if( tempData->tk_asciiParams == NULL )
156
0
            return 0;
157
0
        entptr->ent_location = GTIFF_ASCIIPARAMS;
158
0
        entptr->ent_val_offset = (pinfo_t) tempData->tk_asciiParamsOffset;
159
0
        _GTIFmemcpy (tempData->tk_asciiParams + tempData->tk_asciiParamsOffset
160
0
                     , keyptr->gk_data, keyptr->gk_count);
161
0
        tempData->tk_asciiParams[tempData->tk_asciiParamsOffset+keyptr->gk_count-1] = '|';
162
0
        tempData->tk_asciiParamsOffset += keyptr->gk_count;
163
0
        break;
164
0
      default:
165
0
        return 0; /* failure */
166
0
    }
167
168
0
    return 1; /* success */
169
0
}
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
static int SortKeys(GTIF* gt,int *sortkeys)
179
0
{
180
    /* A bit convoluted to make Clang Static Analyzer happy */
181
0
    if( gt->gt_num_keys <= 0 )
182
0
        return 1;
183
184
0
    sortkeys[0] = 1;
185
0
    for( int i = 1; i < gt->gt_num_keys; i++ )
186
0
        sortkeys[i] = i+1;
187
188
0
    int did_work;
189
0
    do {  /* simple bubble sort */
190
0
        did_work = 0;
191
0
        for( int i = 0; i < gt->gt_num_keys-1; i++ )
192
0
        {
193
0
            if( gt->gt_keys[sortkeys[i]].gk_key
194
0
                > gt->gt_keys[sortkeys[i+1]].gk_key )
195
0
            {
196
                /* swap keys in sort list */
197
0
                int j = sortkeys[i];
198
0
                sortkeys[i] = sortkeys[i+1];
199
0
                sortkeys[i+1] = j;
200
201
0
                did_work = 1;
202
0
            }
203
0
        }
204
0
    } while( did_work );
205
206
0
    return 1;
207
0
}