Line data Source code
1 : /******************************************************************************
2 : * Copyright (c) 2008, Frank Warmerdam
3 : *
4 : * SPDX-License-Identifier: MIT
5 : ******************************************************************************
6 : *
7 : * geo_simpletags.c TIFF Interface module that just keeps track of the
8 : * tags in memory, without depending on libtiff.
9 : *
10 : *****************************************************************************/
11 :
12 : #include "geotiff.h" /* public GTIFF interface */
13 : #include "geo_simpletags.h"
14 :
15 : #include "geo_tiffp.h" /* Private TIFF interface */
16 : #include "geo_keyp.h" /* Private GTIFF interface */
17 :
18 : static int ST_TypeSize( int st_type );
19 :
20 : static int _GTIFGetField (tiff_t *tif, pinfo_t tag, int *count, void *value );
21 : static int _GTIFSetField (tiff_t *tif, pinfo_t tag, int count, void *value );
22 : static tagtype_t _GTIFTagType (tiff_t *tif, pinfo_t tag);
23 :
24 : /*
25 : * Set up default TIFF handlers.
26 : */
27 0 : void GTIFSetSimpleTagsMethods(TIFFMethod *method)
28 : {
29 0 : if (!method) return;
30 :
31 0 : method->get = _GTIFGetField;
32 0 : method->set = _GTIFSetField;
33 0 : method->type = _GTIFTagType;
34 : }
35 :
36 : /* returns the value of TIFF tag <tag>, or if
37 : * the value is an array, returns an allocated buffer
38 : * containing the values. Allocate a copy of the actual
39 : * buffer, sized up for updating.
40 : */
41 0 : static int _GTIFGetField (tiff_t *tif, pinfo_t tag, int *count, void *val )
42 : {
43 : int data_type;
44 : void *internal_value;
45 0 : if( !ST_GetKey( (ST_TIFF*) tif, (int) tag, count, &data_type,
46 : &internal_value ) )
47 0 : return 0;
48 :
49 0 : if( data_type != ST_TagType( tag ) )
50 0 : return 0;
51 :
52 0 : const int item_size = ST_TypeSize( data_type );
53 :
54 0 : void *ret_value = (char *)_GTIFcalloc( (size_t)(*count) * item_size );
55 0 : if (!ret_value) return 0;
56 :
57 0 : _TIFFmemcpy( ret_value, internal_value, (size_t)(item_size) * *count );
58 :
59 0 : *(void **)val = ret_value;
60 0 : return 1;
61 : }
62 :
63 : /*
64 : * Set a GeoTIFF TIFF field.
65 : */
66 0 : static int _GTIFSetField (tiff_t *tif, pinfo_t tag, int count, void *value )
67 : {
68 0 : const int st_type = ST_TagType( tag );
69 :
70 0 : return ST_SetKey( (ST_TIFF *) tif, (int) tag, count, st_type, value );
71 : }
72 :
73 : /*
74 : * This routine is supposed to return the TagType of the <tag>
75 : * TIFF tag. Unfortunately, "libtiff" does not provide this
76 : * service by default, so we just have to "know" what type of tags
77 : * we've got, and how many. We only define the ones Geotiff
78 : * uses here, and others return UNKNOWN. The "tif" parameter
79 : * is provided for those TIFF implementations that provide
80 : * for tag-type queries.
81 : */
82 0 : static tagtype_t _GTIFTagType (tiff_t *tif, pinfo_t tag)
83 : {
84 : (void) tif; /* dummy reference */
85 :
86 : tagtype_t ttype;
87 0 : switch (tag)
88 : {
89 0 : case GTIFF_ASCIIPARAMS: ttype=TYPE_ASCII; break;
90 0 : case GTIFF_PIXELSCALE:
91 : case GTIFF_TRANSMATRIX:
92 : case GTIFF_TIEPOINTS:
93 0 : case GTIFF_DOUBLEPARAMS: ttype=TYPE_DOUBLE; break;
94 0 : case GTIFF_GEOKEYDIRECTORY: ttype=TYPE_SHORT; break;
95 0 : default: ttype = TYPE_UNKNOWN;
96 : }
97 :
98 0 : return ttype;
99 : }
100 :
101 : /************************************************************************/
102 : /* ST_TagType() */
103 : /************************************************************************/
104 :
105 0 : int ST_TagType( int tag )
106 : {
107 0 : switch (tag)
108 : {
109 0 : case GTIFF_ASCIIPARAMS:
110 0 : return STT_ASCII;
111 :
112 0 : case GTIFF_PIXELSCALE:
113 : case GTIFF_TRANSMATRIX:
114 : case GTIFF_TIEPOINTS:
115 : case GTIFF_DOUBLEPARAMS:
116 0 : return STT_DOUBLE;
117 :
118 0 : case GTIFF_GEOKEYDIRECTORY:
119 0 : return STT_SHORT;
120 : }
121 :
122 0 : return -1;
123 : }
124 :
125 :
126 : /************************************************************************/
127 : /* ST_TypeSize() */
128 : /************************************************************************/
129 :
130 0 : static int ST_TypeSize( int st_type )
131 :
132 : {
133 0 : if( st_type == STT_ASCII )
134 0 : return 1;
135 0 : else if( st_type == STT_SHORT )
136 0 : return 2;
137 : else /* if( st_type == STT_DOUBLE ) */
138 0 : return 8;
139 : }
140 :
141 : /************************************************************************/
142 : /* ST_Create() */
143 : /************************************************************************/
144 :
145 0 : ST_TIFF *ST_Create()
146 :
147 : {
148 0 : return (ST_TIFF *) calloc(1,sizeof(ST_TIFF));
149 : }
150 :
151 : /************************************************************************/
152 : /* ST_Destroy() */
153 : /************************************************************************/
154 :
155 0 : void ST_Destroy( ST_TIFF *st )
156 :
157 : {
158 0 : for( int i = 0; i < st->key_count; i++ )
159 0 : free( st->key_list[i].data );
160 :
161 0 : if( st->key_list )
162 0 : free( st->key_list );
163 0 : free( st );
164 0 : }
165 :
166 : /************************************************************************/
167 : /* ST_SetKey() */
168 : /************************************************************************/
169 :
170 0 : int ST_SetKey( ST_TIFF *st, int tag, int count, int st_type, void *data )
171 :
172 : {
173 : /* -------------------------------------------------------------------- */
174 : /* We should compute the length if we were not given a count */
175 : /* -------------------------------------------------------------------- */
176 0 : if (count == 0 && st_type == STT_ASCII )
177 : {
178 0 : count = (int)strlen((char*)data)+1;
179 : }
180 :
181 : /* -------------------------------------------------------------------- */
182 : /* If we already have a value for this tag, replace it. */
183 : /* -------------------------------------------------------------------- */
184 0 : const int item_size = ST_TypeSize( st_type );
185 0 : for( int i = 0; i < st->key_count; i++ )
186 : {
187 0 : if( st->key_list[i].tag == tag )
188 : {
189 0 : free( st->key_list[i].data );
190 0 : st->key_list[i].count = count;
191 0 : st->key_list[i].type = st_type;
192 : /* +1 to make clang static analyzer not warn about potential malloc(0) */
193 0 : st->key_list[i].data = malloc(item_size*count+1);
194 0 : memcpy( st->key_list[i].data, data, (size_t)count * item_size );
195 0 : return 1;
196 : }
197 : }
198 :
199 : /* -------------------------------------------------------------------- */
200 : /* Otherwise, add a new entry. */
201 : /* -------------------------------------------------------------------- */
202 0 : st->key_count++;
203 0 : st->key_list = (ST_KEY *) realloc(st->key_list,
204 0 : sizeof(ST_KEY) * st->key_count);
205 0 : st->key_list[st->key_count-1].tag = tag;
206 0 : st->key_list[st->key_count-1].count = count;
207 0 : st->key_list[st->key_count-1].type = st_type;
208 : /* +1 to make clang static analyzer not warn about potential malloc(0) */
209 0 : st->key_list[st->key_count-1].data = malloc((size_t)(item_size) * count+1);
210 0 : memcpy( st->key_list[st->key_count-1].data, data, (size_t)(item_size) * count );
211 :
212 0 : return 1;
213 : }
214 :
215 : /************************************************************************/
216 : /* ST_GetKey() */
217 : /************************************************************************/
218 :
219 0 : int ST_GetKey( ST_TIFF *st, int tag, int *count,
220 : int *st_type, void **data_ptr )
221 :
222 : {
223 0 : for( int i = 0; i < st->key_count; i++ )
224 : {
225 0 : if( st->key_list[i].tag == tag )
226 : {
227 0 : if( count )
228 0 : *count = st->key_list[i].count;
229 0 : if( st_type )
230 0 : *st_type = st->key_list[i].type;
231 0 : if( data_ptr )
232 0 : *data_ptr = st->key_list[i].data;
233 0 : return 1;
234 : }
235 : }
236 :
237 0 : return 0;
238 : }
|