2
* \file lib/raster/quant_io.c
4
* \brief Raster Library - Quantization rules (input / output)
6
* (C) 1999-2010 by the GRASS Development Team
8
* This program is free software under the GNU General Public License
9
* (>=v2). Read the file COPYING that comes with GRASS for details.
11
* \author USACERL and many others
14
/**********************************************************************
16
**********************************************************************/
20
#include <grass/gis.h>
21
#include <grass/raster.h>
22
#include <grass/glocale.h>
24
#define QUANT_FILE_NAME "f_quant"
26
static int quant_parse_file(FILE *, struct Quant *);
29
/* redundant: integer range doesn't exist now: it is defined by
31
static int quant_load_range(struct Quant *quant, const char *name, const char *mapset)
33
struct FPRange fprange;
39
if (Rast_read_fp_range(name, mapset, &fprange) <= 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));
48
if (Rast_read_range(name, mapset, &range) < 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));
57
Rast_quant_add_rule(quant, dMin, dMax, min, max);
64
\brief Reads quantization rules (internal use only)
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
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.
79
Note: use Rast_quant_init() to allocate and initialize the quantization
80
staructure quant before the first usage of G_quant_import().
82
Note: this function uses Rast_quant_free () to clear all previously
83
stored rules in quant.
86
\param mapset mapset name
87
\param[out] quant pointer to Quant structure
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.
94
int Rast__quant_import(const char *name, const char *mapset,
98
char xname[GNAME_MAX], xmapset[GMAPSET_MAX], element[GNAME_MAX + 7];
102
Rast_quant_free(quant);
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));
111
if (G_name_is_fully_qualified(name, xname, xmapset)) {
112
if (strlen(mapset) == 0)
114
else if (strcmp(xmapset, mapset) != 0)
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);
127
"quantization file in quant2 for raster map <%s> is empty",
128
G_fully_qualified_name(name, mapset));
131
/* now try reading regular : cell_misc/name/quant file */
132
if (!(fd = G_fopen_old_misc("cell_misc", QUANT_FILE_NAME, name, mapset))) {
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));
139
parsStat = quant_parse_file(fd, quant);
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));
153
\brief Parse input lines with the following formats
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]) (**)
162
All other lines are ignored
164
(**) only the first appearances in the file are considered.
166
static int quant_parse_file(FILE * fd, struct Quant *quant)
171
int foundNegInf = 0, foundPosInf = 0;
173
while (fgets(buf, sizeof(buf), fd)) {
174
if (strncmp(buf, "truncate", 8) == 0) {
175
quant->truncate_only = 1;
178
if (strncmp(buf, "round", 5) == 0) {
179
quant->round_only = 1;
182
switch (sscanf(buf, "%lf:%lf:%d:%d", &dLow, &dHigh, &cLow, &cHigh)) {
184
Rast_quant_add_rule(quant, dLow, dHigh, cLow, cLow);
187
Rast_quant_add_rule(quant, dLow, dHigh, cLow, cHigh);
190
switch (sscanf(buf, "*:%lf:%d", &dLow, &cLow)) {
193
Rast_quant_set_neg_infinite_rule(quant, dLow, cLow);
198
switch (sscanf(buf, "%lf:*:%d", &dLow, &cLow)) {
201
Rast_quant_set_pos_infinite_rule(quant, dLow, cLow);
206
continue; /* other lines are ignored */
212
if (Rast_quant_nof_rules(quant) > 0)
213
Rast_quant_reverse_rule_order(quant);
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));
220
static void quant_write(FILE * fd, const struct Quant *quant)
226
if (quant->truncate_only) {
227
fprintf(fd, "truncate");
230
if (quant->round_only) {
231
fprintf(fd, "round");
234
if (Rast_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0)
235
fprintf(fd, "*:%.20g:%d\n", dLow, cLow);
237
if (Rast_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0)
238
fprintf(fd, "%.20g:*:%d\n", dLow, cLow);
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);
244
fprintf(fd, ":%d", cHigh);
250
\brief Writes the quantization rules (internal use only)
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).
259
Note: if no rules are defined an empty file is created.
262
\param mapset mapset name
263
\param quant pointer to Quant structure
265
\return -1 if map name is not fully qualified or file could not be opened.
268
int Rast__quant_export(const char *name, const char *mapset,
269
const struct Quant *quant)
271
char element[GNAME_MAX + 7];
272
char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
275
if (G_name_is_fully_qualified(name, xname, xmapset)) {
276
if (strcmp(xmapset, mapset) != 0)
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)))
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)))
295
quant_write(fd, quant);