color_read.c 9.2 KB

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