GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-e07a2894ef
raster3d/color.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/types.h>
5 #include <unistd.h>
6 
7 #include <grass/gis.h>
8 #include <grass/raster.h>
9 #include <grass/glocale.h>
10 
11 #include "raster3d_intern.h"
12 
13 static int read_colors(const char *, const char *, struct Colors *);
14 static int read_new_colors(FILE *, struct Colors *);
15 static int read_old_colors(FILE *, struct Colors *);
16 
17 /*---------------------------------------------------------------------------*/
18 
19 /*!
20  \brief Removes the primary and/or secondary color file.
21 
22  \todo Is <em>primary and/or secondary color file</em> still valid for 7?
23 
24  \see G_remove_colr
25  */
26 int Rast3d_remove_color(const char *name)
27 /* adapted from G_remove_colr */
28 {
30 }
31 
32 /*---------------------------------------------------------------------------*/
33 
34 /*!
35  \brief Reads color file for map \p name in \p mapset into the Colors
36  structure.
37 
38  \param name 3D raster map name
39  \param mapset mapset name
40  \param colors colors to be associated with a map
41 
42  \see Rast3d_write_colors, Rast_read_colors
43  */
44 int Rast3d_read_colors(const char *name, const char *mapset,
45  struct Colors *colors)
46 /* adapted from Rast_read_colors */
47 {
48  const char *err;
49  struct FPRange drange;
50  DCELL dmin, dmax;
51 
52  Rast_init_colors(colors);
53 
54  Rast_mark_colors_as_fp(colors);
55 
56  switch (read_colors(name, mapset, colors)) {
57  case -2:
58  if (Rast3d_read_range(name, mapset, &drange) >= 0) {
59  Rast_get_fp_range_min_max(&drange, &dmin, &dmax);
60  if (!Rast_is_d_null_value(&dmin) && !Rast_is_d_null_value(&dmax))
61  Rast_make_fp_colors(colors, DEFAULT_COLOR_TABLE, dmin, dmax);
62  return 0;
63  }
64  err = "missing";
65  break;
66  case -1:
67  err = "invalid";
68  break;
69  default:
70  return 1;
71  }
72 
73  G_warning("color support for [%s] in mapset [%s] %s", name, mapset, err);
74  return -1;
75 }
76 
77 static int read_colors(const char *name, const char *mapset,
78  struct Colors *colors)
79 {
80  FILE *fd;
81  int stat;
82  char buf[1024];
83 
85  mapset);
86  if (!fd)
87  return -2;
88 
89  /*
90  * first line in 4.0 color files is %
91  * otherwise it is pre 4.0
92  */
93  if (fgets(buf, sizeof buf, fd) == NULL) {
94  fclose(fd);
95  return -1;
96  }
97  G_fseek(fd, 0L, 0);
98 
99  G_strip(buf);
100  if (*buf == '%') { /* 4.0 format */
101  stat = read_new_colors(fd, colors);
102  colors->version = 0; /* 4.0 format */
103  }
104  else {
105  stat = read_old_colors(fd, colors);
106  colors->version = -1; /* pre 4.0 format */
107  }
108  fclose(fd);
109  return stat;
110 }
111 
112 /* parse input lines with the following formats
113  * val1:r:g:b val2:r:g:b
114  * val:r:g:b (implies cat1==cat2)
115  *
116  * r:g:b can be just a single grey level
117  * cat1:x cat2:y
118  * cat:x
119  *
120  * optional lines are
121  * invert invert color table
122  * shift:n where n is the amount to shift the color table
123  */
124 static int read_new_colors(FILE *fd, struct Colors *colors)
125 {
126  double val1, val2;
127  long cat1, cat2;
128  int r1, g1, b1;
129  int r2, g2, b2;
130  char buf[1024];
131  char word1[256], word2[256];
132  int n, fp_rule;
133  int null, undef;
134  int modular;
135  DCELL shift;
136 
137  if (fgets(buf, sizeof buf, fd) == NULL)
138  return -1;
139  G_strip(buf);
140 
141  if (sscanf(buf + 1, "%lf %lf", &val1, &val2) == 2)
142  Rast_set_d_color_range((DCELL)val1, (DCELL)val2, colors);
143 
144  modular = 0;
145  while (fgets(buf, sizeof buf, fd)) {
146  null = undef = fp_rule = 0;
147  *word1 = *word2 = 0;
148  n = sscanf(buf, "%s %s", word1, word2);
149  if (n < 1)
150  continue;
151 
152  if (sscanf(word1, "shift:%lf", &shift) == 1 ||
153  (strcmp(word1, "shift:") == 0 &&
154  sscanf(word2, "%lf", &shift) == 1)) {
155  Rast_shift_d_colors(shift, colors);
156  continue;
157  }
158  if (strcmp(word1, "invert") == 0) {
159  Rast_invert_colors(colors);
160  continue;
161  }
162  if (strcmp(word1, "%%") == 0) {
163  modular = !modular;
164  continue;
165  }
166 
167  switch (sscanf(word1, "nv:%d:%d:%d", &r1, &g1, &b1)) {
168  case 1:
169  null = 1;
170  b1 = g1 = r1;
171  break;
172  case 3:
173  null = 1;
174  break;
175  }
176  if (!null)
177  switch (sscanf(word1, "*:%d:%d:%d", &r1, &g1, &b1)) {
178  case 1:
179  undef = 1;
180  b1 = g1 = r1;
181  break;
182  case 3:
183  undef = 1;
184  break;
185  }
186  if (!null && !undef)
187  switch (sscanf(word1, "%ld:%d:%d:%d", &cat1, &r1, &g1, &b1)) {
188  case 2:
189  b1 = g1 = r1;
190  break;
191  case 4:
192  break;
193  default:
194  if (sscanf(word1, "%lf:%d:%d:%d", &val1, &r1, &g1, &b1) == 4)
195  fp_rule = 1;
196  else if (sscanf(word1, "%lf:%d", &val1, &r1) == 2) {
197  fp_rule = 1;
198  b1 = g1 = r1;
199  }
200  else
201  continue; /* other lines are ignored */
202  }
203  if (n == 2) {
204  switch (sscanf(word2, "%ld:%d:%d:%d", &cat2, &r2, &g2, &b2)) {
205  case 2:
206  b2 = g2 = r2;
207  if (fp_rule)
208  val2 = (DCELL)cat2;
209  break;
210  case 4:
211  if (fp_rule)
212  val2 = (DCELL)cat2;
213  break;
214  default:
215  if (sscanf(word2, "%lf:%d:%d:%d", &val2, &r2, &g2, &b2) == 4) {
216  if (!fp_rule)
217  val1 = (DCELL)cat1;
218  fp_rule = 1;
219  }
220  else if (sscanf(word2, "%lf:%d", &val2, &r2) == 2) {
221  if (!fp_rule)
222  val1 = (DCELL)cat1;
223  fp_rule = 1;
224  b2 = g2 = r2;
225  }
226  else
227  continue; /* other lines are ignored */
228  }
229  }
230  else {
231  if (!fp_rule)
232  cat2 = cat1;
233  else
234  val2 = val1;
235  r2 = r1;
236  g2 = g1;
237  b2 = b1;
238  }
239  if (null)
240  Rast_set_null_value_color(r1, g1, b1, colors);
241  else if (undef)
242  Rast_set_default_color(r1, g1, b1, colors);
243 
244  else if (modular) {
245  if (fp_rule)
246  Rast_add_modular_d_color_rule((DCELL *)&val1, r1, g1, b1,
247  (DCELL *)&val2, r2, g2, b2,
248  colors);
249  else
250  Rast_add_modular_c_color_rule((CELL *)&cat1, r1, g1, b1,
251  (CELL *)&cat2, r2, g2, b2,
252  colors);
253  }
254  else {
255  if (fp_rule)
256  Rast_add_d_color_rule((DCELL *)&val1, r1, g1, b1,
257  (DCELL *)&val2, r2, g2, b2, colors);
258  else
259  Rast_add_c_color_rule((CELL *)&cat1, r1, g1, b1, (CELL *)&cat2,
260  r2, g2, b2, colors);
261  }
262  /*
263  fprintf (stderr, "adding rule %d=%.2lf %d %d %d %d=%.2lf %d %d
264  %d\n", cat1,val1, r1, g1, b1, cat2, val2, r2, g2, b2);
265  */
266  }
267  return 1;
268 }
269 
270 static int read_old_colors(FILE *fd, struct Colors *colors)
271 {
272  char buf[256];
273  long n;
274  long min;
275  float red_f, grn_f, blu_f;
276  int red, grn, blu;
277  int old;
278  int zero;
279 
280  Rast_init_colors(colors);
281  /*
282  * first line in pre 3.0 color files is number of colors - ignore
283  * otherwise it is #min first color, and the next line is for color 0
284  */
285  if (fgets(buf, sizeof buf, fd) == NULL)
286  return -1;
287 
288  G_strip(buf);
289  if (*buf == '#') { /* 3.0 format */
290  old = 0;
291  if (sscanf(buf + 1, "%ld", &min) != 1) /* first color */
292  return -1;
293  zero = 1;
294  }
295  else {
296  old = 1;
297  min = 0;
298  zero = 0;
299  }
300 
301  colors->cmin = min;
302  n = min;
303  while (fgets(buf, sizeof buf, fd)) {
304  if (old) {
305  if (sscanf(buf, "%f %f %f", &red_f, &grn_f, &blu_f) != 3)
306  return -1;
307 
308  red = 256 * red_f;
309  grn = 256 * grn_f;
310  blu = 256 * blu_f;
311  }
312  else {
313  switch (sscanf(buf, "%d %d %d", &red, &grn, &blu)) {
314  case 1:
315  blu = grn = red;
316  break;
317  case 2:
318  blu = grn;
319  break;
320  case 3:
321  break;
322  default:
323  return -1;
324  }
325  }
326  if (zero) {
327  Rast__insert_color_into_lookup((CELL)0, red, grn, blu,
328  &colors->fixed);
329  zero = 0;
330  }
331  else
332  Rast__insert_color_into_lookup((CELL)n++, red, grn, blu,
333  &colors->fixed);
334  }
335  colors->cmax = n - 1;
336 
337  return 0;
338 }
339 
340 /*---------------------------------------------------------------------------*/
341 
342 /*!
343  \brief Writes the \p colors for map \p name in \p mapset into a color file.
344 
345  \param name 3D raster map name
346  \param mapset mapset name
347  \param colors colors to be associated with a map
348 
349  \see Rast3d_read_colors, Rast3d_remove_color, Rast_write_colors
350  */
351 int Rast3d_write_colors(const char *name, const char *mapset,
352  struct Colors *colors)
353 /* adapted from Rast_write_colors */
354 {
355  FILE *fd;
356 
357  if (strcmp(mapset, G_mapset()) != 0) {
358  G_warning(_("mapset <%s> is not the current mapset"), mapset);
359  return -1;
360  }
361 
363  if (!fd)
364  return -1;
365 
366  Rast__write_colors(fd, colors);
367  fclose(fd);
368 
369  return 1;
370 }
371 
372 /*---------------------------------------------------------------------------*/
373 
374 /*---------------------------------------------------------------------------*/
375 
376 /*---------------------------------------------------------------------------*/
#define NULL
Definition: ccmath.h:32
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
void G_warning(const char *,...) __attribute__((format(printf
void G_fseek(FILE *, off_t, int)
Change the file position of the stream.
Definition: gis/seek.c:50
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_misc(const char *, const char *, const char *)
Remove a database misc file.
Definition: remove.c:65
void G_strip(char *)
Removes all leading and trailing white space from string.
Definition: strings.c:300
int Rast3d_read_range(const char *, const char *, struct FPRange *)
void Rast_add_d_color_rule(const DCELL *, int, int, int, const DCELL *, int, int, int, struct Colors *)
Adds the floating-point color rule (DCELL version)
Definition: color_rule.c:38
int Rast__insert_color_into_lookup(CELL, int, int, int, struct _Color_Info_ *)
Definition: color_insrt.c:18
void Rast_set_null_value_color(int, int, int, struct Colors *)
Set color for NULL-value.
Definition: color_set.c:79
int Rast_add_modular_c_color_rule(const CELL *, int, int, int, const CELL *, int, int, int, struct Colors *)
Add modular integer color rule (CELL version)
Definition: color_rule.c:184
void Rast_mark_colors_as_fp(struct Colors *)
Mark colors as floating-point.
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_add_c_color_rule(const CELL *, int, int, int, const CELL *, int, int, int, struct Colors *)
Adds the integer color rule (CELL version)
Definition: color_rule.c:76
void Rast_init_colors(struct Colors *)
Initialize color structure.
Definition: color_init.c:25
void Rast_set_d_color_range(DCELL, DCELL, struct Colors *)
Set color range (DCELL version)
Definition: color_range.c:42
void Rast__write_colors(FILE *, struct Colors *)
Write map layer color table.
int Rast_add_modular_d_color_rule(const DCELL *, int, int, int, const DCELL *, int, int, int, struct Colors *)
Add modular floating-point color rule (DCELL version)
Definition: color_rule.c:124
void Rast_make_fp_colors(struct Colors *, const char *, DCELL, DCELL)
Load color rules from predefined floating-point color table.
#define Rast_is_d_null_value(dcellVal)
Definition: defs/raster.h:405
void Rast_invert_colors(struct Colors *)
Definition: color_invrt.c:17
void Rast_set_default_color(int, int, int, struct Colors *)
Set default color value.
Definition: color_set.c:99
void Rast_shift_d_colors(DCELL, struct Colors *)
Definition: color_shift.c:22
#define min(x, y)
Definition: draw2.c:29
#define DEFAULT_COLOR_TABLE
Definition: gis.h:400
double DCELL
Definition: gis.h:628
int CELL
Definition: gis.h:627
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:6
int Rast3d_write_colors(const char *name, const char *mapset, struct Colors *colors)
Writes the colors for map name in mapset into a color file.
int Rast3d_read_colors(const char *name, const char *mapset, struct Colors *colors)
Reads color file for map name in mapset into the Colors structure.
int Rast3d_remove_color(const char *name)
Removes the primary and/or secondary color file.
#define RASTER3D_COLOR_ELEMENT
Definition: raster3d.h:37
#define RASTER3D_DIRECTORY
Definition: raster3d.h:31
Definition: gis.h:685
DCELL cmax
Definition: gis.h:701
struct _Color_Info_ fixed
Definition: gis.h:698
int version
Definition: gis.h:686
DCELL cmin
Definition: gis.h:700
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:216