color_rules.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*!
  2. \file lib/raster/color_read.c
  3. \brief Raster Library - Read and parse color rules file
  4. (C) 2007 by the GRASS Development Team
  5. This program is free software under the GNU General Public
  6. License (>=v2). Read the file COPYING that comes with GRASS
  7. for details.
  8. \author Glynn Clements
  9. */
  10. #include <stdio.h>
  11. #include <grass/gis.h>
  12. #include <grass/raster.h>
  13. #include <grass/glocale.h>
  14. struct rule
  15. {
  16. int set;
  17. int r, g, b;
  18. DCELL val;
  19. };
  20. enum rule_error
  21. {
  22. CR_OK = 0,
  23. CR_ERROR_SYNTAX,
  24. CR_ERROR_RGB,
  25. CR_ERROR_COLOR,
  26. CR_ERROR_PERCENT,
  27. CR_ERROR_VALUE,
  28. };
  29. /*!
  30. \brief Read color rule
  31. \param min, max min & max values (used only when color rules are in percentage)
  32. \param buf
  33. \param val value
  34. \param[out] r,g,b color values
  35. \param norm
  36. \param nval
  37. \param dflt
  38. \return 0 on failure
  39. \return 1 on success
  40. */
  41. int Rast_parse_color_rule(DCELL min, DCELL max, const char *buf,
  42. DCELL * val, int *r, int *g, int *b,
  43. int *norm, int *nval, int *dflt)
  44. {
  45. char value[80], color[80];
  46. double x;
  47. char c;
  48. *norm = *nval = *dflt = 0;
  49. if (sscanf(buf, "%s %[^\n]", value, color) != 2)
  50. return CR_ERROR_SYNTAX;
  51. G_chop(color);
  52. if (sscanf(color, "%d:%d:%d", r, g, b) == 3 ||
  53. sscanf(color, "%d %d %d", r, g, b) == 3) {
  54. if (*r < 0 || *r > 255 || *g < 0 || *g > 255 || *b < 0 || *b > 255)
  55. return CR_ERROR_RGB;
  56. }
  57. else {
  58. float fr, fg, fb;
  59. if (G_color_values(color, &fr, &fg, &fb) < 0)
  60. return CR_ERROR_COLOR;
  61. *r = (int)(fr * 255.99);
  62. *g = (int)(fg * 255.99);
  63. *b = (int)(fb * 255.99);
  64. }
  65. G_chop(value);
  66. if (G_strcasecmp(value, "default") == 0) {
  67. *dflt = 1;
  68. return CR_OK;
  69. }
  70. if (G_strcasecmp(value, "nv") == 0) {
  71. *nval = 1;
  72. return CR_OK;
  73. }
  74. if (sscanf(value, "%lf%c", &x, &c) == 2 && c == '%') {
  75. if (x < 0 || x > 100)
  76. return CR_ERROR_PERCENT;
  77. *val = min + (max - min) * (x / 100);
  78. *norm = 1;
  79. return CR_OK;
  80. }
  81. if (sscanf(value, "%lf", val) == 1) {
  82. *norm = 1;
  83. return CR_OK;
  84. }
  85. return CR_ERROR_VALUE;
  86. }
  87. /*!
  88. \brief Parse color rule
  89. \param code
  90. \return pointer to buffer with error message
  91. */
  92. const char *Rast_parse_color_rule_error(int code)
  93. {
  94. switch (code) {
  95. case CR_OK:
  96. return "";
  97. case CR_ERROR_SYNTAX:
  98. return _("syntax error");
  99. case CR_ERROR_RGB:
  100. return _("R/G/B not in range 0-255");
  101. case CR_ERROR_COLOR:
  102. return _("invalid color name");
  103. case CR_ERROR_PERCENT:
  104. return _("percentage not in range 0-100");
  105. case CR_ERROR_VALUE:
  106. return _("invalid value");
  107. default:
  108. return _("unknown error");
  109. }
  110. }
  111. /*!
  112. \brief Read color rule
  113. \param closure
  114. \param min, max min & max values (used only when color rules are in percentage)
  115. \param val value
  116. \param[out] r,g,b color values
  117. \param norm
  118. \param nval
  119. \param dflt
  120. \return 0 on failure
  121. \return 1 on success
  122. */
  123. int Rast_read_color_rule(void *closure, DCELL min, DCELL max,
  124. DCELL * val, int *r, int *g, int *b,
  125. int *norm, int *nval, int *dflt)
  126. {
  127. char buf[1024];
  128. FILE *fp = closure;
  129. int ret;
  130. *norm = *nval = *dflt = 0;
  131. for (;;) {
  132. if (!G_getl2(buf, sizeof(buf), fp))
  133. return 0;
  134. G_strip(buf);
  135. G_debug(5, "color buf = [%s]", buf);
  136. if (*buf == '\0')
  137. continue;
  138. if (*buf == '#')
  139. continue;
  140. ret =
  141. Rast_parse_color_rule(min, max, buf, val, r, g, b, norm, nval,
  142. dflt);
  143. if (ret == 0)
  144. return 1;
  145. G_fatal_error(_("bad rule (%s): [%s]"),
  146. Rast_parse_color_rule_error(ret), buf);
  147. }
  148. return 0;
  149. }
  150. /*!
  151. \brief Read color rules from file
  152. \param[out] colors pointer to Colors structure
  153. \param min, max min & max values (used only when color rules are in percentage)
  154. \param read_rule pointer to read_rule_fn structure
  155. \param closure
  156. \return 0 on failure
  157. \return 1 on success
  158. */
  159. int Rast_read_color_rules(struct Colors *colors, DCELL min, DCELL max,
  160. read_rule_fn * read_rule, void *closure)
  161. {
  162. struct rule *rule = NULL;
  163. int nrules = 0;
  164. struct rule dflt, null;
  165. int set, is_null, is_dflt, r, g, b;
  166. DCELL val;
  167. int n;
  168. if (!read_rule)
  169. read_rule = Rast_read_color_rule;
  170. Rast_init_colors(colors);
  171. /* initialization */
  172. dflt.r = dflt.g = dflt.b = dflt.set = 0;
  173. null.r = null.g = null.b = null.set = 0;
  174. while ((*read_rule)
  175. (closure, min, max, &val, &r, &g, &b, &set, &is_null, &is_dflt)) {
  176. struct rule *p;
  177. if (set) {
  178. n = nrules++;
  179. rule = G_realloc(rule, nrules * sizeof(struct rule));
  180. p = &rule[n];
  181. }
  182. else if (is_dflt)
  183. p = &dflt;
  184. else if (is_null)
  185. p = &null;
  186. p->r = r;
  187. p->g = g;
  188. p->b = b;
  189. p->set = 1;
  190. p->val = val;
  191. }
  192. if (nrules == 0)
  193. return 0;
  194. if (nrules == 1) {
  195. const struct rule *p = &rule[0];
  196. Rast_set_d_color(p->val, p->r, p->g, p->b, colors);
  197. }
  198. for (n = 1; n < nrules; n++) {
  199. struct rule *lo = &rule[n - 1];
  200. struct rule *hi = &rule[n];
  201. Rast_add_d_color_rule(&lo->val, lo->r, lo->g, lo->b,
  202. &hi->val, hi->r, hi->g, hi->b, colors);
  203. }
  204. G_free(rule);
  205. /* null value and default color set up, if rules are set up by user */
  206. if (null.set)
  207. Rast_set_null_value_color(null.r, null.g, null.b, colors);
  208. if (dflt.set)
  209. Rast_set_default_color(dflt.r, dflt.g, dflt.b, colors);
  210. return 1;
  211. }
  212. static int load_rules_file(struct Colors *colors, const char *path, DCELL min,
  213. DCELL max)
  214. {
  215. FILE *fp;
  216. int ret;
  217. fp = fopen(path, "r");
  218. if (!fp)
  219. return 0;
  220. ret =
  221. Rast_read_color_rules(colors, min, max, Rast_read_color_rule,
  222. (void *)fp);
  223. fclose(fp);
  224. return ret;
  225. }
  226. /*!
  227. \brief Load color rules from file
  228. \param[out] colors pointer to Colors structure
  229. \param path path to the color rules file
  230. \param min, max min & max values (used only when color rules are in percentage)
  231. \return 0 on failure
  232. \return 1 on success
  233. */
  234. int Rast_load_colors(struct Colors *colors, const char *path, CELL min,
  235. CELL max)
  236. {
  237. return load_rules_file(colors, path, (DCELL) min, (DCELL) max);
  238. }
  239. /*!
  240. \brief Load color floating-point rules from file
  241. \param[out] colors pointer to Colors structure
  242. \param path path to the color rules file
  243. \param min, max min & max values (used only when color rules are in percentage)
  244. \return 0 on failure
  245. \return 1 on success
  246. */
  247. int Rast_load_fp_colors(struct Colors *colors, const char *path, DCELL min,
  248. DCELL max)
  249. {
  250. return load_rules_file(colors, path, min, max);
  251. }
  252. static void load_rules_name(struct Colors *colors, const char *name,
  253. DCELL min, DCELL max)
  254. {
  255. char path[GPATH_MAX];
  256. sprintf(path, "%s/etc/colors/%s", G_gisbase(), name);
  257. if (!load_rules_file(colors, path, min, max))
  258. G_fatal_error(_("Unable to load color rules <%s>"), name);
  259. }
  260. /*!
  261. \brief Load color rules from predefined color table
  262. \param[out] colors pointer to Colors structure
  263. \param name name of color table to load
  264. \param min, max min & max values (used only when color rules are in percentage)
  265. */
  266. void Rast_make_colors(struct Colors *colors, const char *name, CELL min,
  267. CELL max)
  268. {
  269. return load_rules_name(colors, name, (DCELL) min, (DCELL) max);
  270. }
  271. /*!
  272. \brief Load color rules from predefined floating-point color table
  273. \param[out] colors pointer to Colors structure
  274. \param name name of color table to load
  275. \param min, max min & max values (used only when color rules are in percentage)
  276. */
  277. void Rast_make_fp_colors(struct Colors *colors, const char *name, DCELL min,
  278. DCELL max)
  279. {
  280. return load_rules_name(colors, name, min, max);
  281. }