GRASS Programmer's Manual  6.4.3(2013)-r
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
color_rules.c
Go to the documentation of this file.
1 
2 /****************************************************************************
3  *
4  * MODULE: gis library
5  * AUTHOR(S): Glynn Clements <glynn@gclements.plus.com>
6  * COPYRIGHT: (C) 2007 Glynn Clements and the GRASS Development Team
7  *
8  * NOTE: Based upon r.colors/rules.c
9  * The colors are stored in ./colors/
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  *****************************************************************************/
22 
23 #include <stdio.h>
24 #include <grass/gis.h>
25 #include <grass/glocale.h>
26 
27 struct rule
28 {
29  int set;
30  int r, g, b;
31  DCELL val;
32 };
33 
35 {
36  CR_OK = 0,
42 };
43 
44 int G_parse_color_rule(DCELL min, DCELL max, const char *buf,
45  DCELL * val, int *r, int *g, int *b,
46  int *norm, int *nval, int *dflt)
47 {
48  char value[80], color[80];
49  double x;
50  char c;
51 
52  *norm = *nval = *dflt = 0;
53 
54  if (sscanf(buf, "%s %[^\n]", value, color) != 2)
55  return CR_ERROR_SYNTAX;
56 
57  G_chop(color);
58 
59  if (sscanf(color, "%d:%d:%d", r, g, b) == 3 ||
60  sscanf(color, "%d %d %d", r, g, b) == 3) {
61  if (*r < 0 || *r > 255 || *g < 0 || *g > 255 || *b < 0 || *b > 255)
62  return CR_ERROR_RGB;
63  }
64  else {
65  float fr, fg, fb;
66 
67  if (G_color_values(color, &fr, &fg, &fb) < 0)
68  return CR_ERROR_COLOR;
69 
70  *r = (int)(fr * 255.99);
71  *g = (int)(fg * 255.99);
72  *b = (int)(fb * 255.99);
73  }
74 
75  G_chop(value);
76 
77  if (G_strcasecmp(value, "default") == 0) {
78  *dflt = 1;
79  return CR_OK;
80  }
81 
82  if (G_strcasecmp(value, "nv") == 0) {
83  *nval = 1;
84  return CR_OK;
85  }
86 
87  if (sscanf(value, "%lf%c", &x, &c) == 2 && c == '%') {
88  if (x < 0 || x > 100)
89  return CR_ERROR_PERCENT;
90 
91  *val = min + (max - min) * (x / 100);
92  *norm = 1;
93  return CR_OK;
94  }
95 
96  if (sscanf(value, "%lf", val) == 1) {
97  *norm = 1;
98  return CR_OK;
99  }
100 
101  return CR_ERROR_VALUE;
102 }
103 
104 const char *G_parse_color_rule_error(int code)
105 {
106  switch (code) {
107  case CR_OK:
108  return "";
109  case CR_ERROR_SYNTAX:
110  return _("syntax error");
111  case CR_ERROR_RGB:
112  return _("R/G/B not in range 0-255");
113  case CR_ERROR_COLOR:
114  return _("invalid color name");
115  case CR_ERROR_PERCENT:
116  return _("percentage not in range 0-100");
117  case CR_ERROR_VALUE:
118  return _("invalid value");
119  default:
120  return _("unknown error");
121  }
122 }
123 
124 int G_read_color_rule(void *closure, DCELL min, DCELL max,
125  DCELL * val, int *r, int *g, int *b,
126  int *norm, int *nval, int *dflt)
127 {
128  char buf[1024];
129  FILE *fp = closure;
130  int ret;
131 
132  *norm = *nval = *dflt = 0;
133 
134  for (;;) {
135  if (!G_getl2(buf, sizeof(buf), fp))
136  return 0;
137 
138  G_strip(buf);
139  G_debug(5, "color buf = [%s]", buf);
140 
141  if (*buf == '\0')
142  continue;
143  if (*buf == '#')
144  continue;
145 
146  ret =
147  G_parse_color_rule(min, max, buf, val, r, g, b, norm, nval, dflt);
148  if (ret == 0)
149  return 1;
150 
151  G_fatal_error(_("bad rule (%s): [%s]"),
152  G_parse_color_rule_error(ret), buf);
153  }
154 
155  return 0;
156 }
157 
158 int G_read_color_rules(struct Colors *colors, DCELL min, DCELL max,
159  read_rule_fn * read_rule, void *closure)
160 {
161  struct rule *rule = NULL;
162  int nrules = 0;
163  struct rule dflt, null;
164  int set, is_null, is_dflt, r, g, b;
165  DCELL val;
166  int n;
167 
168  if (!read_rule)
169  read_rule = G_read_color_rule;
170 
171  G_init_colors(colors);
172 
173  /* initialization */
174  dflt.r = dflt.g = dflt.b = dflt.set = 0;
175  null.r = null.g = null.b = null.set = 0;
176 
177  while ((*read_rule)
178  (closure, min, max, &val, &r, &g, &b, &set, &is_null, &is_dflt)) {
179  struct rule *p;
180 
181  if (set) {
182  n = nrules++;
183  rule = G_realloc(rule, nrules * sizeof(struct rule));
184  p = &rule[n];
185  }
186  else if (is_dflt)
187  p = &dflt;
188  else if (is_null)
189  p = &null;
190 
191  p->r = r;
192  p->g = g;
193  p->b = b;
194  p->set = 1;
195  p->val = val;
196  }
197 
198  if (nrules == 0)
199  return 0;
200 
201  if (nrules == 1) {
202  const struct rule *p = &rule[0];
203 
204  G_set_d_color(p->val, p->r, p->g, p->b, colors);
205  }
206 
207  for (n = 1; n < nrules; n++) {
208  struct rule *lo = &rule[n - 1];
209  struct rule *hi = &rule[n];
210 
211  G_add_d_raster_color_rule(&lo->val, lo->r, lo->g, lo->b,
212  &hi->val, hi->r, hi->g, hi->b, colors);
213  }
214 
215  /* null value and default color set up, if rules are set up by user */
216  if (null.set)
217  G_set_null_value_color(null.r, null.g, null.b, colors);
218 
219  if (dflt.set)
220  G_set_default_color(dflt.r, dflt.g, dflt.b, colors);
221 
222  return 1;
223 }
224 
225 static int load_rules_file(struct Colors *colors, const char *path, DCELL min,
226  DCELL max)
227 {
228  FILE *fp;
229  int ret;
230 
231  fp = fopen(path, "r");
232 
233  if (!fp)
234  return 0;
235 
236  ret = G_read_color_rules(colors, min, max, G_read_color_rule, (void *)fp);
237 
238  fclose(fp);
239 
240  return ret;
241 }
242 
243 int G_load_colors(struct Colors *colors, const char *path, CELL min, CELL max)
244 {
245  return load_rules_file(colors, path, (DCELL) min, (DCELL) max);
246 }
247 
248 int G_load_fp_colors(struct Colors *colors, const char *path, DCELL min,
249  DCELL max)
250 {
251  return load_rules_file(colors, path, min, max);
252 }
253 
254 static int load_rules_name(struct Colors *colors, const char *name, DCELL min,
255  DCELL max)
256 {
257  int ret;
258  char path[GPATH_MAX];
259 
260  sprintf(path, "%s/etc/colors/%s", G_gisbase(), name);
261 
262  ret = load_rules_file(colors, path, min, max);
263 
264  if (!ret)
265  G_fatal_error(_("Unable to load color rules <%s>"), name);
266 
267  return ret;
268 }
269 
270 int G_make_colors(struct Colors *colors, const char *name, CELL min, CELL max)
271 {
272  return load_rules_name(colors, name, (DCELL) min, (DCELL) max);
273 }
274 
275 int G_make_fp_colors(struct Colors *colors, const char *name, DCELL min,
276  DCELL max)
277 {
278  return load_rules_name(colors, name, min, max);
279 }