GRASS Programmer's Manual
6.4.2(2012)
|
00001 00002 /**************************************************************************** 00003 * 00004 * MODULE: gis library 00005 * AUTHOR(S): Glynn Clements <glynn@gclements.plus.com> 00006 * COPYRIGHT: (C) 2007 Glynn Clements and the GRASS Development Team 00007 * 00008 * NOTE: Based upon r.colors/rules.c 00009 * The colors are stored in ./colors/ 00010 * 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 *****************************************************************************/ 00022 00023 #include <stdio.h> 00024 #include <grass/gis.h> 00025 #include <grass/glocale.h> 00026 00027 struct rule 00028 { 00029 int set; 00030 int r, g, b; 00031 DCELL val; 00032 }; 00033 00034 enum rule_error 00035 { 00036 CR_OK = 0, 00037 CR_ERROR_SYNTAX, 00038 CR_ERROR_RGB, 00039 CR_ERROR_COLOR, 00040 CR_ERROR_PERCENT, 00041 CR_ERROR_VALUE, 00042 }; 00043 00044 int G_parse_color_rule(DCELL min, DCELL max, const char *buf, 00045 DCELL * val, int *r, int *g, int *b, 00046 int *norm, int *nval, int *dflt) 00047 { 00048 char value[80], color[80]; 00049 double x; 00050 char c; 00051 00052 *norm = *nval = *dflt = 0; 00053 00054 if (sscanf(buf, "%s %[^\n]", value, color) != 2) 00055 return CR_ERROR_SYNTAX; 00056 00057 G_chop(color); 00058 00059 if (sscanf(color, "%d:%d:%d", r, g, b) == 3 || 00060 sscanf(color, "%d %d %d", r, g, b) == 3) { 00061 if (*r < 0 || *r > 255 || *g < 0 || *g > 255 || *b < 0 || *b > 255) 00062 return CR_ERROR_RGB; 00063 } 00064 else { 00065 float fr, fg, fb; 00066 00067 if (G_color_values(color, &fr, &fg, &fb) < 0) 00068 return CR_ERROR_COLOR; 00069 00070 *r = (int)(fr * 255.99); 00071 *g = (int)(fg * 255.99); 00072 *b = (int)(fb * 255.99); 00073 } 00074 00075 G_chop(value); 00076 00077 if (G_strcasecmp(value, "default") == 0) { 00078 *dflt = 1; 00079 return CR_OK; 00080 } 00081 00082 if (G_strcasecmp(value, "nv") == 0) { 00083 *nval = 1; 00084 return CR_OK; 00085 } 00086 00087 if (sscanf(value, "%lf%c", &x, &c) == 2 && c == '%') { 00088 if (x < 0 || x > 100) 00089 return CR_ERROR_PERCENT; 00090 00091 *val = min + (max - min) * (x / 100); 00092 *norm = 1; 00093 return CR_OK; 00094 } 00095 00096 if (sscanf(value, "%lf", val) == 1) { 00097 *norm = 1; 00098 return CR_OK; 00099 } 00100 00101 return CR_ERROR_VALUE; 00102 } 00103 00104 const char *G_parse_color_rule_error(int code) 00105 { 00106 switch (code) { 00107 case CR_OK: 00108 return ""; 00109 case CR_ERROR_SYNTAX: 00110 return _("syntax error"); 00111 case CR_ERROR_RGB: 00112 return _("R/G/B not in range 0-255"); 00113 case CR_ERROR_COLOR: 00114 return _("invalid color name"); 00115 case CR_ERROR_PERCENT: 00116 return _("percentage not in range 0-100"); 00117 case CR_ERROR_VALUE: 00118 return _("invalid value"); 00119 default: 00120 return _("unknown error"); 00121 } 00122 } 00123 00124 int G_read_color_rule(void *closure, DCELL min, DCELL max, 00125 DCELL * val, int *r, int *g, int *b, 00126 int *norm, int *nval, int *dflt) 00127 { 00128 char buf[1024]; 00129 FILE *fp = closure; 00130 int ret; 00131 00132 *norm = *nval = *dflt = 0; 00133 00134 for (;;) { 00135 if (!G_getl2(buf, sizeof(buf), fp)) 00136 return 0; 00137 00138 G_strip(buf); 00139 G_debug(5, "color buf = [%s]", buf); 00140 00141 if (*buf == '\0') 00142 continue; 00143 if (*buf == '#') 00144 continue; 00145 00146 ret = 00147 G_parse_color_rule(min, max, buf, val, r, g, b, norm, nval, dflt); 00148 if (ret == 0) 00149 return 1; 00150 00151 G_fatal_error(_("bad rule (%s): [%s]"), 00152 G_parse_color_rule_error(ret), buf); 00153 } 00154 00155 return 0; 00156 } 00157 00158 int G_read_color_rules(struct Colors *colors, DCELL min, DCELL max, 00159 read_rule_fn * read_rule, void *closure) 00160 { 00161 struct rule *rule = NULL; 00162 int nrules = 0; 00163 struct rule dflt, null; 00164 int set, is_null, is_dflt, r, g, b; 00165 DCELL val; 00166 int n; 00167 00168 if (!read_rule) 00169 read_rule = G_read_color_rule; 00170 00171 G_init_colors(colors); 00172 00173 /* initialization */ 00174 dflt.r = dflt.g = dflt.b = dflt.set = 0; 00175 null.r = null.g = null.b = null.set = 0; 00176 00177 while ((*read_rule) 00178 (closure, min, max, &val, &r, &g, &b, &set, &is_null, &is_dflt)) { 00179 struct rule *p; 00180 00181 if (set) { 00182 n = nrules++; 00183 rule = G_realloc(rule, nrules * sizeof(struct rule)); 00184 p = &rule[n]; 00185 } 00186 else if (is_dflt) 00187 p = &dflt; 00188 else if (is_null) 00189 p = &null; 00190 00191 p->r = r; 00192 p->g = g; 00193 p->b = b; 00194 p->set = 1; 00195 p->val = val; 00196 } 00197 00198 if (nrules == 0) 00199 return 0; 00200 00201 if (nrules == 1) { 00202 const struct rule *p = &rule[0]; 00203 00204 G_set_d_color(p->val, p->r, p->g, p->b, colors); 00205 } 00206 00207 for (n = 1; n < nrules; n++) { 00208 struct rule *lo = &rule[n - 1]; 00209 struct rule *hi = &rule[n]; 00210 00211 G_add_d_raster_color_rule(&lo->val, lo->r, lo->g, lo->b, 00212 &hi->val, hi->r, hi->g, hi->b, colors); 00213 } 00214 00215 /* null value and default color set up, if rules are set up by user */ 00216 if (null.set) 00217 G_set_null_value_color(null.r, null.g, null.b, colors); 00218 00219 if (dflt.set) 00220 G_set_default_color(dflt.r, dflt.g, dflt.b, colors); 00221 00222 return 1; 00223 } 00224 00225 static int load_rules_file(struct Colors *colors, const char *path, DCELL min, 00226 DCELL max) 00227 { 00228 FILE *fp; 00229 int ret; 00230 00231 fp = fopen(path, "r"); 00232 00233 if (!fp) 00234 return 0; 00235 00236 ret = G_read_color_rules(colors, min, max, G_read_color_rule, (void *)fp); 00237 00238 fclose(fp); 00239 00240 return ret; 00241 } 00242 00243 int G_load_colors(struct Colors *colors, const char *path, CELL min, CELL max) 00244 { 00245 return load_rules_file(colors, path, (DCELL) min, (DCELL) max); 00246 } 00247 00248 int G_load_fp_colors(struct Colors *colors, const char *path, DCELL min, 00249 DCELL max) 00250 { 00251 return load_rules_file(colors, path, min, max); 00252 } 00253 00254 static int load_rules_name(struct Colors *colors, const char *name, DCELL min, 00255 DCELL max) 00256 { 00257 int ret; 00258 char path[GPATH_MAX]; 00259 00260 sprintf(path, "%s/etc/colors/%s", G_gisbase(), name); 00261 00262 ret = load_rules_file(colors, path, min, max); 00263 00264 if (!ret) 00265 G_fatal_error(_("Unable to load color rules <%s>"), name); 00266 00267 return ret; 00268 } 00269 00270 int G_make_colors(struct Colors *colors, const char *name, CELL min, CELL max) 00271 { 00272 return load_rules_name(colors, name, (DCELL) min, (DCELL) max); 00273 } 00274 00275 int G_make_fp_colors(struct Colors *colors, const char *name, DCELL min, 00276 DCELL max) 00277 { 00278 return load_rules_name(colors, name, min, max); 00279 }