GRASS 8 Programmer's Manual 8.6.0dev(2026)-8843f13794
Loading...
Searching...
No Matches
color_rule.c
Go to the documentation of this file.
1/*!
2 \file lib/raster/color_rule.c
3
4 \brief Raster Library - Color rules.
5
6 SPDX-FileCopyrightText: 2001-2009 GRASS Development Team
7 SPDX-License-Identifier: GPL-2.0-or-later
8
9 \author Original author CERL
10 */
11
12#include <grass/gis.h>
13#include <grass/raster.h>
14
15#define LIMIT(x) \
16 if (x < 0) \
17 x = 0; \
18 else if (x > 255) \
19 x = 255;
20
21static void add_color_rule(const void *, int, int, int, const void *, int, int,
22 int, struct _Color_Info_ *, int, DCELL *, DCELL *,
24
25/*!
26 \brief Adds the floating-point color rule (DCELL version)
27
28 See Rast_add_color_rule() for details.
29
30 \param val1 cell value
31 \param r1,g1,b1 color value
32 \param val2 cell value
33 \param r2,g2,b2 color value
34 \param[in,out] colors pointer to color table structure
35 */
36void Rast_add_d_color_rule(const DCELL *val1, int r1, int g1, int b1,
37 const DCELL *val2, int r2, int g2, int b2,
38 struct Colors *colors)
39{
40 add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->fixed,
41 colors->version, &colors->cmin, &colors->cmax, DCELL_TYPE);
42}
43
44/*!
45 \brief Adds the floating-point color rule (FCELL version)
46
47 See Rast_add_color_rule() for details.
48
49 \param cat1 cell value
50 \param r1,g1,b1 color value
51 \param cat2 cell value
52 \param r2,g2,b2 color value
53 \param[in,out] colors pointer to color table structure
54 */
55void Rast_add_f_color_rule(const FCELL *cat1, int r1, int g1, int b1,
56 const FCELL *cat2, int r2, int g2, int b2,
57 struct Colors *colors)
58{
59 add_color_rule(cat1, r1, g1, b1, cat2, r2, g2, b2, &colors->fixed,
60 colors->version, &colors->cmin, &colors->cmax, FCELL_TYPE);
61}
62
63/*!
64 \brief Adds the integer color rule (CELL version)
65
66 See Rast_add_color_rule() for details.
67
68 \param cat1 cell value
69 \param r1,g1,b1 color value
70 \param cat2 cell value
71 \param r2,g2,b2 color value
72 \param[in,out] colors pointer to color table structure
73 */
74void Rast_add_c_color_rule(const CELL *cat1, int r1, int g1, int b1,
75 const CELL *cat2, int r2, int g2, int b2,
76 struct Colors *colors)
77{
78 add_color_rule(cat1, r1, g1, b1, cat2, r2, g2, b2, &colors->fixed,
79 colors->version, &colors->cmin, &colors->cmax, CELL_TYPE);
80}
81
82/*!
83 \brief Adds the color rule
84
85 Adds the floating-point rule that the range [<em>v1,v2</em>] gets a
86 linear ramp of colors from [<em>r1,g1,b1</em>] to
87 [<em>r2,g2,b2</em>].
88 If either <em>v1</em> or <em>v2</em> is the NULL-value, this call is
89 converted ino <tt>Rast_set_null_value_color (r1, g1, b1, colors)</tt>
90
91 - If <em>map_type</em> is CELL_TYPE, calls Rast_add_c_color_rule()
92 - If <em>map_type</em> is FCELL_TYPE, calls Rast_add_f_color_rule()
93 - If <em>map_type</em> is DCELL_TYPE, calls Rast_add_d_color_rule()
94
95 \param val1 cell value
96 \param r1,g1,b1 color value
97 \param val2 cell value
98 \param r2,g2,b2 color value
99 \param[in,out] colors pointer to color table structure
100 \param data_type raster data type (CELL, FCELL, DCELL)
101 */
102void Rast_add_color_rule(const void *val1, int r1, int g1, int b1,
103 const void *val2, int r2, int g2, int b2,
104 struct Colors *colors, RASTER_MAP_TYPE data_type)
105{
106 add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->fixed,
107 colors->version, &colors->cmin, &colors->cmax, data_type);
108}
109
110/*!
111 \brief Add modular floating-point color rule (DCELL version)
112
113 \param val1 cell value
114 \param r1,g1,b1 color value
115 \param val2 cell value
116 \param r2,g2,b2 color value
117 \param[in,out] colors pointer to color table structure
118
119 \return -1 on failure
120 \return 1 on success
121 */
122int Rast_add_modular_d_color_rule(const DCELL *val1, int r1, int g1, int b1,
123 const DCELL *val2, int r2, int g2, int b2,
124 struct Colors *colors)
125{
126 DCELL min, max;
127
128 if (colors->version < 0)
129 return -1; /* can't use this on 3.0 colors */
130 min = colors->cmin;
131 max = colors->cmax;
132 add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->modular, 0,
133 &colors->cmin, &colors->cmax, DCELL_TYPE);
134 colors->cmin = min; /* don't reset these */
135 colors->cmax = max;
136
137 return 1;
138}
139
140/*!
141 \brief Add modular floating-point color rule (FCELL version)
142
143 \param val1 cell value
144 \param r1,g1,b1 color value
145 \param val2 cell value
146 \param r2,g2,b2 color value
147 \param[in,out] colors pointer to color table structure
148
149 \return -1 on failure
150 \return 1 on success
151 */
152int Rast_add_modular_f_color_rule(const FCELL *val1, int r1, int g1, int b1,
153 const FCELL *val2, int r2, int g2, int b2,
154 struct Colors *colors)
155{
156 DCELL min, max;
157
158 if (colors->version < 0)
159 return -1; /* can;t use this on 3.0 colors */
160 min = colors->cmin;
161 max = colors->cmax;
162 add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->modular, 0,
163 &colors->cmin, &colors->cmax, FCELL_TYPE);
164 colors->cmin = min; /* don't reset these */
165 colors->cmax = max;
166
167 return 1;
168}
169
170/*!
171 \brief Add modular integer color rule (CELL version)
172
173 \param val1 cell value
174 \param r1,g1,b1 color value
175 \param val2 cell value
176 \param r2,g2,b2 color value
177 \param[in,out] colors pointer to color table structure
178
179 \return -1 on failure
180 \return 1 on success
181 */
182int Rast_add_modular_c_color_rule(const CELL *val1, int r1, int g1, int b1,
183 const CELL *val2, int r2, int g2, int b2,
184 struct Colors *colors)
185{
186 CELL min, max;
187
188 if (colors->version < 0)
189 return -1; /* can;t use this on 3.0 colors */
190 min = colors->cmin;
191 max = colors->cmax;
192 add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->modular, 0,
193 &colors->cmin, &colors->cmax, CELL_TYPE);
194 colors->cmin = min; /* don't reset these */
195 colors->cmax = max;
196
197 return 1;
198}
199
200/*!
201 \brief Add modular color rule
202
203 \todo Question: shouldn't this function call
204 G_add_modular_<data_type>_raster_color_rule() instead?
205
206 \param val1 cell value
207 \param r1,g1,b1 color value
208 \param val2 cell value
209 \param r2,g2,b2 color value
210 \param[in,out] colors pointer to color table structure
211 \param data_type raster data type
212
213 \return -1 on failure
214 \return 1 on success
215 */
216int Rast_add_modular_color_rule(const void *val1, int r1, int g1, int b1,
217 const void *val2, int r2, int g2, int b2,
218 struct Colors *colors,
219 RASTER_MAP_TYPE data_type)
220{
221 CELL min, max;
222
223 if (colors->version < 0)
224 return -1; /* can't use this on 3.0 colors */
225 min = colors->cmin;
226 max = colors->cmax;
227 add_color_rule(val1, r1, g1, b1, val2, r2, g2, b2, &colors->modular, 0,
228 &colors->cmin, &colors->cmax, data_type);
229 colors->cmin = min; /* don't reset these */
230 colors->cmax = max;
231
232 return 1;
233}
234
235static void add_color_rule(const void *pt1, int r1, int g1, int b1,
236 const void *pt2, int r2, int g2, int b2,
237 struct _Color_Info_ *cp, int version, DCELL *cmin,
238 DCELL *cmax, RASTER_MAP_TYPE data_type)
239{
240 struct _Color_Rule_ *rule, *next;
241 unsigned char red, grn, blu;
242 DCELL min, max, val1, val2;
243 CELL cat;
244
245 val1 = Rast_get_d_value(pt1, data_type);
246 val2 = Rast_get_d_value(pt2, data_type);
247 /* allocate a low:high rule */
248 rule = (struct _Color_Rule_ *)G_malloc(sizeof(*rule));
249 rule->next = rule->prev = NULL;
250
251 /* make sure colors are in the range [0,255] */
252 LIMIT(r1);
253 LIMIT(g1);
254 LIMIT(b1);
255 LIMIT(r2);
256 LIMIT(g2);
257 LIMIT(b2);
258
259 /* val1==val2, use average color */
260 /* otherwise make sure low < high */
261 if (val1 == val2) {
262 rule->low.value = rule->high.value = val1;
263 rule->low.red = rule->high.red = (r1 + r2) / 2;
264 rule->low.grn = rule->high.grn = (g1 + g2) / 2;
265 rule->low.blu = rule->high.blu = (b1 + b2) / 2;
266 }
267 else if (val1 < val2) {
268 rule->low.value = val1;
269 rule->low.red = r1;
270 rule->low.grn = g1;
271 rule->low.blu = b1;
272
273 rule->high.value = val2;
274 rule->high.red = r2;
275 rule->high.grn = g2;
276 rule->high.blu = b2;
277 }
278 else {
279 rule->low.value = val2;
280 rule->low.red = r2;
281 rule->low.grn = g2;
282 rule->low.blu = b2;
283
284 rule->high.value = val1;
285 rule->high.red = r1;
286 rule->high.grn = g1;
287 rule->high.blu = b1;
288 }
289
290 /* keep track of the overall min and max, excluding null */
291 if (Rast_is_d_null_value(&(rule->low.value))) {
292 G_free(rule);
293 return;
294 }
295 if (Rast_is_d_null_value(&(rule->high.value))) {
296 G_free(rule);
297 return;
298 }
299 min = rule->low.value;
300 max = rule->high.value;
301 if (min <= max) {
302 if (cp->min > cp->max) {
303 cp->min = min;
304 cp->max = max;
305 }
306 else {
307 if (cp->min > min)
308 cp->min = min;
309 if (cp->max < max)
310 cp->max = max;
311 }
312 }
313 if (*cmin > *cmax) {
314 *cmin = cp->min;
315 *cmax = cp->max;
316 }
317 else {
318 if (*cmin > cp->min)
319 *cmin = cp->min;
320 if (*cmax < cp->max)
321 *cmax = cp->max;
322 }
323
324 /* If version is old style (i.e., pre 4.0),
325 * interpolate this rule from min to max
326 * and insert each cat into the lookup table.
327 * Then free the rule.
328 * Otherwise, free the lookup table, if active.
329 * G_organize_colors() will regenerate it
330 * Link this rule into the list of rules
331 */
332
333 if (version < 0) {
334 for (cat = (CELL)min; cat <= (CELL)max; cat++) {
335 Rast__interpolate_color_rule((DCELL)cat, &red, &grn, &blu, rule);
336 Rast__insert_color_into_lookup(cat, (int)red, (int)grn, (int)blu,
337 cp);
338 }
339 G_free(rule);
340 }
341 else {
342 if (cp->rules)
343 cp->rules->prev = rule;
344 rule->next = cp->rules;
345 cp->rules = rule;
346
347 /* prune the rules:
348 * remove all rules that are contained by this rule
349 */
350 min = rule->low.value; /* mod 4.1 */
351 max = rule->high.value; /* mod 4.1 */
352 cp->n_rules++;
353 for (rule = rule->next; rule; rule = next) {
354 next = rule->next; /* has to be done here, not in for stmt */
355 if (min <= rule->low.value && max >= rule->high.value) {
356 if ((rule->prev->next = next)) /* remove from the list */
357 next->prev = rule->prev;
358 G_free(rule);
359 cp->n_rules--;
360 }
361 }
362
363 /* free lookup array, if allocated */
366 }
367}
#define NULL
Definition ccmath.h:32
int Rast_add_modular_c_color_rule(const CELL *val1, int r1, int g1, int b1, const CELL *val2, int r2, int g2, int b2, struct Colors *colors)
Add modular integer color rule (CELL version)
Definition color_rule.c:182
void Rast_add_d_color_rule(const DCELL *val1, int r1, int g1, int b1, const DCELL *val2, int r2, int g2, int b2, struct Colors *colors)
Adds the floating-point color rule (DCELL version)
Definition color_rule.c:36
void Rast_add_c_color_rule(const CELL *cat1, int r1, int g1, int b1, const CELL *cat2, int r2, int g2, int b2, struct Colors *colors)
Adds the integer color rule (CELL version)
Definition color_rule.c:74
int Rast_add_modular_color_rule(const void *val1, int r1, int g1, int b1, const void *val2, int r2, int g2, int b2, struct Colors *colors, RASTER_MAP_TYPE data_type)
Add modular color rule.
Definition color_rule.c:216
void Rast_add_f_color_rule(const FCELL *cat1, int r1, int g1, int b1, const FCELL *cat2, int r2, int g2, int b2, struct Colors *colors)
Adds the floating-point color rule (FCELL version)
Definition color_rule.c:55
#define LIMIT(x)
Definition color_rule.c:15
int Rast_add_modular_d_color_rule(const DCELL *val1, int r1, int g1, int b1, const DCELL *val2, int r2, int g2, int b2, struct Colors *colors)
Add modular floating-point color rule (DCELL version)
Definition color_rule.c:122
void Rast_add_color_rule(const void *val1, int r1, int g1, int b1, const void *val2, int r2, int g2, int b2, struct Colors *colors, RASTER_MAP_TYPE data_type)
Adds the color rule.
Definition color_rule.c:102
int Rast_add_modular_f_color_rule(const FCELL *val1, int r1, int g1, int b1, const FCELL *val2, int r2, int g2, int b2, struct Colors *colors)
Add modular floating-point color rule (FCELL version)
Definition color_rule.c:152
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_malloc(n)
Definition defs/gis.h:136
int Rast__insert_color_into_lookup(CELL, int, int, int, struct _Color_Info_ *)
Definition color_insrt.c:18
void Rast__color_free_fp_lookup(struct _Color_Info_ *)
Free color rules structure.
Definition color_free.c:77
#define Rast_is_d_null_value(dcellVal)
void Rast__color_free_lookup(struct _Color_Info_ *)
Free color rules structure.
Definition color_free.c:59
void Rast__interpolate_color_rule(DCELL, unsigned char *, unsigned char *, unsigned char *, const struct _Color_Rule_ *)
Interpolate color rules.
Definition color_look.c:419
DCELL Rast_get_d_value(const void *, RASTER_MAP_TYPE)
Retrieves the value of given type from pointer p (DCELL)
#define min(x, y)
Definition draw2.c:29
#define max(x, y)
Definition draw2.c:30
float FCELL
Definition gis.h:633
double DCELL
Definition gis.h:632
int CELL
Definition gis.h:631
#define FCELL_TYPE
Definition raster.h:12
#define DCELL_TYPE
Definition raster.h:13
#define CELL_TYPE
Definition raster.h:11
int RASTER_MAP_TYPE
Definition raster.h:25
Definition gis.h:689
DCELL cmax
Definition gis.h:705
struct _Color_Info_ fixed
Definition gis.h:702
struct _Color_Info_ modular
Definition gis.h:703
int version
Definition gis.h:690
DCELL cmin
Definition gis.h:704
struct _Color_Rule_ * prev
Definition gis.h:662
struct _Color_Rule_ * next
Definition gis.h:661
struct _Color_Value_ low high
Definition gis.h:660