GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-299a28a7d0
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  snprintf(element, sizeof(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  snprintf(buf, sizeof(buf),
130  "quantization file in quant2 for raster map <%s> is empty",
131  G_fully_qualified_name(name, mapset));
132  }
133 
134  /* now try reading regular : cell_misc/name/quant file */
135  if (!(fd = G_fopen_old_misc("cell_misc", QUANT_FILE_NAME, name, mapset))) {
136 
137  /* int range doesn't exist anymore if (quant_load_range (quant, name,
138  * mapset)>0) return 3; */
139  char *mname = G_fully_qualified_name(name, mapset);
140  G_warning(_("Quantization file for raster map <%s> is missing"), mname);
141  G_free(mname);
142  }
143  else {
144  parsStat = quant_parse_file(fd, quant);
145  fclose(fd);
146 
147  if (parsStat)
148  return 1;
149  /* int range doesn't exist anymore if (quant_load_range (quant, name,
150  * mapset)>0) return 2; */
151  G_warning(_("Quantization file for raster map <%s> is empty"),
152  G_fully_qualified_name(name, mapset));
153  }
154 
155  return 0;
156 }
157 
158 /*!
159  \brief Parse input lines with the following formats
160 
161  \code
162  d_high:d_low:c_high:c_low
163  d_high:d_low:c_val (i.e. c_high == c_low)
164  *:d_val:c_val (interval [inf, d_val]) (**)
165  d_val:*:c_val (interval [d_val, inf]) (**)
166  \endcode
167 
168  All other lines are ignored
169 
170  (**) only the first appearances in the file are considered.
171  */
172 static int quant_parse_file(FILE *fd, struct Quant *quant)
173 {
174  CELL cLow, cHigh;
175  DCELL dLow, dHigh;
176  char buf[1024];
177  int foundNegInf = 0, foundPosInf = 0;
178 
179  while (fgets(buf, sizeof(buf), fd)) {
180  if (strncmp(buf, "truncate", 8) == 0) {
181  quant->truncate_only = 1;
182  return 1;
183  }
184  if (strncmp(buf, "round", 5) == 0) {
185  quant->round_only = 1;
186  return 1;
187  }
188  switch (sscanf(buf, "%lf:%lf:%d:%d", &dLow, &dHigh, &cLow, &cHigh)) {
189  case 3:
190  Rast_quant_add_rule(quant, dLow, dHigh, cLow, cLow);
191  break;
192  case 4:
193  Rast_quant_add_rule(quant, dLow, dHigh, cLow, cHigh);
194  break;
195  default:
196  switch (sscanf(buf, "*:%lf:%d", &dLow, &cLow)) {
197  case 2:
198  if (!foundNegInf) {
199  Rast_quant_set_neg_infinite_rule(quant, dLow, cLow);
200  foundNegInf = 1;
201  }
202  break;
203  default:
204  switch (sscanf(buf, "%lf:*:%d", &dLow, &cLow)) {
205  case 2:
206  if (!foundPosInf) {
207  Rast_quant_set_pos_infinite_rule(quant, dLow, cLow);
208  foundPosInf = 1;
209  }
210  break;
211  default:
212  continue; /* other lines are ignored */
213  }
214  }
215  }
216  }
217 
218  if (Rast_quant_nof_rules(quant) > 0)
220 
221  return ((Rast_quant_nof_rules(quant) > 0) ||
222  (Rast_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0) ||
223  (Rast_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0));
224 }
225 
226 static void quant_write(FILE *fd, const struct Quant *quant)
227 {
228  DCELL dLow, dHigh;
229  CELL cLow, cHigh;
230  int i;
231 
232  if (quant->truncate_only) {
233  fprintf(fd, "truncate");
234  return;
235  }
236  if (quant->round_only) {
237  fprintf(fd, "round");
238  return;
239  }
240  if (Rast_quant_get_neg_infinite_rule(quant, &dLow, &cLow) > 0)
241  fprintf(fd, "*:%.20g:%d\n", dLow, cLow);
242 
243  if (Rast_quant_get_pos_infinite_rule(quant, &dLow, &cLow) > 0)
244  fprintf(fd, "%.20g:*:%d\n", dLow, cLow);
245 
246  for (i = Rast_quant_nof_rules(quant) - 1; i >= 0; i--) {
247  Rast_quant_get_ith_rule(quant, i, &dLow, &dHigh, &cLow, &cHigh);
248  fprintf(fd, "%.20g:%.20g:%d", dLow, dHigh, cLow);
249  if (cLow != cHigh)
250  fprintf(fd, ":%d", cHigh);
251  fprintf(fd, "\n");
252  }
253 }
254 
255 /*!
256  \brief Writes the quantization rules (internal use only)
257 
258  Writes the quantization rules stored in <i>quant</i> for <i>name</i>
259  . If the mapset is the same as the current mapset, the quant file is
260  created in 'cell_misc/name' directory, otherwise it is created in
261  'quant2/mapset' directory, much like writing colors for map in
262  another mapset. The rules are written in decreasing order of
263  priority (i.e. rules added earlier are written later).
264 
265  Note: if no rules are defined an empty file is created.
266 
267  \param name map name
268  \param mapset mapset name
269  \param quant pointer to Quant structure
270 
271  \return -1 if map name is not fully qualified or file could not be opened.
272  \return 1 otherwise.
273  */
274 int Rast__quant_export(const char *name, const char *mapset,
275  const struct Quant *quant)
276 {
277  char element[GNAME_MAX + 7];
278  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
279  FILE *fd;
280 
281  if (G_name_is_fully_qualified(name, xname, xmapset)) {
282  if (strcmp(xmapset, mapset) != 0)
283  return -1;
284  name = xname;
285  }
286 
287  if (strcmp(G_mapset(), mapset) == 0) {
288  G_remove_misc("cell_misc", QUANT_FILE_NAME, name);
289  G__make_mapset_element_misc("cell_misc", name);
290  if (!(fd = G_fopen_new_misc("cell_misc", QUANT_FILE_NAME, name)))
291  return -1;
292  }
293  else {
294  snprintf(element, sizeof(element), "quant2/%s", mapset);
297  if (!(fd = G_fopen_new(element, name)))
298  return -1;
299  }
300 
301  quant_write(fd, quant);
302  fclose(fd);
303 
304  return 1;
305 }
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:261
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:75
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:785
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:735
int Rast_read_range(const char *, const char *, struct Range *)
Read raster range (CELL)
Definition: raster/range.c:163
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:414
#define Rast_is_c_null_value(cellVal)
Definition: defs/raster.h:410
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:191
#define GNAME_MAX
Definition: gis.h:190
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:274
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