GRASS Programmer's Manual  6.4.2(2012)
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
color_write.c
Go to the documentation of this file.
1 
2 /**********************************************************************
3  * G_write_colors (name, mapset, colors)
4  * char *name name of map
5  * char *mapset mapset that map belongs to
6  * struct Colors *colors structure holding color info
7  *
8  * Writes the color information associated with map layer "map"
9  * in mapset "mapset" from the structure "colors".
10  *
11  * returns: 1 if successful
12  * -1 on fail
13  *
14  * If the environment variable FORCE_GRASS3_COLORS is set (to anything at all)
15  * then the output format is 3.0, even if the structure contains 4.0 rules.
16  * This allows users to create 3.0 color files for export to sites which
17  * don't yet have 4.0
18  ***********************************************************************/
19 #include <string.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <grass/gis.h>
23 #define PRECISION 30
24 #define THRESHOLD .0000000000000000000000000000005
25 /* .5 * 10 ^(-30) */
26 
27 static int write_new_colors(FILE *, struct Colors *);
28 static int write_rules(FILE *, struct _Color_Rule_ *, DCELL, DCELL);
29 static int write_old_colors(FILE *, struct Colors *);
30 static int forced_write_old_colors(FILE *, struct Colors *);
31 static int format_min(char *, double);
32 static int format_max(char *, double);
33 
34 
77 int G_write_colors(const char *name, const char *mapset,
78  struct Colors *colors)
79 {
80  char element[512];
81  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
82  FILE *fd;
83  int stat;
84 
85  if (G__name_is_fully_qualified(name, xname, xmapset)) {
86  if (strcmp(xmapset, mapset) != 0)
87  return -1;
88  name = xname;
89  }
90  /*
91  * if mapset is current mapset, remove colr2 file (created by pre 3.0 grass)
92  * and then write original color table
93  * else write secondary color table
94  */
95  sprintf(element, "colr2/%s", mapset);
96  if (strcmp(mapset, G_mapset()) == 0) {
97  G_remove(element, name); /* get rid of existing colr2, if any */
98  strcpy(element, "colr");
99  }
100  if (!(fd = G_fopen_new(element, name)))
101  return -1;
102 
103  stat = G__write_colors(fd, colors);
104  fclose(fd);
105  return stat;
106 }
107 
108 int G__write_colors(FILE * fd, struct Colors *colors)
109 {
110  if (getenv("FORCE_GRASS3_COLORS"))
111  return forced_write_old_colors(fd, colors);
112  else if (colors->version < 0)
113  return write_old_colors(fd, colors);
114  else
115  return write_new_colors(fd, colors);
116 }
117 
118 static int write_new_colors(FILE * fd, struct Colors *colors)
119 {
120  char str1[100], str2[100];
121 
122  format_min(str1, (double)colors->cmin);
123  format_max(str2, (double)colors->cmax);
124  fprintf(fd, "%% %s %s\n", str1, str2);
125 
126  if (colors->shift) {
127  sprintf(str2, "%.10f", (double)colors->shift);
128  G_trim_decimal(str2);
129  fprintf(fd, "shift:%s\n", str2);
130  }
131  if (colors->invert)
132  fprintf(fd, "invert\n");
133 
134  if (colors->null_set) {
135  fprintf(fd, "nv:%d", colors->null_red);
136  if (colors->null_red != colors->null_grn || colors->null_red
137  != colors->null_blu)
138  fprintf(fd, ":%d:%d", colors->null_grn, colors->null_blu);
139  fprintf(fd, "\n");
140  }
141  if (colors->undef_set) {
142  fprintf(fd, "*:%d", colors->undef_red);
143  if (colors->undef_red != colors->undef_grn || colors->undef_red
144  != colors->undef_blu)
145  fprintf(fd, ":%d:%d", colors->undef_grn, colors->undef_blu);
146  fprintf(fd, "\n");
147  }
148  if (colors->modular.rules) {
149  fprintf(fd, "%s\n", "%%");
150  write_rules(fd, colors->modular.rules, colors->cmin, colors->cmax);
151  fprintf(fd, "%s\n", "%%");
152  }
153  if (colors->fixed.rules)
154  write_rules(fd, colors->fixed.rules, colors->cmin, colors->cmax);
155 
156  return 1;
157 }
158 
159 static int write_rules(FILE * fd, struct _Color_Rule_ *crules, DCELL dmin, DCELL dmax /* overall min and max data values in color table */
160  )
161 {
162  struct _Color_Rule_ *rule;
163  char str[100];
164 
165  /* find the end of the rules list */
166  rule = crules;
167  while (rule->next)
168  rule = rule->next;
169 
170  /* write out the rules in reverse order */
171  for (; rule; rule = rule->prev) {
172  if (rule->low.value == dmin)
173  format_min(str, (double)rule->low.value);
174  else {
175  sprintf(str, "%.10f", (double)rule->low.value);
176  G_trim_decimal(str);
177  }
178  fprintf(fd, "%s:%d", str, (int)rule->low.red);
179  if (rule->low.red != rule->low.grn || rule->low.red != rule->low.blu)
180  fprintf(fd, ":%d:%d", rule->low.grn, rule->low.blu);
181  /* even if low==high, write second end when the high is dmax */
182  if (rule->high.value == dmax || rule->low.value != rule->high.value) {
183  if (rule->high.value == dmax)
184  format_max(str, (double)rule->high.value);
185  else {
186  sprintf(str, "%.10f", (double)rule->high.value);
187  G_trim_decimal(str);
188  }
189  fprintf(fd, " %s:%d", str, (int)rule->high.red);
190  if (rule->high.red != rule->high.grn ||
191  rule->high.red != rule->high.blu)
192  fprintf(fd, ":%d:%d", rule->high.grn, rule->high.blu);
193  }
194  fprintf(fd, "\n");
195  }
196 
197  return 0;
198 }
199 
200 static int write_old_colors(FILE * fd, struct Colors *colors)
201 {
202  int i, n;
203 
204  fprintf(fd, "#%ld first color\n", (long)colors->fixed.min);
205  if (colors->null_set) {
206  fprintf(fd, "%d %d %d\n",
207  (int)colors->null_red,
208  (int)colors->null_grn, (int)colors->null_blu);
209  }
210  else
211  fprintf(fd, "255 255 255\n"); /* white */
212 
213  n = colors->fixed.max - colors->fixed.min + 1;
214 
215  for (i = 0; i < n; i++) {
216  fprintf(fd, "%d", (int)colors->fixed.lookup.red[i]);
217  if (colors->fixed.lookup.red[i] != colors->fixed.lookup.grn[i]
218  || colors->fixed.lookup.red[i] != colors->fixed.lookup.blu[i])
219  fprintf(fd, " %d %d",
220  (int)colors->fixed.lookup.grn[i],
221  (int)colors->fixed.lookup.blu[i]);
222  fprintf(fd, "\n");
223  }
224 
225  return 1;
226 }
227 
228 static int forced_write_old_colors(FILE * fd, struct Colors *colors)
229 {
230  int red, grn, blu;
231  CELL cat;
232 
233  fprintf(fd, "#%ld first color\n", (long)colors->cmin);
234  G_get_color((CELL) 0, &red, &grn, &blu, colors);
235  fprintf(fd, "%d %d %d\n", red, grn, blu);
236 
237  for (cat = colors->cmin; cat <= colors->cmax; cat++) {
238  G_get_color(cat, &red, &grn, &blu, colors);
239  fprintf(fd, "%d", red);
240  if (red != grn || red != blu)
241  fprintf(fd, " %d %d", grn, blu);
242  fprintf(fd, "\n");
243  }
244 
245  return 1;
246 }
247 
248 static int format_min(char *str, double dval)
249 {
250  double dtmp;
251 
252  sprintf(str, "%.*f", PRECISION, dval);
253  G_trim_decimal(str);
254  sscanf(str, "%lf", &dtmp);
255  if (dtmp != dval) { /* if no zeros after decimal point were trimmed */
256  sprintf(str, "%.*f", PRECISION, dval - THRESHOLD);
257  /* because precision is probably higher than PRECISION */
258  }
259 
260  return 0;
261 }
262 
263 static int format_max(char *str, double dval)
264 {
265  double dtmp;
266 
267  sprintf(str, "%.*f", PRECISION, dval);
268  G_trim_decimal(str);
269  sscanf(str, "%lf", &dtmp);
270  if (dtmp != dval) { /* if no zeros after decimal point were trimmed */
271  sprintf(str, "%.*f", PRECISION, dval + THRESHOLD);
272  /* because precision is probably higher than PRECISION */
273  }
274 
275  return 0;
276 }