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