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
8
* Writes the color information associated with map layer "map"
9
* in mapset "mapset" from the structure "colors".
11
* returns: 1 if successful
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
18
***********************************************************************/
22
#include <grass/gis.h>
24
#define THRESHOLD .0000000000000000000000000000005
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);
36
* \brief write map layer color table
38
* The color table is written for the
39
* raster map <b>name</b> in the specified <b>mapset</b> from the
40
* <b>colors</b> structure.
41
* If there is an error, -1 is returned. No diagnostic is printed. Otherwise, 1
43
* The <b>colors</b> structure must be created properly, i.e.,
44
* <i>G_init_colors</i> to initialize the structure and
45
* <i>G_add_color_rule</i> to set the category colors.\remarks{These
46
* routines are called by higher level routines which read or create entire
47
* color tables, such as<i>G_read_colors</i> or
48
* <i>G_make_ramp_colors.</i>}
49
* <b>Note.</b> The calling sequence for this function deserves special
50
* attention. The <b>mapset</b> parameter seems to imply that it is possible
51
* to overwrite the color table for a raster map which is in another mapset.
52
* However, this is not what actually happens. It is very useful for users to
53
* create their own color tables for raster maps in other mapsets, but without
54
* overwriting other users' color tables for the same raster map. If
55
* <b>mapset</b> is the current mapset, then the color file for <b>name</b>
56
* will be overwritten by the new color table. But if <b>mapset</b> is not the
57
* current mapset, then the color table is actually written in the current
58
* mapset under the <b>colr2</b> element as: colr2/mapset/name.
70
* The rules are written out using
71
* floating-point format, removing trailing zeros (possibly producing integers).
72
* The flag marking the colors as floating-point is <b>not</b> written.
77
int G_write_colors(const char *name, const char *mapset,
78
struct Colors *colors)
81
char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
85
if (G__name_is_fully_qualified(name, xname, xmapset)) {
86
if (strcmp(xmapset, mapset) != 0)
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
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");
100
if (!(fd = G_fopen_new(element, name)))
103
stat = G__write_colors(fd, colors);
108
int G__write_colors(FILE * fd, struct Colors *colors)
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);
115
return write_new_colors(fd, colors);
118
static int write_new_colors(FILE * fd, struct Colors *colors)
120
char str1[100], str2[100];
122
format_min(str1, (double)colors->cmin);
123
format_max(str2, (double)colors->cmax);
124
fprintf(fd, "%% %s %s\n", str1, str2);
127
sprintf(str2, "%.10f", (double)colors->shift);
128
G_trim_decimal(str2);
129
fprintf(fd, "shift:%s\n", str2);
132
fprintf(fd, "invert\n");
134
if (colors->null_set) {
135
fprintf(fd, "nv:%d", colors->null_red);
136
if (colors->null_red != colors->null_grn || colors->null_red
138
fprintf(fd, ":%d:%d", colors->null_grn, colors->null_blu);
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);
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", "%%");
153
if (colors->fixed.rules)
154
write_rules(fd, colors->fixed.rules, colors->cmin, colors->cmax);
159
static int write_rules(FILE * fd, struct _Color_Rule_ *crules, DCELL dmin, DCELL dmax /* overall min and max data values in color table */
162
struct _Color_Rule_ *rule;
165
/* find the end of the rules list */
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);
175
sprintf(str, "%.10f", (double)rule->low.value);
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);
186
sprintf(str, "%.10f", (double)rule->high.value);
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);
200
static int write_old_colors(FILE * fd, struct Colors *colors)
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);
211
fprintf(fd, "255 255 255\n"); /* white */
213
n = colors->fixed.max - colors->fixed.min + 1;
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]);
228
static int forced_write_old_colors(FILE * fd, struct Colors *colors)
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);
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);
248
static int format_min(char *str, double dval)
252
sprintf(str, "%.*f", PRECISION, dval);
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 */
263
static int format_max(char *str, double dval)
267
sprintf(str, "%.*f", PRECISION, dval);
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 */