GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-f22b1278f8
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,
32  const char *mapset)
33 {
34  struct FPRange fprange;
35  struct Range range;
36  char buf[300];
37  DCELL dMin, dMax;
38  CELL min, max;
39 
40  if (Rast_read_fp_range(name, mapset, &fprange) <= 0)
41  return 0;
42  Rast_get_fp_range_min_max(&fprange, &dMin, &dMax);
43  if (Rast_is_d_null_value(&dMin) || Rast_is_d_null_value(&dMax)) {
44  G_warning(_("Floating data range for raster map <%s> is empty"),
45  G_fully_qualified_name(name, mapset));
46  return -3;
47  }
48 
49  if (Rast_read_range(name, mapset, &range) < 0)
50  return 0;
51  Rast_get_range_min_max(&range, &min, &max);
53  G_warning(_("Integer data range for raster map <%s> is empty"),
54  G_fully_qualified_name(name, mapset));
55  return -3;
56  }
57 
58  Rast_quant_add_rule(quant, dMin, dMax, min, max);
59 
60  return 1;
61 }
62 #endif
63 
64 /*!
65  \brief Reads quantization rules (internal use only)
66 
67  Reads quantization rules for raster map <i>name</i> in <i>mapset</i>
68  and stores them in the quantization structure "quant". If the map is
69  in another mapset, first checks for quant2 table for this map in
70  current mapset.
71 
72  Note: in the case of negative return value, the result of using the
73  quantization structure is not defined.
74  in case of return value 0, calls to Rast_quant_perform_d()
75  and Rast_quant_perform_f() return NO_DATA (see description of
76  Rast_quant_perform_d() for more details). in case of
77  return values 2 and 3, the explicit rule for quant is set:
78  floating range is mapped to integer range.
79 
80  Note: use Rast_quant_init() to allocate and initialize the quantization
81  staructure quant before the first usage of G_quant_import().
82 
83  Note: this function uses Rast_quant_free () to clear all previously
84  stored rules in quant.
85 
86  \param name map name
87  \param mapset mapset name
88  \param[out] quant pointer to Quant structure
89 
90  \return -2 if raster map is of type integer.
91  \return -1 if map name is fully qualified and mapset is not the current one
92  \return 0 if quantization file does not exist, or the file is empty,
93  \return 1 if non-empty quantization file exists.
94  */
95 int Rast__quant_import(const char *name, const char *mapset,
96  struct Quant *quant)
97 {
98  char buf[1024];
99  char xname[GNAME_MAX], xmapset[GMAPSET_MAX], element[GNAME_MAX + 7];
100  int parsStat;
101  FILE *fd;
102 
103  Rast_quant_free(quant);
104 
105  if (Rast_map_type(name, mapset) == CELL_TYPE) {
106  char *mname = G_fully_qualified_name(name, mapset);
107  G_warning(_("Attempt to open quantization"
108  " table for CELL raster map <%s>"),
109  mname);
110  G_free(mname);
111  return -2;
112  }
113 
114  if (G_name_is_fully_qualified(name, xname, xmapset)) {
115  if (strlen(mapset) == 0)
116  mapset = xmapset;
117  else if (strcmp(xmapset, mapset) != 0)
118  return -1;
119  name = xname;
120  }
121 
122  /* first check if quant2/mapset/name exists in the current mapset */
123  sprintf(element, "quant2/%s", mapset);
124  if ((fd = G_fopen_old(element, name, G_mapset()))) {
125  parsStat = quant_parse_file(fd, quant);
126  fclose(fd);
127  if (parsStat)
128  return 1;
129  sprintf(buf, "quantization file in quant2 for raster map <%s> is empty",
130  G_fully_qualified_name(name, mapset));
131  }
132 
133  /* now try reading regular : cell_misc/name/quant file */
134  if (!(fd = G_fopen_old_misc("cell_misc", QUANT_FILE_NAME, name, mapset))) {
135 
136  /* int range doesn't exist anymore if (quant_load_range (quant, name,
137  * mapset)>0) return 3; */
138  char *mname = G_fully_qualified_name(name, mapset);
139  G_warning(_("Quantization file for raster map <%s> is missing"), mname);
140  G_free(mname);
141  }
142  else {
143  parsStat = quant_parse_file(fd, quant);
144  fclose(fd);
145 
146  if (parsStat)
147  return 1;
148  /* int range doesn't exist anymore if (quant_load_range (quant, name,
149  * mapset)>0) return 2; */
150  G_warning(_("Quantization file for raster map <%s> is empty"),
151  G_fully_qualified_name(name, mapset));
152  }
153 
154  return 0;
155 }
156 
157 /*!
158  \brief Parse input lines with the following formats
159 
160  \code
161  d_high:d_low:c_high:c_low
162  d_high:d_low:c_val (i.e. c_high == c_low)
163  *:d_val:c_val (interval [inf, d_val]) (**)
164  d_val:*:c_val (interval [d_val, inf]) (**)
165  \endcode
166 
167  All other lines are ignored
168 
169  (**) only the first appearances in the file are considered.
170  */
171 static int quant_parse_file(FILE *fd, struct Quant *quant)
172 {
173  CELL cLow, cHigh;
174  DCELL dLow, dHigh;
175  char buf[1024];
176  int foundNegInf = 0, foundPosInf = 0;
177 
178  while (fgets(buf, sizeof(buf), fd)) {
179  if (strncmp(buf, "truncate", 8) == 0) {
180  quant->truncate_only = 1;
181  return 1;
182  }
183  if (strncmp(buf, "round", 5) == 0) {
184  quant->round_only = 1;
185  return 1;
186  }
187  switch (sscanf(buf, "%lf:%lf:%d:%d", &dLow, &dHigh, &cLow, &cHigh)) {
188  case 3:
189  Rast_quant_add_rule(quant, dLow, dHigh, cLow, cLow);
190  break;
191  case 4:
192  Rast_quant_add_rule(quant, dLow, dHigh, cLow, cHigh);
193  break;
194  default:
195  switch (sscanf(buf, "*:%lf:%d", &dLow, &cLow)) {
196  case 2:
197  if (!foundNegInf) {
198  Rast_quant_set_neg_infinite_rule(quant, dLow, cLow);
199  foundNegInf = 1;
200  }
201  break;
202  default:
203  switch (sscanf(buf, "%lf:*:%d", &dLow, &cLow)) {
204  case 2:
205  if (!foundPosInf) {
206  Rast_quant_set_pos_infinite_rule(quant, dLow, cLow);
207  foundPosInf = 1;
208  }
209  break;
210  default:
211  continue; /* other lines are ignored */
212  }
213  }
214  }
215  }
216 
217  if (Rast_quant_nof_rules(quant) > 0)
219 
220  return ((Rast_quant_nof_rules(quant) > 0) ||
221  (Rast_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0) ||
222  (Rast_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0));
223 }
224 
225 static void quant_write(FILE *fd, const struct Quant *quant)
226 {
227  DCELL dLow, dHigh;
228  CELL cLow, cHigh;
229  int i;
230 
231  if (quant->truncate_only) {
232  fprintf(fd, "truncate");
233  return;
234  }
235  if (quant->round_only) {
236  fprintf(fd, "round");
237  return;
238  }
239  if (Rast_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0)
240  fprintf(fd, "*:%.20g:%d\n", dLow, cLow);
241 
242  if (Rast_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0)
243  fprintf(fd, "%.20g:*:%d\n", dLow, cLow);
244 
245  for (i = Rast_quant_nof_rules(quant) - 1; i >= 0; i--) {
246  Rast_quant_get_ith_rule(quant, i, &dLow, &dHigh, &cLow, &cHigh);
247  fprintf(fd, "%.20g:%.20g:%d", dLow, dHigh, cLow);
248  if (cLow != cHigh)
249  fprintf(fd, ":%d", cHigh);
250  fprintf(fd, "\n");
251  }
252 }
253 
254 /*!
255  \brief Writes the quantization rules (internal use only)
256 
257  Writes the quantization rules stored in <i>quant</i> for <i>name</i>
258  . If the mapset is the same as the current mapset, the quant file is
259  created in 'cell_misc/name' directory, otherwise it is created in
260  'quant2/mapset' directory, much like writing colors for map in
261  another mapset. The rules are written in decreasing order of
262  priority (i.e. rules added earlier are written later).
263 
264  Note: if no rules are defined an empty file is created.
265 
266  \param name map name
267  \param mapset mapset name
268  \param quant pointer to Quant structure
269 
270  \return -1 if map name is not fully qualified or file could not be opened.
271  \return 1 otherwise.
272  */
273 int Rast__quant_export(const char *name, const char *mapset,
274  const struct Quant *quant)
275 {
276  char element[GNAME_MAX + 7];
277  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
278  FILE *fd;
279 
280  if (G_name_is_fully_qualified(name, xname, xmapset)) {
281  if (strcmp(xmapset, mapset) != 0)
282  return -1;
283  name = xname;
284  }
285 
286  if (strcmp(G_mapset(), mapset) == 0) {
287  G_remove_misc("cell_misc", QUANT_FILE_NAME, name);
288  G__make_mapset_element_misc("cell_misc", name);
289  if (!(fd = G_fopen_new_misc("cell_misc", QUANT_FILE_NAME, name)))
290  return -1;
291  }
292  else {
293  sprintf(element, "quant2/%s", mapset);
296  if (!(fd = G_fopen_new(element, name)))
297  return -1;
298  }
299 
300  quant_write(fd, quant);
301  fclose(fd);
302 
303  return 1;
304 }
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
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition: gis/open.c:251
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
FILE * G_fopen_old_misc(const char *, const char *, const char *, const char *)
open a database misc file for reading
Definition: open_misc.c:205
int G__make_mapset_element_misc(const char *, const char *)
Create misc element in the current mapset.
Definition: mapset_msc.c:260
void G_warning(const char *,...) __attribute__((format(printf
int G_make_mapset_object_group(const char *)
Create directory for group of elements of a given type.
Definition: mapset_msc.c:74
FILE * G_fopen_new_misc(const char *, const char *, const char *)
open a new database misc file
Definition: open_misc.c:178
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
int G_remove(const char *, const char *)
Remove a database file.
Definition: remove.c:44
int G_remove_misc(const char *, const char *, const char *)
Remove a database misc file.
Definition: remove.c:65
char * G_fully_qualified_name(const char *, const char *)
Get fully qualified element name.
Definition: nme_in_mps.c:101
FILE * G_fopen_new(const char *, const char *)
Open a new database file.
Definition: gis/open.c:219
int Rast_quant_get_neg_infinite_rule(const struct Quant *, DCELL *, CELL *)
Returns in "dLeft" and "c" the rule values.
Definition: quant.c:390
int Rast_read_fp_range(const char *, const char *, struct FPRange *)
Read floating-point range.
Definition: raster/range.c:71
void Rast_quant_set_pos_infinite_rule(struct Quant *, DCELL, CELL)
Defines a rule for values "dRight" and larger.
Definition: quant.c:412
void Rast_quant_free(struct Quant *)
Resets and frees allocated memory.
Definition: quant.c:55
void Rast_quant_set_neg_infinite_rule(struct Quant *, DCELL, CELL)
Defines a rule for values "dLeft" and smaller.
Definition: quant.c:364
void Rast_get_fp_range_min_max(const struct FPRange *, DCELL *, DCELL *)
Get minimum and maximum value from fp range.
Definition: raster/range.c:768
void Rast_quant_reverse_rule_order(struct Quant *)
Rreverses the order in which the qunatization rules are stored.
Definition: quant.c:513
RASTER_MAP_TYPE Rast_map_type(const char *, const char *)
Determine raster data type.
Definition: raster/open.c:894
void Rast_quant_add_rule(struct Quant *, DCELL, DCELL, CELL, CELL)
Adds a new rule to the set of quantization rules.
Definition: quant.c:469
void Rast_get_range_min_max(const struct Range *, CELL *, CELL *)
Get range min and max.
Definition: raster/range.c:718
int Rast_read_range(const char *, const char *, struct Range *)
Read raster range (CELL)
Definition: raster/range.c:160
void Rast_quant_get_ith_rule(const struct Quant *, int, DCELL *, DCELL *, CELL *, CELL *)
Returns the i'th quantization rule.
Definition: quant.c:327
int Rast_quant_get_pos_infinite_rule(const struct Quant *, DCELL *, CELL *)
Returns in "dRight" and "c" the rule values.
Definition: quant.c:438
#define Rast_is_d_null_value(dcellVal)
Definition: defs/raster.h:412
#define Rast_is_c_null_value(cellVal)
Definition: defs/raster.h:408
int Rast_quant_nof_rules(const struct Quant *)
Returns the number of quantization rules defined.
Definition: quant.c:309
#define min(x, y)
Definition: draw2.c:29
#define max(x, y)
Definition: draw2.c:30
#define GMAPSET_MAX
Definition: gis.h:192
#define GNAME_MAX
Definition: gis.h:191
double DCELL
Definition: gis.h:629
int CELL
Definition: gis.h:628
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:6
#define QUANT_FILE_NAME
Definition: quant_io.c:24
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:273
int Rast__quant_import(const char *name, const char *mapset, struct Quant *quant)
Reads quantization rules (internal use only)
Definition: quant_io.c:95
#define CELL_TYPE
Definition: raster.h:11
Definition: raster.h:80
int truncate_only
Definition: raster.h:81
int round_only
Definition: raster.h:82
Definition: raster.h:220
Definition: lidar.h:85