~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to lib/raster/quant_io.c

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*!
 
2
 * \file lib/raster/quant_io.c
 
3
 * 
 
4
 * \brief Raster Library - Quantization rules (input / output)
 
5
 *
 
6
 * (C) 1999-2010 by the GRASS Development Team
 
7
 *
 
8
 * This program is free software under the GNU General Public License
 
9
 * (>=v2). Read the file COPYING that comes with GRASS for details.
 
10
 *
 
11
 * \author USACERL and many others
 
12
 */
 
13
 
 
14
/**********************************************************************
 
15
 *
 
16
 **********************************************************************/
 
17
 
 
18
#include <string.h>
 
19
 
 
20
#include <grass/gis.h>
 
21
#include <grass/raster.h>
 
22
#include <grass/glocale.h>
 
23
 
 
24
#define QUANT_FILE_NAME "f_quant"
 
25
 
 
26
static int quant_parse_file(FILE *, struct Quant *);
 
27
 
 
28
#if 0
 
29
/* redundant: integer range doesn't exist now: it is defined by
 
30
   the quant rules */
 
31
static int quant_load_range(struct Quant *quant, const char *name, const char *mapset)
 
32
{
 
33
    struct FPRange fprange;
 
34
    struct Range range;
 
35
    char buf[300];
 
36
    DCELL dMin, dMax;
 
37
    CELL min, max;
 
38
 
 
39
    if (Rast_read_fp_range(name, mapset, &fprange) <= 0)
 
40
        return 0;
 
41
    Rast_get_fp_range_min_max(&fprange, &dMin, &dMax);
 
42
    if (Rast_is_d_null_value(&dMin) || Rast_is_d_null_value(&dMax)) {
 
43
        G_warning(_("Floating data range for raster map <%s> is empty"),
 
44
                  G_fully_qualified_name(name, mapset));
 
45
        return -3;
 
46
    }
 
47
 
 
48
    if (Rast_read_range(name, mapset, &range) < 0)
 
49
        return 0;
 
50
    Rast_get_range_min_max(&range, &min, &max);
 
51
    if (Rast_is_c_null_value(&min) && Rast_is_c_null_value(&max)) {
 
52
        G_warning(_("Integer data range for raster map <%s> is empty"),
 
53
                  G_fully_qualified_name(name, mapset));
 
54
        return -3;
 
55
    }
 
56
 
 
57
    Rast_quant_add_rule(quant, dMin, dMax, min, max);
 
58
 
 
59
    return 1;
 
60
}
 
61
#endif
 
62
 
 
63
/*!
 
64
  \brief Reads quantization rules (internal use only)
 
65
 
 
66
  Reads quantization rules for raster map <i>name</i> in <i>mapset</i>
 
67
  and stores them in the quantization structure "quant". If the map is
 
68
  in another mapset, first checks for quant2 table for this map in
 
69
  current mapset.
 
70
 
 
71
  Note: in the case of negative return value, the result of using the 
 
72
  quantization structure is not defined.
 
73
  in case of return value 0, calls to Rast_quant_perform_d() 
 
74
  and Rast_quant_perform_f() return NO_DATA (see description of 
 
75
  Rast_quant_perform_d() for more details). in case of
 
76
  return values 2 and 3, the explicit rule for quant is set:
 
77
  floating range is mapped to integer range.
 
78
  
 
79
  Note: use Rast_quant_init() to allocate and initialize the quantization
 
80
  staructure quant before the first usage of G_quant_import().
 
81
 
 
82
  Note: this function uses Rast_quant_free () to clear all previously
 
83
  stored rules in quant.
 
84
 
 
85
  \param name map name
 
86
  \param mapset mapset name
 
87
  \param[out] quant pointer to Quant structure
 
88
  
 
89
  \return -2 if raster map is of type integer.
 
90
  \return -1 if map name is fully qualified and mapset is not the current one
 
91
  \return 0 if quantization file does not exist, or the file is empty, 
 
92
  \return 1 if non-empty quantization file exists.
 
93
*/
 
94
int Rast__quant_import(const char *name, const char *mapset,
 
95
                       struct Quant *quant)
 
96
{
 
97
    char buf[1024];
 
98
    char xname[GNAME_MAX], xmapset[GMAPSET_MAX], element[GNAME_MAX + 7];
 
99
    int parsStat;
 
100
    FILE *fd;
 
101
 
 
102
    Rast_quant_free(quant);
 
103
 
 
104
    if (Rast_map_type(name, mapset) == CELL_TYPE) {
 
105
        G_warning(_("Attempt to open quantization"
 
106
                    " table for CELL raster map <%s>"),
 
107
                  G_fully_qualified_name(name, mapset));
 
108
        return -2;
 
109
    }
 
110
 
 
111
    if (G_name_is_fully_qualified(name, xname, xmapset)) {
 
112
        if (strlen(mapset) == 0)
 
113
            mapset = xmapset;
 
114
        else if (strcmp(xmapset, mapset) != 0)
 
115
            return -1;
 
116
        name = xname;
 
117
    }
 
118
 
 
119
    /* first check if quant2/mapset/name exists in the current mapset */
 
120
    sprintf(element, "quant2/%s", mapset);
 
121
    if ((fd = G_fopen_old(element, name, G_mapset()))) {
 
122
        parsStat = quant_parse_file(fd, quant);
 
123
        fclose(fd);
 
124
        if (parsStat)
 
125
            return 1;
 
126
        sprintf(buf,
 
127
                "quantization file in quant2 for raster map <%s> is empty",
 
128
                G_fully_qualified_name(name, mapset));
 
129
    }
 
130
 
 
131
    /* now try reading regular : cell_misc/name/quant file */
 
132
    if (!(fd = G_fopen_old_misc("cell_misc", QUANT_FILE_NAME, name, mapset))) {
 
133
 
 
134
        /* int range doesn't exist anymore if (quant_load_range (quant, name, mapset)>0) return 3; */
 
135
        G_warning(_("Quantization file for raster map <%s> is missing"),
 
136
                  G_fully_qualified_name(name, mapset));
 
137
    }
 
138
    else {
 
139
        parsStat = quant_parse_file(fd, quant);
 
140
        fclose(fd);
 
141
 
 
142
        if (parsStat)
 
143
            return 1;
 
144
        /* int range doesn't exist anymore if (quant_load_range (quant, name, mapset)>0) return 2; */
 
145
        G_warning(_("Quantization file for raster map <%s> is empty"),
 
146
                  G_fully_qualified_name(name, mapset));
 
147
    }
 
148
    
 
149
    return 0;
 
150
}
 
151
 
 
152
/*!
 
153
  \brief Parse input lines with the following formats
 
154
 
 
155
  \code
 
156
  d_high:d_low:c_high:c_low
 
157
  d_high:d_low:c_val          (i.e. c_high == c_low)
 
158
  *:d_val:c_val               (interval [inf, d_val])  (**)
 
159
  d_val:*:c_val               (interval [d_val, inf])  (**)
 
160
  \endcode
 
161
 
 
162
  All other lines are ignored
 
163
  
 
164
  (**) only the first appearances in the file are considered.
 
165
*/
 
166
static int quant_parse_file(FILE * fd, struct Quant *quant)
 
167
{
 
168
    CELL cLow, cHigh;
 
169
    DCELL dLow, dHigh;
 
170
    char buf[1024];
 
171
    int foundNegInf = 0, foundPosInf = 0;
 
172
 
 
173
    while (fgets(buf, sizeof(buf), fd)) {
 
174
        if (strncmp(buf, "truncate", 8) == 0) {
 
175
            quant->truncate_only = 1;
 
176
            return 1;
 
177
        }
 
178
        if (strncmp(buf, "round", 5) == 0) {
 
179
            quant->round_only = 1;
 
180
            return 1;
 
181
        }
 
182
        switch (sscanf(buf, "%lf:%lf:%d:%d", &dLow, &dHigh, &cLow, &cHigh)) {
 
183
        case 3:
 
184
            Rast_quant_add_rule(quant, dLow, dHigh, cLow, cLow);
 
185
            break;
 
186
        case 4:
 
187
            Rast_quant_add_rule(quant, dLow, dHigh, cLow, cHigh);
 
188
            break;
 
189
        default:
 
190
            switch (sscanf(buf, "*:%lf:%d", &dLow, &cLow)) {
 
191
            case 2:
 
192
                if (!foundNegInf) {
 
193
                    Rast_quant_set_neg_infinite_rule(quant, dLow, cLow);
 
194
                    foundNegInf = 1;
 
195
                }
 
196
                break;
 
197
            default:
 
198
                switch (sscanf(buf, "%lf:*:%d", &dLow, &cLow)) {
 
199
                case 2:
 
200
                    if (!foundPosInf) {
 
201
                        Rast_quant_set_pos_infinite_rule(quant, dLow, cLow);
 
202
                        foundPosInf = 1;
 
203
                    }
 
204
                    break;
 
205
                default:
 
206
                    continue;   /* other lines are ignored */
 
207
                }
 
208
            }
 
209
        }
 
210
    }
 
211
 
 
212
    if (Rast_quant_nof_rules(quant) > 0)
 
213
        Rast_quant_reverse_rule_order(quant);
 
214
 
 
215
    return ((Rast_quant_nof_rules(quant) > 0) ||
 
216
            (Rast_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0) ||
 
217
            (Rast_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0));
 
218
}
 
219
 
 
220
static void quant_write(FILE * fd, const struct Quant *quant)
 
221
{
 
222
    DCELL dLow, dHigh;
 
223
    CELL cLow, cHigh;
 
224
    int i;
 
225
 
 
226
    if (quant->truncate_only) {
 
227
        fprintf(fd, "truncate");
 
228
        return;
 
229
    }
 
230
    if (quant->round_only) {
 
231
        fprintf(fd, "round");
 
232
        return;
 
233
    }
 
234
    if (Rast_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0)
 
235
        fprintf(fd, "*:%.20g:%d\n", dLow, cLow);
 
236
 
 
237
    if (Rast_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0)
 
238
        fprintf(fd, "%.20g:*:%d\n", dLow, cLow);
 
239
 
 
240
    for (i = Rast_quant_nof_rules(quant) - 1; i >= 0; i--) {
 
241
        Rast_quant_get_ith_rule(quant, i, &dLow, &dHigh, &cLow, &cHigh);
 
242
        fprintf(fd, "%.20g:%.20g:%d", dLow, dHigh, cLow);
 
243
        if (cLow != cHigh)
 
244
            fprintf(fd, ":%d", cHigh);
 
245
        fprintf(fd, "\n");
 
246
    }
 
247
}
 
248
 
 
249
/*!
 
250
  \brief Writes the quantization rules (internal use only)
 
251
 
 
252
  Writes the quantization rules stored in <i>quant</i> for <i>name</i>
 
253
  . If the mapset is the same as the current mapset, the quant file is
 
254
  created in 'cell_misc/name' directory, otherwise it is created in
 
255
  'quant2/mapset' directory, much like writing colors for map in
 
256
  another mapset.  The rules are written in decreasing order of
 
257
  priority (i.e. rules added earlier are written later).
 
258
 
 
259
  Note: if no rules are defined an empty file is created. 
 
260
  
 
261
  \param name map name
 
262
  \param mapset mapset name
 
263
  \param quant pointer to Quant structure
 
264
 
 
265
  \return -1 if map name is not fully qualified or file could not be opened.
 
266
  \return 1 otherwise.
 
267
*/
 
268
int Rast__quant_export(const char *name, const char *mapset,
 
269
                       const struct Quant *quant)
 
270
{
 
271
    char element[GNAME_MAX + 7];
 
272
    char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
 
273
    FILE *fd;
 
274
 
 
275
    if (G_name_is_fully_qualified(name, xname, xmapset)) {
 
276
        if (strcmp(xmapset, mapset) != 0)
 
277
            return -1;
 
278
        name = xname;
 
279
    }
 
280
 
 
281
    if (strcmp(G_mapset(), mapset) == 0) {
 
282
        G_remove_misc("cell_misc", QUANT_FILE_NAME, name);
 
283
        G__make_mapset_element_misc("cell_misc", name);
 
284
        if (!(fd = G_fopen_new_misc("cell_misc", QUANT_FILE_NAME, name)))
 
285
            return -1;
 
286
    }
 
287
    else {
 
288
        sprintf(element, "quant2/%s", mapset);
 
289
        G_remove(element, name);
 
290
        G_make_mapset_element(element);
 
291
        if (!(fd = G_fopen_new(element, name)))
 
292
            return -1;
 
293
    }
 
294
    
 
295
    quant_write(fd, quant);
 
296
    fclose(fd);
 
297
 
 
298
    return 1;
 
299
}