color_read.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /*!
  2. \file lib/raster/color_read.c
  3. \brief Raster Library - Read color table of raster map
  4. (C) 1999-2009, 2011 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 USACERL and many others
  9. */
  10. #include <string.h>
  11. #include <grass/gis.h>
  12. #include <grass/raster.h>
  13. #include <grass/glocale.h>
  14. static int read_new_colors(FILE *, struct Colors *);
  15. static int read_old_colors(FILE *, struct Colors *);
  16. /*!
  17. \brief Read color table of raster map
  18. The color table for the raster map <i>name</i> in the specified
  19. <i>mapset</i> is read into the <i>colors</i> structure. If the data
  20. layer has no color table, a default color table is generated and 0
  21. is returned. If there is an error reading the color table, a
  22. diagnostic message is printed and -1 is returned. If the color
  23. table is read ok, 1 is returned.
  24. This routine reads the rules from the color file. If the input
  25. raster map is is a floating-point map it calls
  26. Rast_mark_colors_as_fp().
  27. Note: If a secondary color file for map name <i>name</i> exists in
  28. the current project, that color file is read. This allows the
  29. user to define their own color lookup tables for cell maps found
  30. in other mapsets.
  31. Warning message is printed if the color file is
  32. missing or invalid.
  33. \param name map name
  34. \param mapset mapset name
  35. \param[out] colors pointer to Colors structure
  36. \return -1 on error
  37. \return 0 if missing, but default colors generated
  38. \return 1 on success
  39. */
  40. int Rast_read_colors(const char *name, const char *mapset,
  41. struct Colors *colors)
  42. {
  43. int fp;
  44. char buf[GNAME_MAX];
  45. char *err;
  46. char xname[GNAME_MAX];
  47. struct Range range;
  48. struct FPRange drange;
  49. CELL min, max;
  50. DCELL dmin, dmax;
  51. fp = Rast_map_is_fp(name, mapset);
  52. Rast_init_colors(colors);
  53. strcpy(xname, name);
  54. mapset = G_find_raster(xname, mapset);
  55. name = xname;
  56. if (fp)
  57. Rast_mark_colors_as_fp(colors);
  58. /* first look for secondary color table in current mapset */
  59. sprintf(buf, "colr2/%s", mapset);
  60. if (Rast__read_colors(buf, name, G_mapset(), colors) >= 0)
  61. return 1;
  62. /* now look for the regular color table */
  63. switch (Rast__read_colors("colr", name, mapset, colors)) {
  64. case -2:
  65. if (!fp) {
  66. if (Rast_read_range(name, mapset, &range) >= 0) {
  67. Rast_get_range_min_max(&range, &min, &max);
  68. if (!Rast_is_c_null_value(&min) &&
  69. !Rast_is_c_null_value(&max))
  70. Rast_make_colors(colors, DEFAULT_COLOR_TABLE, min, max);
  71. return 0;
  72. }
  73. }
  74. else {
  75. if (Rast_read_fp_range(name, mapset, &drange) >= 0) {
  76. Rast_get_fp_range_min_max(&drange, &dmin, &dmax);
  77. if (!Rast_is_d_null_value(&dmin) &&
  78. !Rast_is_d_null_value(&dmax))
  79. Rast_make_fp_colors(colors, DEFAULT_COLOR_TABLE, dmin, dmax);
  80. return 0;
  81. }
  82. }
  83. err = _("missing");
  84. break;
  85. case -1:
  86. err = _("invalid");
  87. break;
  88. default:
  89. return 1;
  90. }
  91. G_warning(_("Color support for <%s@%s> %s"), name, mapset, err);
  92. return -1;
  93. }
  94. int Rast__read_colors(const char *element, const char *name,
  95. const char *mapset, struct Colors *colors)
  96. {
  97. FILE *fd;
  98. int stat;
  99. char buf[1024];
  100. if (!(fd = G_fopen_old(element, name, mapset)))
  101. return -2;
  102. /*
  103. * first line in 4.0 color files is %
  104. * otherwise it is pre 4.0
  105. */
  106. if (fgets(buf, sizeof buf, fd) == NULL) {
  107. fclose(fd);
  108. return -1;
  109. }
  110. stat = 1;
  111. if (colors) {
  112. G_fseek(fd, 0L, 0);
  113. G_strip(buf);
  114. if (*buf == '%') { /* 4.0 format */
  115. stat = read_new_colors(fd, colors);
  116. colors->version = 0; /* 4.0 format */
  117. }
  118. else {
  119. stat = read_old_colors(fd, colors);
  120. colors->version = -1; /* pre 4.0 format */
  121. }
  122. }
  123. fclose(fd);
  124. return stat;
  125. }
  126. /* parse input lines with the following formats
  127. * val1:r:g:b val2:r:g:b
  128. * val:r:g:b (implies cat1==cat2)
  129. *
  130. * r:g:b can be just a single grey level
  131. * cat1:x cat2:y
  132. * cat:x
  133. *
  134. * optional lines are
  135. * invert invert color table
  136. * shift:n where n is the amount to shift the color table
  137. * nv:r:g:b color to use for NULL values
  138. * *:r:g:b color to use for undefined (beyond color rules)
  139. */
  140. static int read_new_colors(FILE * fd, struct Colors *colors)
  141. {
  142. double val1, val2;
  143. long cat1, cat2;
  144. int r1, g1, b1;
  145. int r2, g2, b2;
  146. char buf[1024];
  147. char word1[256], word2[256];
  148. int n, fp_rule;
  149. int null, undef;
  150. int modular;
  151. DCELL shift;
  152. if (fgets(buf, sizeof buf, fd) == NULL)
  153. return -1;
  154. G_strip(buf);
  155. if (sscanf(buf + 1, "%lf %lf", &val1, &val2) == 2)
  156. Rast_set_d_color_range((DCELL) val1, (DCELL) val2, colors);
  157. modular = 0;
  158. while (fgets(buf, sizeof buf, fd)) {
  159. null = undef = fp_rule = 0;
  160. *word1 = *word2 = 0;
  161. n = sscanf(buf, "%s %s", word1, word2);
  162. if (n < 1)
  163. continue;
  164. if (sscanf(word1, "shift:%lf", &shift) == 1
  165. || (strcmp(word1, "shift:") == 0 &&
  166. sscanf(word2, "%lf", &shift) == 1)) {
  167. Rast_shift_d_colors(shift, colors);
  168. continue;
  169. }
  170. if (strcmp(word1, "invert") == 0) {
  171. Rast_invert_colors(colors);
  172. continue;
  173. }
  174. if (strcmp(word1, "%%") == 0) {
  175. modular = !modular;
  176. continue;
  177. }
  178. switch (sscanf(word1, "nv:%d:%d:%d", &r1, &g1, &b1)) {
  179. case 1:
  180. null = 1;
  181. b1 = g1 = r1;
  182. break;
  183. case 3:
  184. null = 1;
  185. break;
  186. }
  187. if (!null)
  188. switch (sscanf(word1, "*:%d:%d:%d", &r1, &g1, &b1)) {
  189. case 1:
  190. undef = 1;
  191. b1 = g1 = r1;
  192. break;
  193. case 3:
  194. undef = 1;
  195. break;
  196. }
  197. if (!null && !undef)
  198. switch (sscanf(word1, "%ld:%d:%d:%d", &cat1, &r1, &g1, &b1)) {
  199. case 2:
  200. b1 = g1 = r1;
  201. break;
  202. case 4:
  203. break;
  204. default:
  205. if (sscanf(word1, "%lf:%d:%d:%d", &val1, &r1, &g1, &b1) == 4)
  206. fp_rule = 1;
  207. else if (sscanf(word1, "%lf:%d", &val1, &r1) == 2) {
  208. fp_rule = 1;
  209. b1 = g1 = r1;
  210. }
  211. else
  212. continue; /* other lines are ignored */
  213. }
  214. if (n == 2) {
  215. switch (sscanf(word2, "%ld:%d:%d:%d", &cat2, &r2, &g2, &b2)) {
  216. case 2:
  217. b2 = g2 = r2;
  218. if (fp_rule)
  219. val2 = (DCELL) cat2;
  220. break;
  221. case 4:
  222. if (fp_rule)
  223. val2 = (DCELL) cat2;
  224. break;
  225. default:
  226. if (sscanf(word2, "%lf:%d:%d:%d", &val2, &r2, &g2, &b2) == 4) {
  227. if (!fp_rule)
  228. val1 = (DCELL) cat1;
  229. fp_rule = 1;
  230. }
  231. else if (sscanf(word2, "%lf:%d", &val2, &r2) == 2) {
  232. if (!fp_rule)
  233. val1 = (DCELL) cat1;
  234. fp_rule = 1;
  235. b2 = g2 = r2;
  236. }
  237. else
  238. continue; /* other lines are ignored */
  239. }
  240. }
  241. else {
  242. if (!fp_rule)
  243. cat2 = cat1;
  244. else
  245. val2 = val1;
  246. r2 = r1;
  247. g2 = g1;
  248. b2 = b1;
  249. }
  250. if (null)
  251. Rast_set_null_value_color(r1, g1, b1, colors);
  252. else if (undef)
  253. Rast_set_default_color(r1, g1, b1, colors);
  254. else if (modular) {
  255. if (fp_rule)
  256. Rast_add_modular_d_color_rule((DCELL *) & val1, r1, g1,
  257. b1, (DCELL *) & val2, r2,
  258. g2, b2, colors);
  259. else
  260. Rast_add_modular_c_color_rule((CELL *) & cat1, r1, g1, b1,
  261. (CELL *) & cat2, r2, g2, b2,
  262. colors);
  263. }
  264. else {
  265. if (fp_rule)
  266. Rast_add_d_color_rule((DCELL *) & val1, r1, g1, b1,
  267. (DCELL *) & val2, r2, g2, b2, colors);
  268. else
  269. Rast_add_c_color_rule((CELL *) & cat1, r1, g1, b1,
  270. (CELL *) & cat2, r2, g2, b2, colors);
  271. }
  272. G_debug(3, "adding rule %ld=%.2lf %d %d %d %ld=%.2lf %d %d %d",
  273. cat1, val1, r1, g1, b1, cat2, val2, r2, g2, b2);
  274. }
  275. return 1;
  276. }
  277. static int read_old_colors(FILE * fd, struct Colors *colors)
  278. {
  279. char buf[256];
  280. long n;
  281. long min;
  282. float red_f, grn_f, blu_f;
  283. int red, grn, blu;
  284. int old;
  285. int zero;
  286. Rast_init_colors(colors);
  287. /*
  288. * first line in pre 3.0 color files is number of colors - ignore
  289. * otherwise it is #min first color, and the next line is for color 0
  290. */
  291. if (fgets(buf, sizeof buf, fd) == NULL)
  292. return -1;
  293. G_strip(buf);
  294. if (*buf == '#') { /* 3.0 format */
  295. old = 0;
  296. if (sscanf(buf + 1, "%ld", &min) != 1) /* first color */
  297. return -1;
  298. zero = 1;
  299. }
  300. else {
  301. old = 1;
  302. min = 0;
  303. zero = 0;
  304. }
  305. colors->cmin = min;
  306. n = min;
  307. while (fgets(buf, sizeof buf, fd)) {
  308. if (old) {
  309. if (sscanf(buf, "%f %f %f", &red_f, &grn_f, &blu_f) != 3)
  310. return -1;
  311. red = 256 * red_f;
  312. grn = 256 * grn_f;
  313. blu = 256 * blu_f;
  314. }
  315. else {
  316. switch (sscanf(buf, "%d %d %d", &red, &grn, &blu)) {
  317. case 1:
  318. blu = grn = red;
  319. break;
  320. case 2:
  321. blu = grn;
  322. break;
  323. case 3:
  324. break;
  325. default:
  326. return -1;
  327. }
  328. }
  329. if (zero) {
  330. Rast__insert_color_into_lookup((CELL) 0, red, grn, blu,
  331. &colors->fixed);
  332. zero = 0;
  333. }
  334. else
  335. Rast__insert_color_into_lookup((CELL) n++, red, grn, blu,
  336. &colors->fixed);
  337. }
  338. colors->cmax = n - 1;
  339. return 0;
  340. }
  341. /*!
  342. * \brief Mark colors as floating-point.
  343. *
  344. * Sets a flag in the <i>colors</i> structure that indicates that
  345. * these colors should only be looked up using floating-point raster
  346. * data (not integer data). In particular if this flag is set, the
  347. * routine Rast_get_c_colors_min_max() should return min=-255$^3$ and
  348. * max=255$^3$.
  349. *
  350. * \param colors pointer to Colors structure
  351. */
  352. void Rast_mark_colors_as_fp(struct Colors *colors)
  353. {
  354. colors->is_float = 1;
  355. }