color.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <unistd.h>
  6. #include <grass/gis.h>
  7. #include <grass/raster.h>
  8. #include <grass/glocale.h>
  9. #include "raster3d_intern.h"
  10. static int read_colors(const char *, const char *, struct Colors *);
  11. static int read_new_colors(FILE *, struct Colors *);
  12. static int read_old_colors(FILE *, struct Colors *);
  13. /*---------------------------------------------------------------------------*/
  14. /*!
  15. \brief Removes the primary and/or secondary color file.
  16. \todo Is <em>primary and/or secondary color file</em> still valid for 7?
  17. \see G_remove_colr
  18. */
  19. int Rast3d_remove_color(const char *name)
  20. /* adapted from G_remove_colr */
  21. {
  22. return G_remove_misc(RASTER3D_DIRECTORY, RASTER3D_COLOR_ELEMENT, name);
  23. }
  24. /*---------------------------------------------------------------------------*/
  25. /*!
  26. \brief Reads color file for map \p name in \p mapset into the Colors structure.
  27. \param name 3D raster map name
  28. \param mapset mapset name
  29. \param colors colors to be associated with a map
  30. \see Rast3d_write_colors, Rast_read_colors
  31. */
  32. int Rast3d_read_colors(const char *name, const char *mapset, struct Colors *colors)
  33. /* adapted from Rast_read_colors */
  34. {
  35. const char *err;
  36. struct FPRange drange;
  37. DCELL dmin, dmax;
  38. Rast_init_colors(colors);
  39. Rast_mark_colors_as_fp(colors);
  40. switch (read_colors(name, mapset, colors)) {
  41. case -2:
  42. if (Rast3d_read_range(name, mapset, &drange) >= 0) {
  43. Rast_get_fp_range_min_max(&drange, &dmin, &dmax);
  44. if (!Rast_is_d_null_value(&dmin) && !Rast_is_d_null_value(&dmax))
  45. Rast_make_fp_colors(colors, DEFAULT_COLOR_TABLE, dmin, dmax);
  46. return 0;
  47. }
  48. err = "missing";
  49. break;
  50. case -1:
  51. err = "invalid";
  52. break;
  53. default:
  54. return 1;
  55. }
  56. G_warning("color support for [%s] in mapset [%s] %s", name, mapset, err);
  57. return -1;
  58. }
  59. static int read_colors(const char *name, const char *mapset,
  60. struct Colors *colors)
  61. {
  62. FILE *fd;
  63. int stat;
  64. char buf[1024];
  65. fd = G_fopen_old_misc(RASTER3D_DIRECTORY, RASTER3D_COLOR_ELEMENT, name, mapset);
  66. if (!fd)
  67. return -2;
  68. /*
  69. * first line in 4.0 color files is %
  70. * otherwise it is pre 4.0
  71. */
  72. if (fgets(buf, sizeof buf, fd) == NULL) {
  73. fclose(fd);
  74. return -1;
  75. }
  76. G_fseek(fd, 0L, 0);
  77. G_strip(buf);
  78. if (*buf == '%') { /* 4.0 format */
  79. stat = read_new_colors(fd, colors);
  80. colors->version = 0; /* 4.0 format */
  81. }
  82. else {
  83. stat = read_old_colors(fd, colors);
  84. colors->version = -1; /* pre 4.0 format */
  85. }
  86. fclose(fd);
  87. return stat;
  88. }
  89. /* parse input lines with the following formats
  90. * val1:r:g:b val2:r:g:b
  91. * val:r:g:b (implies cat1==cat2)
  92. *
  93. * r:g:b can be just a single grey level
  94. * cat1:x cat2:y
  95. * cat:x
  96. *
  97. * optional lines are
  98. * invert invert color table
  99. * shift:n where n is the amount to shift the color table
  100. */
  101. static int read_new_colors(FILE * fd, struct Colors *colors)
  102. {
  103. double val1, val2;
  104. long cat1, cat2;
  105. int r1, g1, b1;
  106. int r2, g2, b2;
  107. char buf[1024];
  108. char word1[256], word2[256];
  109. int n, fp_rule;
  110. int null, undef;
  111. int modular;
  112. DCELL shift;
  113. if (fgets(buf, sizeof buf, fd) == NULL)
  114. return -1;
  115. G_strip(buf);
  116. if (sscanf(buf + 1, "%lf %lf", &val1, &val2) == 2)
  117. Rast_set_d_color_range((DCELL) val1, (DCELL) val2, colors);
  118. modular = 0;
  119. while (fgets(buf, sizeof buf, fd)) {
  120. null = undef = fp_rule = 0;
  121. *word1 = *word2 = 0;
  122. n = sscanf(buf, "%s %s", word1, word2);
  123. if (n < 1)
  124. continue;
  125. if (sscanf(word1, "shift:%lf", &shift) == 1
  126. || (strcmp(word1, "shift:") == 0 &&
  127. sscanf(word2, "%lf", &shift) == 1)) {
  128. Rast_shift_d_colors(shift, colors);
  129. continue;
  130. }
  131. if (strcmp(word1, "invert") == 0) {
  132. Rast_invert_colors(colors);
  133. continue;
  134. }
  135. if (strcmp(word1, "%%") == 0) {
  136. modular = !modular;
  137. continue;
  138. }
  139. switch (sscanf(word1, "nv:%d:%d:%d", &r1, &g1, &b1)) {
  140. case 1:
  141. null = 1;
  142. b1 = g1 = r1;
  143. break;
  144. case 3:
  145. null = 1;
  146. break;
  147. }
  148. if (!null)
  149. switch (sscanf(word1, "*:%d:%d:%d", &r1, &g1, &b1)) {
  150. case 1:
  151. undef = 1;
  152. b1 = g1 = r1;
  153. break;
  154. case 3:
  155. undef = 1;
  156. break;
  157. }
  158. if (!null && !undef)
  159. switch (sscanf(word1, "%ld:%d:%d:%d", &cat1, &r1, &g1, &b1)) {
  160. case 2:
  161. b1 = g1 = r1;
  162. break;
  163. case 4:
  164. break;
  165. default:
  166. if (sscanf(word1, "%lf:%d:%d:%d", &val1, &r1, &g1, &b1) == 4)
  167. fp_rule = 1;
  168. else if (sscanf(word1, "%lf:%d", &val1, &r1) == 2) {
  169. fp_rule = 1;
  170. b1 = g1 = r1;
  171. }
  172. else
  173. continue; /* other lines are ignored */
  174. }
  175. if (n == 2) {
  176. switch (sscanf(word2, "%ld:%d:%d:%d", &cat2, &r2, &g2, &b2)) {
  177. case 2:
  178. b2 = g2 = r2;
  179. if (fp_rule)
  180. val2 = (DCELL) cat2;
  181. break;
  182. case 4:
  183. if (fp_rule)
  184. val2 = (DCELL) cat2;
  185. break;
  186. default:
  187. if (sscanf(word2, "%lf:%d:%d:%d", &val2, &r2, &g2, &b2) == 4) {
  188. if (!fp_rule)
  189. val1 = (DCELL) cat1;
  190. fp_rule = 1;
  191. }
  192. else if (sscanf(word2, "%lf:%d", &val2, &r2) == 2) {
  193. if (!fp_rule)
  194. val1 = (DCELL) cat1;
  195. fp_rule = 1;
  196. b2 = g2 = r2;
  197. }
  198. else
  199. continue; /* other lines are ignored */
  200. }
  201. }
  202. else {
  203. if (!fp_rule)
  204. cat2 = cat1;
  205. else
  206. val2 = val1;
  207. r2 = r1;
  208. g2 = g1;
  209. b2 = b1;
  210. }
  211. if (null)
  212. Rast_set_null_value_color(r1, g1, b1, colors);
  213. else if (undef)
  214. Rast_set_default_color(r1, g1, b1, colors);
  215. else if (modular) {
  216. if (fp_rule)
  217. Rast_add_modular_d_color_rule((DCELL *) & val1, r1, g1,
  218. b1, (DCELL *) & val2, r2,
  219. g2, b2, colors);
  220. else
  221. Rast_add_modular_c_color_rule((CELL *) &cat1, r1, g1, b1,
  222. (CELL *) &cat2, r2, g2, b2, colors);
  223. }
  224. else {
  225. if (fp_rule)
  226. Rast_add_d_color_rule((DCELL *) & val1, r1, g1, b1,
  227. (DCELL *) & val2, r2, g2, b2,
  228. colors);
  229. else
  230. Rast_add_c_color_rule((CELL *) &cat1, r1, g1, b1,
  231. (CELL *) &cat2, r2, g2, b2, colors);
  232. }
  233. /*
  234. fprintf (stderr, "adding rule %d=%.2lf %d %d %d %d=%.2lf %d %d %d\n", cat1,val1, r1, g1, b1, cat2, val2, r2, g2, b2);
  235. */
  236. }
  237. return 1;
  238. }
  239. static int read_old_colors(FILE * fd, struct Colors *colors)
  240. {
  241. char buf[256];
  242. long n;
  243. long min;
  244. float red_f, grn_f, blu_f;
  245. int red, grn, blu;
  246. int old;
  247. int zero;
  248. Rast_init_colors(colors);
  249. /*
  250. * first line in pre 3.0 color files is number of colors - ignore
  251. * otherwise it is #min first color, and the next line is for color 0
  252. */
  253. if (fgets(buf, sizeof buf, fd) == NULL)
  254. return -1;
  255. G_strip(buf);
  256. if (*buf == '#') { /* 3.0 format */
  257. old = 0;
  258. if (sscanf(buf + 1, "%ld", &min) != 1) /* first color */
  259. return -1;
  260. zero = 1;
  261. }
  262. else {
  263. old = 1;
  264. min = 0;
  265. zero = 0;
  266. }
  267. colors->cmin = min;
  268. n = min;
  269. while (fgets(buf, sizeof buf, fd)) {
  270. if (old) {
  271. if (sscanf(buf, "%f %f %f", &red_f, &grn_f, &blu_f) != 3)
  272. return -1;
  273. red = 256 * red_f;
  274. grn = 256 * grn_f;
  275. blu = 256 * blu_f;
  276. }
  277. else {
  278. switch (sscanf(buf, "%d %d %d", &red, &grn, &blu)) {
  279. case 1:
  280. blu = grn = red;
  281. break;
  282. case 2:
  283. blu = grn;
  284. break;
  285. case 3:
  286. break;
  287. default:
  288. return -1;
  289. }
  290. }
  291. if (zero) {
  292. Rast__insert_color_into_lookup((CELL) 0, red, grn, blu,
  293. &colors->fixed);
  294. zero = 0;
  295. }
  296. else
  297. Rast__insert_color_into_lookup((CELL) n++, red, grn, blu,
  298. &colors->fixed);
  299. }
  300. colors->cmax = n - 1;
  301. return 0;
  302. }
  303. /*---------------------------------------------------------------------------*/
  304. /*!
  305. \brief Writes the \p colors for map \p name in \p mapset into a color file.
  306. \param name 3D raster map name
  307. \param mapset mapset name
  308. \param colors colors to be associated with a map
  309. \see Rast3d_read_colors, Rast3d_remove_color, Rast_write_colors
  310. */
  311. int Rast3d_write_colors(const char *name, const char *mapset, struct Colors *colors)
  312. /* adapted from Rast_write_colors */
  313. {
  314. FILE *fd;
  315. if (strcmp(mapset, G_mapset()) != 0) {
  316. G_warning(_("mapset <%s> is not the current mapset"), mapset);
  317. return -1;
  318. }
  319. fd = G_fopen_new_misc(RASTER3D_DIRECTORY, RASTER3D_COLOR_ELEMENT, name);
  320. if (!fd)
  321. return -1;
  322. Rast__write_colors(fd, colors);
  323. fclose(fd);
  324. return 1;
  325. }
  326. /*---------------------------------------------------------------------------*/
  327. /*---------------------------------------------------------------------------*/
  328. /*---------------------------------------------------------------------------*/