GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
quant_io.c
Go to the documentation of this file.
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)
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);
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 }
#define CELL_TYPE
Definition: raster.h:11
int G_remove(const char *, const char *)
Remove a database file.
Definition: remove.c:44
#define GMAPSET_MAX
Definition: gis.h:178
int Rast_quant_get_pos_infinite_rule(const struct Quant *, DCELL *, CELL *)
Returns in "dRight" and "c" the rule values.
Definition: quant.c:442
#define Rast_is_d_null_value(dcellVal)
Definition: defs/raster.h:414
#define min(x, y)
Definition: draw2.c:31
double DCELL
Definition: gis.h:614
int G__make_mapset_element_misc(const char *, const char *)
Create misc element in the current mapset.
Definition: mapset_msc.c:232
#define max(x, y)
Definition: draw2.c:32
int G_remove_misc(const char *, const char *, const char *)
Remove a database misc file.
Definition: remove.c:65
int Rast_quant_nof_rules(const struct Quant *)
Returns the number of quantization rules defined.
Definition: quant.c:310
int Rast_read_range(const char *, const char *, struct Range *)
Read raster range (CELL)
Definition: range.c:160
int truncate_only
Definition: raster.h:86
void Rast_quant_free(struct Quant *)
Resets and frees allocated memory.
Definition: quant.c:55
Definition: lidar.h:86
int Rast__quant_import(const char *name, const char *mapset, struct Quant *quant)
Reads quantization rules (internal use only)
Definition: quant_io.c:94
void Rast_get_fp_range_min_max(const struct FPRange *, DCELL *, DCELL *)
Get minimum and maximum value from fp range.
Definition: range.c:764
FILE * G_fopen_new(const char *, const char *)
Open a new database file.
Definition: gis/open.c:220
char * G_fully_qualified_name(const char *, const char *)
Get fully qualified element name.
Definition: nme_in_mps.c:101
Definition: raster.h:84
FILE * G_fopen_old_misc(const char *, const char *, const char *, const char *)
open a database misc file for reading
Definition: open_misc.c:210
int Rast_quant_get_neg_infinite_rule(const struct Quant *, DCELL *, CELL *)
Returns in "dLeft" and "c" the rule values.
Definition: quant.c:394
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition: gis/open.c:253
void Rast_quant_set_pos_infinite_rule(struct Quant *, DCELL, CELL)
Defines a rule for values "dRight" and larger.
Definition: quant.c:416
Definition: raster.h:225
int Rast_read_fp_range(const char *, const char *, struct FPRange *)
Read floating-point range.
Definition: range.c:71
FILE * G_fopen_new_misc(const char *, const char *, const char *)
open a new database misc file
Definition: open_misc.c:182
void Rast_quant_add_rule(struct Quant *, DCELL, DCELL, CELL, CELL)
Adds a new rule to the set of quantization rules.
Definition: quant.c:473
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
void Rast_quant_get_ith_rule(const struct Quant *, int, DCELL *, DCELL *, CELL *, CELL *)
Returns the i&#39;th quantization rule.
Definition: quant.c:328
#define GNAME_MAX
Definition: gis.h:177
void G_warning(const char *,...) __attribute__((format(printf
int CELL
Definition: gis.h:613
int round_only
Definition: raster.h:87
#define _(str)
Definition: glocale.h:10
void Rast_quant_set_neg_infinite_rule(struct Quant *, DCELL, CELL)
Defines a rule for values "dLeft" and smaller.
Definition: quant.c:368
const char * name
Definition: named_colr.c:7
int G_name_is_fully_qualified(const char *, char *, char *)
Check if map name is fully qualified (map @ mapset)
Definition: nme_in_mps.c:36
#define QUANT_FILE_NAME
Definition: quant_io.c:24
#define Rast_is_c_null_value(cellVal)
Definition: defs/raster.h:410
int Rast__quant_export(const char *name, const char *mapset, const struct Quant *quant)
Writes the quantization rules (internal use only)
Definition: quant_io.c:268
int G_make_mapset_object_group(const char *)
Create directory for group of elements of a given type.
Definition: mapset_msc.c:74
void Rast_quant_reverse_rule_order(struct Quant *)
Rreverses the order in which the qunatization rules are stored.
Definition: quant.c:517
void Rast_get_range_min_max(const struct Range *, CELL *, CELL *)
Get range min and max.
Definition: range.c:714
RASTER_MAP_TYPE Rast_map_type(const char *, const char *)
Determine raster data type.
Definition: raster/open.c:880