GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
Loading...
Searching...
No Matches
raster/color_read.c
Go to the documentation of this file.
1/*!
2 \file lib/raster/color_read.c
3
4 \brief Raster Library - Read color table of raster map
5
6 (C) 1999-2009, 2011 by the GRASS Development Team
7
8 This program is free software under the GNU General Public
9 License (>=v2). Read the file COPYING that comes with GRASS
10 for details.
11
12 \author USACERL and many others
13 */
14
15#include <string.h>
16
17#include <grass/gis.h>
18#include <grass/raster.h>
19#include <grass/glocale.h>
20
21static int read_new_colors(FILE *, struct Colors *);
22static int read_old_colors(FILE *, struct Colors *);
23
24/*!
25 \brief Read color table of raster map
26
27 The color table for the raster map <i>name</i> in the specified
28 <i>mapset</i> is read into the <i>colors</i> structure. If the data
29 layer has no color table, a default color table is generated and 0
30 is returned. If there is an error reading the color table, a
31 diagnostic message is printed and -1 is returned. If the color
32 table is read ok, 1 is returned.
33
34 This routine reads the rules from the color file. If the input
35 raster map is is a floating-point map it calls
36 Rast_mark_colors_as_fp().
37
38 Note: If a secondary color file for map name <i>name</i> exists in
39 the current project, that color file is read. This allows the
40 user to define their own color lookup tables for cell maps found
41 in other mapsets.
42
43 Warning message is printed if the color file is
44 missing or invalid.
45
46 \param name map name
47 \param mapset mapset name
48 \param[out] colors pointer to Colors structure
49
50 \return -1 on error
51 \return 0 if missing, but default colors generated
52 \return 1 on success
53 */
54int Rast_read_colors(const char *name, const char *mapset,
55 struct Colors *colors)
56{
57 int fp;
58 char buf[GNAME_MAX];
59 char *err;
60 char xname[GNAME_MAX];
61 struct Range range;
62 struct FPRange drange;
63 CELL min, max;
64 DCELL dmin, dmax;
65
66 fp = Rast_map_is_fp(name, mapset);
67 Rast_init_colors(colors);
68
70 mapset = G_find_raster(xname, mapset);
71 name = xname;
72
73 if (fp)
75
76 /* first look for secondary color table in current mapset */
77 snprintf(buf, sizeof(buf), "colr2/%s", mapset);
78 if (Rast__read_colors(buf, name, G_mapset(), colors) >= 0)
79 return 1;
80
81 /* now look for the regular color table */
82 switch (Rast__read_colors("colr", name, mapset, colors)) {
83 case -2:
84 if (!fp) {
85 if (Rast_read_range(name, mapset, &range) >= 0) {
86 Rast_get_range_min_max(&range, &min, &max);
89 return 0;
90 }
91 }
92 else {
93 if (Rast_read_fp_range(name, mapset, &drange) >= 0) {
95 if (!Rast_is_d_null_value(&dmin) &&
98 dmax);
99 return 0;
100 }
101 }
102 err = _("missing");
103 break;
104 case -1:
105 err = _("invalid");
106 break;
107 default:
108 return 1;
109 }
110
111 G_warning(_("Color support for <%s@%s> %s"), name, mapset, err);
112 return -1;
113}
114
115int Rast__read_colors(const char *element, const char *name, const char *mapset,
116 struct Colors *colors)
117{
118 FILE *fd;
119 int stat;
120 char buf[1024];
121
122 if (!(fd = G_fopen_old(element, name, mapset)))
123 return -2;
124
125 /*
126 * first line in 4.0 color files is %
127 * otherwise it is pre 4.0
128 */
129 if (fgets(buf, sizeof buf, fd) == NULL) {
130 fclose(fd);
131 return -1;
132 }
133
134 stat = 1;
135 if (colors) {
136 G_fseek(fd, 0L, 0);
137
138 G_strip(buf);
139 if (*buf == '%') { /* 4.0 format */
140 stat = read_new_colors(fd, colors);
141 colors->version = 0; /* 4.0 format */
142 }
143 else {
144 stat = read_old_colors(fd, colors);
145 colors->version = -1; /* pre 4.0 format */
146 }
147 }
148
149 fclose(fd);
150
151 return stat;
152}
153
154/* parse input lines with the following formats
155 * val1:r:g:b val2:r:g:b
156 * val:r:g:b (implies cat1==cat2)
157 *
158 * r:g:b can be just a single grey level
159 * cat1:x cat2:y
160 * cat:x
161 *
162 * optional lines are
163 * invert invert color table
164 * shift:n where n is the amount to shift the color table
165 * nv:r:g:b color to use for NULL values
166 * *:r:g:b color to use for undefined (beyond color rules)
167 */
168static int read_new_colors(FILE *fd, struct Colors *colors)
169{
170 double val1, val2;
171 long cat1, cat2;
172 int r1, g1, b1;
173 int r2, g2, b2;
174 char buf[1024];
175 char word1[256], word2[256];
176 int n, fp_rule;
177 int null, undef;
178 int modular;
179 DCELL shift;
180
181 if (fgets(buf, sizeof buf, fd) == NULL)
182 return -1;
183 G_strip(buf);
184
185 if (sscanf(buf + 1, "%lf %lf", &val1, &val2) == 2)
187
188 modular = 0;
189 while (fgets(buf, sizeof buf, fd)) {
190 null = undef = fp_rule = 0;
191 *word1 = *word2 = 0;
192 n = sscanf(buf, "%s %s", word1, word2);
193 if (n < 1)
194 continue;
195
196 if (sscanf(word1, "shift:%lf", &shift) == 1 ||
197 (strcmp(word1, "shift:") == 0 &&
198 sscanf(word2, "%lf", &shift) == 1)) {
199 Rast_shift_d_colors(shift, colors);
200 continue;
201 }
202 if (strcmp(word1, "invert") == 0) {
203 Rast_invert_colors(colors);
204 continue;
205 }
206 if (strcmp(word1, "%%") == 0) {
207 modular = !modular;
208 continue;
209 }
210
211 switch (sscanf(word1, "nv:%d:%d:%d", &r1, &g1, &b1)) {
212 case 1:
213 null = 1;
214 b1 = g1 = r1;
215 break;
216 case 3:
217 null = 1;
218 break;
219 }
220 if (!null)
221 switch (sscanf(word1, "*:%d:%d:%d", &r1, &g1, &b1)) {
222 case 1:
223 undef = 1;
224 b1 = g1 = r1;
225 break;
226 case 3:
227 undef = 1;
228 break;
229 }
230 if (!null && !undef)
231 switch (sscanf(word1, "%ld:%d:%d:%d", &cat1, &r1, &g1, &b1)) {
232 case 2:
233 b1 = g1 = r1;
234 break;
235 case 4:
236 break;
237 default:
238 if (sscanf(word1, "%lf:%d:%d:%d", &val1, &r1, &g1, &b1) == 4)
239 fp_rule = 1;
240 else if (sscanf(word1, "%lf:%d", &val1, &r1) == 2) {
241 fp_rule = 1;
242 b1 = g1 = r1;
243 }
244 else
245 continue; /* other lines are ignored */
246 }
247 if (n == 2) {
248 switch (sscanf(word2, "%ld:%d:%d:%d", &cat2, &r2, &g2, &b2)) {
249 case 2:
250 b2 = g2 = r2;
251 if (fp_rule)
252 val2 = (DCELL)cat2;
253 break;
254 case 4:
255 if (fp_rule)
256 val2 = (DCELL)cat2;
257 break;
258 default:
259 if (sscanf(word2, "%lf:%d:%d:%d", &val2, &r2, &g2, &b2) == 4) {
260 if (!fp_rule)
261 val1 = (DCELL)cat1;
262 fp_rule = 1;
263 }
264 else if (sscanf(word2, "%lf:%d", &val2, &r2) == 2) {
265 if (!fp_rule)
266 val1 = (DCELL)cat1;
267 fp_rule = 1;
268 b2 = g2 = r2;
269 }
270 else
271 continue; /* other lines are ignored */
272 }
273 }
274 else {
275 if (!fp_rule)
276 cat2 = cat1;
277 else
278 val2 = val1;
279 r2 = r1;
280 g2 = g1;
281 b2 = b1;
282 }
283 if (null)
285 else if (undef)
286 Rast_set_default_color(r1, g1, b1, colors);
287
288 else if (modular) {
289 if (fp_rule)
291 (DCELL *)&val2, r2, g2, b2,
292 colors);
293 else
295 (CELL *)&cat2, r2, g2, b2,
296 colors);
297 }
298 else {
299 if (fp_rule)
301 (DCELL *)&val2, r2, g2, b2, colors);
302 else
304 r2, g2, b2, colors);
305 }
306 G_debug(3, "adding rule %ld=%.2lf %d %d %d %ld=%.2lf %d %d %d", cat1,
307 val1, r1, g1, b1, cat2, val2, r2, g2, b2);
308 }
309 return 1;
310}
311
312static int read_old_colors(FILE *fd, struct Colors *colors)
313{
314 char buf[256];
315 long n;
316 long min;
317 float red_f, grn_f, blu_f;
318 int red, grn, blu;
319 int old;
320 int zero;
321
322 Rast_init_colors(colors);
323 /*
324 * first line in pre 3.0 color files is number of colors - ignore
325 * otherwise it is #min first color, and the next line is for color 0
326 */
327 if (fgets(buf, sizeof buf, fd) == NULL)
328 return -1;
329
330 G_strip(buf);
331 if (*buf == '#') { /* 3.0 format */
332 old = 0;
333 if (sscanf(buf + 1, "%ld", &min) != 1) /* first color */
334 return -1;
335 zero = 1;
336 }
337 else {
338 old = 1;
339 min = 0;
340 zero = 0;
341 }
342
343 colors->cmin = min;
344 n = min;
345 while (fgets(buf, sizeof buf, fd)) {
346 if (old) {
347 if (sscanf(buf, "%f %f %f", &red_f, &grn_f, &blu_f) != 3)
348 return -1;
349
350 red = 256 * red_f;
351 grn = 256 * grn_f;
352 blu = 256 * blu_f;
353 }
354 else {
355 switch (sscanf(buf, "%d %d %d", &red, &grn, &blu)) {
356 case 1:
357 blu = grn = red;
358 break;
359 case 2:
360 blu = grn;
361 break;
362 case 3:
363 break;
364 default:
365 return -1;
366 }
367 }
368 if (zero) {
369 Rast__insert_color_into_lookup((CELL)0, red, grn, blu,
370 &colors->fixed);
371 zero = 0;
372 }
373 else
374 Rast__insert_color_into_lookup((CELL)n++, red, grn, blu,
375 &colors->fixed);
376 }
377 colors->cmax = n - 1;
378
379 return 0;
380}
381
382/*!
383 * \brief Mark colors as floating-point.
384 *
385 * Sets a flag in the <i>colors</i> structure that indicates that
386 * these colors should only be looked up using floating-point raster
387 * data (not integer data). In particular if this flag is set, the
388 * routine Rast_get_c_colors_min_max() should return min=-255$^3$ and
389 * max=255$^3$.
390 *
391 * \param colors pointer to Colors structure
392 */
393void Rast_mark_colors_as_fp(struct Colors *colors)
394{
395 colors->is_float = 1;
396}
#define NULL
Definition ccmath.h:32
const char * G_find_raster(char *, const char *)
Find a raster map.
Definition find_rast.c:55
void G_warning(const char *,...) __attribute__((format(printf
void G_fseek(FILE *, off_t, int)
Change the file position of the stream.
Definition gis/seek.c:50
FILE * G_fopen_old(const char *, const char *, const char *)
Open a database file for reading.
Definition gis/open.c:253
void G_strip(char *)
Removes all leading and trailing white space from string.
Definition strings.c:300
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:33
void Rast_add_d_color_rule(const DCELL *, int, int, int, const DCELL *, int, int, int, struct Colors *)
Adds the floating-point color rule (DCELL version)
Definition color_rule.c:38
int Rast__insert_color_into_lookup(CELL, int, int, int, struct _Color_Info_ *)
Definition color_insrt.c:18
int Rast_read_fp_range(const char *, const char *, struct FPRange *)
Read floating-point range.
void Rast_set_null_value_color(int, int, int, struct Colors *)
Set color for NULL-value.
Definition color_set.c:79
int Rast_add_modular_c_color_rule(const CELL *, int, int, int, const CELL *, int, int, int, struct Colors *)
Add modular integer color rule (CELL version)
Definition color_rule.c:184
void Rast_get_fp_range_min_max(const struct FPRange *, DCELL *, DCELL *)
Get minimum and maximum value from fp range.
void Rast_add_c_color_rule(const CELL *, int, int, int, const CELL *, int, int, int, struct Colors *)
Adds the integer color rule (CELL version)
Definition color_rule.c:76
void Rast_get_range_min_max(const struct Range *, CELL *, CELL *)
Get range min and max.
void Rast_init_colors(struct Colors *)
Initialize color structure.
Definition color_init.c:25
int Rast_read_range(const char *, const char *, struct Range *)
Read raster range (CELL)
void Rast_set_d_color_range(DCELL, DCELL, struct Colors *)
Set color range (DCELL version)
Definition color_range.c:42
int Rast_map_is_fp(const char *, const char *)
Check if raster map is floating-point.
int Rast_add_modular_d_color_rule(const DCELL *, int, int, int, const DCELL *, int, int, int, struct Colors *)
Add modular floating-point color rule (DCELL version)
Definition color_rule.c:124
void Rast_make_fp_colors(struct Colors *, const char *, DCELL, DCELL)
Load color rules from predefined floating-point color table.
#define Rast_is_d_null_value(dcellVal)
#define Rast_is_c_null_value(cellVal)
void Rast_invert_colors(struct Colors *)
Definition color_invrt.c:17
void Rast_make_colors(struct Colors *, const char *, CELL, CELL)
Load color rules from predefined color table.
void Rast_set_default_color(int, int, int, struct Colors *)
Set default color value.
Definition color_set.c:99
void Rast_shift_d_colors(DCELL, struct Colors *)
Definition color_shift.c:22
#define min(x, y)
Definition draw2.c:29
#define max(x, y)
Definition draw2.c:30
#define DEFAULT_COLOR_TABLE
Definition gis.h:407
#define GNAME_MAX
Definition gis.h:196
double DCELL
Definition gis.h:635
int CELL
Definition gis.h:634
#define _(str)
Definition glocale.h:10
const char * name
Definition named_colr.c:6
#define strcpy
Definition parson.c:66
int Rast__read_colors(const char *element, const char *name, const char *mapset, struct Colors *colors)
int Rast_read_colors(const char *name, const char *mapset, struct Colors *colors)
Read color table of raster map.
void Rast_mark_colors_as_fp(struct Colors *colors)
Mark colors as floating-point.
Definition gis.h:692
int is_float
Definition gis.h:696
DCELL cmax
Definition gis.h:708
struct _Color_Info_ fixed
Definition gis.h:705
int version
Definition gis.h:693
DCELL cmin
Definition gis.h:707
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)