color_write.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. /**********************************************************************
  2. * G_write_colors (name, mapset, colors)
  3. * char *name name of map
  4. * char *mapset mapset that map belongs to
  5. * struct Colors *colors structure holding color info
  6. *
  7. * Writes the color information associated with map layer "map"
  8. * in mapset "mapset" from the structure "colors".
  9. *
  10. * returns: 1 if successful
  11. * -1 on fail
  12. *
  13. * If the environment variable FORCE_GRASS3_COLORS is set (to anything at all)
  14. * then the output format is 3.0, even if the structure contains 4.0 rules.
  15. * This allows users to create 3.0 color files for export to sites which
  16. * don't yet have 4.0
  17. ***********************************************************************/
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <grass/gis.h>
  22. #define PRECISION 30
  23. #define THRESHOLD .0000000000000000000000000000005
  24. /* .5 * 10 ^(-30) */
  25. static int write_new_colors(FILE *, struct Colors *);
  26. static int write_rules(FILE *, struct _Color_Rule_ *, DCELL, DCELL);
  27. static int write_old_colors(FILE *, struct Colors *);
  28. static int forced_write_old_colors(FILE *, struct Colors *);
  29. static int format_min(char *, double);
  30. static int format_max(char *, double);
  31. /*!
  32. * \brief write map layer color table
  33. *
  34. * The color table is written for the
  35. * raster map <b>name</b> in the specified <b>mapset</b> from the
  36. * <b>colors</b> structure.
  37. * If there is an error, -1 is returned. No diagnostic is printed. Otherwise, 1
  38. * is returned.
  39. * The <b>colors</b> structure must be created properly, i.e.,
  40. * <i>G_init_colors</i> to initialize the structure and
  41. * <i>G_add_color_rule</i> to set the category colors.\remarks{These
  42. * routines are called by higher level routines which read or create entire
  43. * color tables, such as<i>G_read_colors</i> or
  44. * <i>G_make_ramp_colors.</i>}
  45. * <b>Note.</b> The calling sequence for this function deserves special
  46. * attention. The <b>mapset</b> parameter seems to imply that it is possible
  47. * to overwrite the color table for a raster map which is in another mapset.
  48. * However, this is not what actually happens. It is very useful for users to
  49. * create their own color tables for raster maps in other mapsets, but without
  50. * overwriting other users' color tables for the same raster map. If
  51. * <b>mapset</b> is the current mapset, then the color file for <b>name</b>
  52. * will be overwritten by the new color table. But if <b>mapset</b> is not the
  53. * current mapset, then the color table is actually written in the current
  54. * mapset under the <b>colr2</b> element as: colr2/mapset/name.
  55. *
  56. * \param name
  57. * \param mapset
  58. * \param colors
  59. * \return int
  60. */
  61. /*!
  62. * \brief
  63. *
  64. * The rules are written out using
  65. * floating-point format, removing trailing zeros (possibly producing integers).
  66. * The flag marking the colors as floating-point is <b>not</b> written.
  67. *
  68. * \return int
  69. */
  70. int G_write_colors(const char *name, const char *mapset,
  71. struct Colors *colors)
  72. {
  73. char element[512];
  74. char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
  75. FILE *fd;
  76. int stat;
  77. if (G__name_is_fully_qualified(name, xname, xmapset)) {
  78. if (strcmp(xmapset, mapset) != 0)
  79. return -1;
  80. name = xname;
  81. }
  82. /*
  83. * if mapset is current mapset, remove colr2 file (created by pre 3.0 grass)
  84. * and then write original color table
  85. * else write secondary color table
  86. */
  87. sprintf(element, "colr2/%s", mapset);
  88. if (strcmp(mapset, G_mapset()) == 0) {
  89. G_remove(element, name); /* get rid of existing colr2, if any */
  90. strcpy(element, "colr");
  91. }
  92. if (!(fd = G_fopen_new(element, name)))
  93. return -1;
  94. stat = G__write_colors(fd, colors);
  95. fclose(fd);
  96. return stat;
  97. }
  98. int G__write_colors(FILE * fd, struct Colors *colors)
  99. {
  100. if (getenv("FORCE_GRASS3_COLORS"))
  101. return forced_write_old_colors(fd, colors);
  102. else if (colors->version < 0)
  103. return write_old_colors(fd, colors);
  104. else
  105. return write_new_colors(fd, colors);
  106. }
  107. static int write_new_colors(FILE * fd, struct Colors *colors)
  108. {
  109. char str1[100], str2[100];
  110. format_min(str1, (double)colors->cmin);
  111. format_max(str2, (double)colors->cmax);
  112. fprintf(fd, "%% %s %s\n", str1, str2);
  113. if (colors->shift) {
  114. sprintf(str2, "%.10f", (double)colors->shift);
  115. G_trim_decimal(str2);
  116. fprintf(fd, "shift:%s\n", str2);
  117. }
  118. if (colors->invert)
  119. fprintf(fd, "invert\n");
  120. if (colors->null_set) {
  121. fprintf(fd, "nv:%d", colors->null_red);
  122. if (colors->null_red != colors->null_grn || colors->null_red
  123. != colors->null_blu)
  124. fprintf(fd, ":%d:%d", colors->null_grn, colors->null_blu);
  125. fprintf(fd, "\n");
  126. }
  127. if (colors->undef_set) {
  128. fprintf(fd, "*:%d", colors->undef_red);
  129. if (colors->undef_red != colors->undef_grn || colors->undef_red
  130. != colors->undef_blu)
  131. fprintf(fd, ":%d:%d", colors->undef_grn, colors->undef_blu);
  132. fprintf(fd, "\n");
  133. }
  134. if (colors->modular.rules) {
  135. fprintf(fd, "%s\n", "%%");
  136. write_rules(fd, colors->modular.rules, colors->cmin, colors->cmax);
  137. fprintf(fd, "%s\n", "%%");
  138. }
  139. if (colors->fixed.rules)
  140. write_rules(fd, colors->fixed.rules, colors->cmin, colors->cmax);
  141. return 1;
  142. }
  143. static int write_rules(FILE * fd, struct _Color_Rule_ *crules, DCELL dmin, DCELL dmax /* overall min and max data values in color table */
  144. )
  145. {
  146. struct _Color_Rule_ *rule;
  147. char str[100];
  148. /* find the end of the rules list */
  149. rule = crules;
  150. while (rule->next)
  151. rule = rule->next;
  152. /* write out the rules in reverse order */
  153. for (; rule; rule = rule->prev) {
  154. if (rule->low.value == dmin)
  155. format_min(str, (double)rule->low.value);
  156. else {
  157. sprintf(str, "%.10f", (double)rule->low.value);
  158. G_trim_decimal(str);
  159. }
  160. fprintf(fd, "%s:%d", str, (int)rule->low.red);
  161. if (rule->low.red != rule->low.grn || rule->low.red != rule->low.blu)
  162. fprintf(fd, ":%d:%d", rule->low.grn, rule->low.blu);
  163. /* even if low==high, write second end when the high is dmax */
  164. if (rule->high.value == dmax || rule->low.value != rule->high.value) {
  165. if (rule->high.value == dmax)
  166. format_max(str, (double)rule->high.value);
  167. else {
  168. sprintf(str, "%.10f", (double)rule->high.value);
  169. G_trim_decimal(str);
  170. }
  171. fprintf(fd, " %s:%d", str, (int)rule->high.red);
  172. if (rule->high.red != rule->high.grn ||
  173. rule->high.red != rule->high.blu)
  174. fprintf(fd, ":%d:%d", rule->high.grn, rule->high.blu);
  175. }
  176. fprintf(fd, "\n");
  177. }
  178. return 0;
  179. }
  180. static int write_old_colors(FILE * fd, struct Colors *colors)
  181. {
  182. int i, n;
  183. fprintf(fd, "#%ld first color\n", (long)colors->fixed.min);
  184. if (colors->null_set) {
  185. fprintf(fd, "%d %d %d\n",
  186. (int)colors->null_red,
  187. (int)colors->null_grn, (int)colors->null_blu);
  188. }
  189. else
  190. fprintf(fd, "255 255 255\n"); /* white */
  191. n = colors->fixed.max - colors->fixed.min + 1;
  192. for (i = 0; i < n; i++) {
  193. fprintf(fd, "%d", (int)colors->fixed.lookup.red[i]);
  194. if (colors->fixed.lookup.red[i] != colors->fixed.lookup.grn[i]
  195. || colors->fixed.lookup.red[i] != colors->fixed.lookup.blu[i])
  196. fprintf(fd, " %d %d",
  197. (int)colors->fixed.lookup.grn[i],
  198. (int)colors->fixed.lookup.blu[i]);
  199. fprintf(fd, "\n");
  200. }
  201. return 1;
  202. }
  203. static int forced_write_old_colors(FILE * fd, struct Colors *colors)
  204. {
  205. int red, grn, blu;
  206. CELL cat;
  207. fprintf(fd, "#%ld first color\n", (long)colors->cmin);
  208. G_get_color((CELL) 0, &red, &grn, &blu, colors);
  209. fprintf(fd, "%d %d %d\n", red, grn, blu);
  210. for (cat = colors->cmin; cat <= colors->cmax; cat++) {
  211. G_get_color(cat, &red, &grn, &blu, colors);
  212. fprintf(fd, "%d", red);
  213. if (red != grn || red != blu)
  214. fprintf(fd, " %d %d", grn, blu);
  215. fprintf(fd, "\n");
  216. }
  217. return 1;
  218. }
  219. static int format_min(char *str, double dval)
  220. {
  221. double dtmp;
  222. sprintf(str, "%.*f", PRECISION, dval);
  223. G_trim_decimal(str);
  224. sscanf(str, "%lf", &dtmp);
  225. if (dtmp != dval) { /* if no zeros after decimal point were trimmed */
  226. sprintf(str, "%.*f", PRECISION, dval - THRESHOLD);
  227. /* because precision is probably higher than PRECISION */
  228. }
  229. return 0;
  230. }
  231. static int format_max(char *str, double dval)
  232. {
  233. double dtmp;
  234. sprintf(str, "%.*f", PRECISION, dval);
  235. G_trim_decimal(str);
  236. sscanf(str, "%lf", &dtmp);
  237. if (dtmp != dval) { /* if no zeros after decimal point were trimmed */
  238. sprintf(str, "%.*f", PRECISION, dval + THRESHOLD);
  239. /* because precision is probably higher than PRECISION */
  240. }
  241. return 0;
  242. }