color_rules.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /****************************************************************************
  2. *
  3. * MODULE: gis library
  4. * AUTHOR(S): Glynn Clements <glynn@gclements.plus.com>
  5. * COPYRIGHT: (C) 2007 Glynn Clements and the GRASS Development Team
  6. *
  7. * NOTE: Based upon r.colors/rules.c
  8. * The colors are stored in ./colors/
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. *****************************************************************************/
  21. #include <stdio.h>
  22. #include <grass/gis.h>
  23. #include <grass/raster.h>
  24. #include <grass/glocale.h>
  25. struct rule
  26. {
  27. int set;
  28. int r, g, b;
  29. DCELL val;
  30. };
  31. enum rule_error
  32. {
  33. CR_OK = 0,
  34. CR_ERROR_SYNTAX,
  35. CR_ERROR_RGB,
  36. CR_ERROR_COLOR,
  37. CR_ERROR_PERCENT,
  38. CR_ERROR_VALUE,
  39. };
  40. int Rast_parse_color_rule(DCELL min, DCELL max, const char *buf,
  41. DCELL * val, int *r, int *g, int *b,
  42. int *norm, int *nval, int *dflt)
  43. {
  44. char value[80], color[80];
  45. double x;
  46. char c;
  47. *norm = *nval = *dflt = 0;
  48. if (sscanf(buf, "%s %[^\n]", value, color) != 2)
  49. return CR_ERROR_SYNTAX;
  50. G_chop(color);
  51. if (sscanf(color, "%d:%d:%d", r, g, b) == 3 ||
  52. sscanf(color, "%d %d %d", r, g, b) == 3) {
  53. if (*r < 0 || *r > 255 || *g < 0 || *g > 255 || *b < 0 || *b > 255)
  54. return CR_ERROR_RGB;
  55. }
  56. else {
  57. float fr, fg, fb;
  58. if (G_color_values(color, &fr, &fg, &fb) < 0)
  59. return CR_ERROR_COLOR;
  60. *r = (int)(fr * 255.99);
  61. *g = (int)(fg * 255.99);
  62. *b = (int)(fb * 255.99);
  63. }
  64. G_chop(value);
  65. if (G_strcasecmp(value, "default") == 0) {
  66. *dflt = 1;
  67. return CR_OK;
  68. }
  69. if (G_strcasecmp(value, "nv") == 0) {
  70. *nval = 1;
  71. return CR_OK;
  72. }
  73. if (sscanf(value, "%lf%c", &x, &c) == 2 && c == '%') {
  74. if (x < 0 || x > 100)
  75. return CR_ERROR_PERCENT;
  76. *val = min + (max - min) * (x / 100);
  77. *norm = 1;
  78. return CR_OK;
  79. }
  80. if (sscanf(value, "%lf", val) == 1) {
  81. *norm = 1;
  82. return CR_OK;
  83. }
  84. return CR_ERROR_VALUE;
  85. }
  86. const char *Rast_parse_color_rule_error(int code)
  87. {
  88. switch (code) {
  89. case CR_OK:
  90. return "";
  91. case CR_ERROR_SYNTAX:
  92. return _("syntax error");
  93. case CR_ERROR_RGB:
  94. return _("R/G/B not in range 0-255");
  95. case CR_ERROR_COLOR:
  96. return _("invalid color name");
  97. case CR_ERROR_PERCENT:
  98. return _("percentage not in range 0-100");
  99. case CR_ERROR_VALUE:
  100. return _("invalid value");
  101. default:
  102. return _("unknown error");
  103. }
  104. }
  105. int Rast_read_color_rule(void *closure, DCELL min, DCELL max,
  106. DCELL * val, int *r, int *g, int *b,
  107. int *norm, int *nval, int *dflt)
  108. {
  109. char buf[1024];
  110. FILE *fp = closure;
  111. int ret;
  112. *norm = *nval = *dflt = 0;
  113. for (;;) {
  114. if (!G_getl2(buf, sizeof(buf), fp))
  115. return 0;
  116. G_strip(buf);
  117. G_debug(5, "color buf = [%s]", buf);
  118. if (*buf == '\0')
  119. continue;
  120. if (*buf == '#')
  121. continue;
  122. ret =
  123. Rast_parse_color_rule(min, max, buf, val, r, g, b, norm, nval,
  124. dflt);
  125. if (ret == 0)
  126. return 1;
  127. G_fatal_error(_("bad rule (%s): [%s]"),
  128. Rast_parse_color_rule_error(ret), buf);
  129. }
  130. return 0;
  131. }
  132. int Rast_read_color_rules(struct Colors *colors, DCELL min, DCELL max,
  133. read_rule_fn * read_rule, void *closure)
  134. {
  135. struct rule *rule = NULL;
  136. int nrules = 0;
  137. struct rule dflt, null;
  138. int set, is_null, is_dflt, r, g, b;
  139. DCELL val;
  140. int n;
  141. if (!read_rule)
  142. read_rule = Rast_read_color_rule;
  143. Rast_init_colors(colors);
  144. /* initialization */
  145. dflt.r = dflt.g = dflt.b = dflt.set = 0;
  146. null.r = null.g = null.b = null.set = 0;
  147. while ((*read_rule)
  148. (closure, min, max, &val, &r, &g, &b, &set, &is_null, &is_dflt)) {
  149. struct rule *p;
  150. if (set) {
  151. n = nrules++;
  152. rule = G_realloc(rule, nrules * sizeof(struct rule));
  153. p = &rule[n];
  154. }
  155. else if (is_dflt)
  156. p = &dflt;
  157. else if (is_null)
  158. p = &null;
  159. p->r = r;
  160. p->g = g;
  161. p->b = b;
  162. p->set = 1;
  163. p->val = val;
  164. }
  165. if (nrules == 0)
  166. return 0;
  167. if (nrules == 1) {
  168. const struct rule *p = &rule[0];
  169. Rast_set_d_color(p->val, p->r, p->g, p->b, colors);
  170. }
  171. for (n = 1; n < nrules; n++) {
  172. struct rule *lo = &rule[n - 1];
  173. struct rule *hi = &rule[n];
  174. Rast_add_d_color_rule(&lo->val, lo->r, lo->g, lo->b,
  175. &hi->val, hi->r, hi->g, hi->b, colors);
  176. }
  177. /* null value and default color set up, if rules are set up by user */
  178. if (null.set)
  179. Rast_set_null_value_color(null.r, null.g, null.b, colors);
  180. if (dflt.set)
  181. Rast_set_default_color(dflt.r, dflt.g, dflt.b, colors);
  182. return 1;
  183. }
  184. static int load_rules_file(struct Colors *colors, const char *path, DCELL min,
  185. DCELL max)
  186. {
  187. FILE *fp;
  188. int ret;
  189. fp = fopen(path, "r");
  190. if (!fp)
  191. return 0;
  192. ret =
  193. Rast_read_color_rules(colors, min, max, Rast_read_color_rule,
  194. (void *)fp);
  195. fclose(fp);
  196. return ret;
  197. }
  198. int Rast_load_colors(struct Colors *colors, const char *path, CELL min,
  199. CELL max)
  200. {
  201. return load_rules_file(colors, path, (DCELL) min, (DCELL) max);
  202. }
  203. int Rast_load_fp_colors(struct Colors *colors, const char *path, DCELL min,
  204. DCELL max)
  205. {
  206. return load_rules_file(colors, path, min, max);
  207. }
  208. static void load_rules_name(struct Colors *colors, const char *name,
  209. DCELL min, DCELL max)
  210. {
  211. char path[GPATH_MAX];
  212. sprintf(path, "%s/etc/colors/%s", G_gisbase(), name);
  213. if (!load_rules_file(colors, path, min, max))
  214. G_fatal_error(_("Unable to load color rules <%s>"), name);
  215. }
  216. void Rast_make_colors(struct Colors *colors, const char *name, CELL min,
  217. CELL max)
  218. {
  219. return load_rules_name(colors, name, (DCELL) min, (DCELL) max);
  220. }
  221. void Rast_make_fp_colors(struct Colors *colors, const char *name, DCELL min,
  222. DCELL max)
  223. {
  224. return load_rules_name(colors, name, min, max);
  225. }