color_write.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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 void write_rules(FILE *, struct _Color_Rule_ *, DCELL, DCELL);
  26. static void write_new_colors(FILE *, struct Colors *);
  27. static void write_old_colors(FILE *, struct Colors *);
  28. static void forced_write_old_colors(FILE *, struct Colors *);
  29. static void format_min(char *, double);
  30. static void 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. if (G__name_is_fully_qualified(name, xname, xmapset)) {
  77. if (strcmp(xmapset, mapset) != 0)
  78. return -1;
  79. name = xname;
  80. }
  81. /*
  82. * if mapset is current mapset, remove colr2 file (created by pre 3.0 grass)
  83. * and then write original color table
  84. * else write secondary color table
  85. */
  86. sprintf(element, "colr2/%s", mapset);
  87. if (strcmp(mapset, G_mapset()) == 0) {
  88. G_remove(element, name); /* get rid of existing colr2, if any */
  89. strcpy(element, "colr");
  90. }
  91. if (!(fd = G_fopen_new(element, name)))
  92. return -1;
  93. G__write_colors(fd, colors);
  94. fclose(fd);
  95. return 1;
  96. }
  97. void G__write_colors(FILE * fd, struct Colors *colors)
  98. {
  99. if (getenv("FORCE_GRASS3_COLORS"))
  100. forced_write_old_colors(fd, colors);
  101. else if (colors->version < 0)
  102. write_old_colors(fd, colors);
  103. else
  104. write_new_colors(fd, colors);
  105. }
  106. static void write_new_colors(FILE * fd, struct Colors *colors)
  107. {
  108. char str1[100], str2[100];
  109. format_min(str1, (double)colors->cmin);
  110. format_max(str2, (double)colors->cmax);
  111. fprintf(fd, "%% %s %s\n", str1, str2);
  112. if (colors->shift) {
  113. sprintf(str2, "%.10f", (double)colors->shift);
  114. G_trim_decimal(str2);
  115. fprintf(fd, "shift:%s\n", str2);
  116. }
  117. if (colors->invert)
  118. fprintf(fd, "invert\n");
  119. if (colors->null_set) {
  120. fprintf(fd, "nv:%d", colors->null_red);
  121. if (colors->null_red != colors->null_grn || colors->null_red
  122. != colors->null_blu)
  123. fprintf(fd, ":%d:%d", colors->null_grn, colors->null_blu);
  124. fprintf(fd, "\n");
  125. }
  126. if (colors->undef_set) {
  127. fprintf(fd, "*:%d", colors->undef_red);
  128. if (colors->undef_red != colors->undef_grn || colors->undef_red
  129. != colors->undef_blu)
  130. fprintf(fd, ":%d:%d", colors->undef_grn, colors->undef_blu);
  131. fprintf(fd, "\n");
  132. }
  133. if (colors->modular.rules) {
  134. fprintf(fd, "%s\n", "%%");
  135. write_rules(fd, colors->modular.rules, colors->cmin, colors->cmax);
  136. fprintf(fd, "%s\n", "%%");
  137. }
  138. if (colors->fixed.rules)
  139. write_rules(fd, colors->fixed.rules, colors->cmin, colors->cmax);
  140. }
  141. /* overall min and max data values in color table */
  142. static void write_rules(FILE * fd, struct _Color_Rule_ *crules, DCELL dmin, DCELL dmax)
  143. {
  144. struct _Color_Rule_ *rule;
  145. char str[100];
  146. /* find the end of the rules list */
  147. rule = crules;
  148. while (rule->next)
  149. rule = rule->next;
  150. /* write out the rules in reverse order */
  151. for (; rule; rule = rule->prev) {
  152. if (rule->low.value == dmin)
  153. format_min(str, (double)rule->low.value);
  154. else {
  155. sprintf(str, "%.10f", (double)rule->low.value);
  156. G_trim_decimal(str);
  157. }
  158. fprintf(fd, "%s:%d", str, (int)rule->low.red);
  159. if (rule->low.red != rule->low.grn || rule->low.red != rule->low.blu)
  160. fprintf(fd, ":%d:%d", rule->low.grn, rule->low.blu);
  161. /* even if low==high, write second end when the high is dmax */
  162. if (rule->high.value == dmax || rule->low.value != rule->high.value) {
  163. if (rule->high.value == dmax)
  164. format_max(str, (double)rule->high.value);
  165. else {
  166. sprintf(str, "%.10f", (double)rule->high.value);
  167. G_trim_decimal(str);
  168. }
  169. fprintf(fd, " %s:%d", str, (int)rule->high.red);
  170. if (rule->high.red != rule->high.grn ||
  171. rule->high.red != rule->high.blu)
  172. fprintf(fd, ":%d:%d", rule->high.grn, rule->high.blu);
  173. }
  174. fprintf(fd, "\n");
  175. }
  176. }
  177. static void write_old_colors(FILE * fd, struct Colors *colors)
  178. {
  179. int i, n;
  180. fprintf(fd, "#%ld first color\n", (long)colors->fixed.min);
  181. if (colors->null_set) {
  182. fprintf(fd, "%d %d %d\n",
  183. (int)colors->null_red,
  184. (int)colors->null_grn, (int)colors->null_blu);
  185. }
  186. else
  187. fprintf(fd, "255 255 255\n"); /* white */
  188. n = colors->fixed.max - colors->fixed.min + 1;
  189. for (i = 0; i < n; i++) {
  190. fprintf(fd, "%d", (int)colors->fixed.lookup.red[i]);
  191. if (colors->fixed.lookup.red[i] != colors->fixed.lookup.grn[i]
  192. || colors->fixed.lookup.red[i] != colors->fixed.lookup.blu[i])
  193. fprintf(fd, " %d %d",
  194. (int)colors->fixed.lookup.grn[i],
  195. (int)colors->fixed.lookup.blu[i]);
  196. fprintf(fd, "\n");
  197. }
  198. }
  199. static void forced_write_old_colors(FILE * fd, struct Colors *colors)
  200. {
  201. int red, grn, blu;
  202. CELL cat;
  203. fprintf(fd, "#%ld first color\n", (long)colors->cmin);
  204. G_get_color((CELL) 0, &red, &grn, &blu, colors);
  205. fprintf(fd, "%d %d %d\n", red, grn, blu);
  206. for (cat = colors->cmin; cat <= colors->cmax; cat++) {
  207. G_get_color(cat, &red, &grn, &blu, colors);
  208. fprintf(fd, "%d", red);
  209. if (red != grn || red != blu)
  210. fprintf(fd, " %d %d", grn, blu);
  211. fprintf(fd, "\n");
  212. }
  213. }
  214. static void format_min(char *str, double dval)
  215. {
  216. double dtmp;
  217. sprintf(str, "%.*f", PRECISION, dval);
  218. G_trim_decimal(str);
  219. sscanf(str, "%lf", &dtmp);
  220. if (dtmp != dval) { /* if no zeros after decimal point were trimmed */
  221. sprintf(str, "%.*f", PRECISION, dval - THRESHOLD);
  222. /* because precision is probably higher than PRECISION */
  223. }
  224. }
  225. static void format_max(char *str, double dval)
  226. {
  227. double dtmp;
  228. sprintf(str, "%.*f", PRECISION, dval);
  229. G_trim_decimal(str);
  230. sscanf(str, "%lf", &dtmp);
  231. if (dtmp != dval) { /* if no zeros after decimal point were trimmed */
  232. sprintf(str, "%.*f", PRECISION, dval + THRESHOLD);
  233. /* because precision is probably higher than PRECISION */
  234. }
  235. }