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