GRASS 8 Programmer's Manual 8.6.0dev(2026)-f6f2c534ea
Loading...
Searching...
No Matches
color_look.c
Go to the documentation of this file.
1/*!
2 * \file lib/raster/color_look.c
3 *
4 * \brief Raster Library - Lookup array of colors
5 *
6 * (C) 1999-2009 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 <math.h>
16
17#include <grass/gis.h>
18#include <grass/raster.h>
19
20/*!
21 * \brief Lookup an array of colors
22 *
23 * Extracts colors for an array of <i>cell</i> values. The colors
24 * for the <i>n</i> values in the <i>cell</i> array are stored in
25 * the <i>red, green</i>, and <i>blue</i> arrays. The values in the
26 * <i>set</i> array will indicate if the corresponding <i>cell</i>
27 * value has a color or not (1 means it does, 0 means it does not).
28 *
29 * The programmer must allocate the <i>red, green, blue</i>, and
30 * <b>set</b> arrays to be at least dimension <i>n</i>.
31 *
32 * <b>Note:</b> The <i>red, green</i>, and <i>blue</i> intensities
33 * will be in the range 0 - 255.
34 *
35 * Modified to return a color for NULL-values.
36 *
37 * \param cell raster cell value
38 * \param[out] red red value
39 * \param[out] grn green value
40 * \param[out] blu blue value
41 * \param set array which indicates if color is set or not
42 * \param n number of values
43 * \param colors pointer to Colors structure which holds color info
44 */
45void Rast_lookup_c_colors(const CELL *cell, unsigned char *red,
46 unsigned char *grn, unsigned char *blu,
47 unsigned char *set, int n, struct Colors *colors)
48{
50 colors); /* make sure the lookup tables are in place */
51
52 G_zero((char *)set, n * sizeof(unsigned char));
53
54 /* first lookup the fixed colors */
55 Rast__lookup_colors((void *)cell, red, grn, blu, set, n, colors, 0, 0,
56 CELL_TYPE);
57
58 /* now lookup unset colors using the modular rules */
59 Rast__lookup_colors((void *)cell, red, grn, blu, set, n, colors, 1, 0,
60 CELL_TYPE);
61}
62
63/*!
64 * \brief Lookup an array of colors
65 *
66 * - If the <em>map_type</em> is CELL_TYPE, calls Rast_lookup_colors()
67 * - If the <em>map_type</em> is FCELL_TYPE, calls Rast_lookup_f_colors()
68 * - If the <em>map_type</em> is DCELL_TYPE, calls Rast_lookup_d_colors()
69 *
70 * \param raster raster cell value
71 * \param[out] red red value
72 * \param[out] grn green value
73 * \param[out] blu blue value
74 * \param set array which indicates if color is set or not
75 * \param n number of values
76 * \param colors pointer to Colors structure which holds color info
77 * \param map_type raster type (CELL, FCELL, DCELL)
78 */
79void Rast_lookup_colors(const void *raster, unsigned char *red,
80 unsigned char *grn, unsigned char *blu,
81 unsigned char *set, int n, struct Colors *colors,
82 RASTER_MAP_TYPE map_type)
83{
85 colors); /* make sure the lookup tables are in place */
86 /* in case of float color rules, fp_lookup table is created */
87
88 G_zero((char *)set, n * sizeof(unsigned char));
89
90 /* first lookup the fixed colors */
91 Rast__lookup_colors(raster, red, grn, blu, set, n, colors, 0, 0, map_type);
92
93 /* now lookup unset colors using the modular rules */
94 Rast__lookup_colors(raster, red, grn, blu, set, n, colors, 1, 0, map_type);
95}
96
97/*!
98 * \brief Lookup an array of colors (FCELL)
99 *
100 * Converts the <em>n</em> floating-point values in the <em>fcell</em>
101 * array to their <em>r,g,b</em> color components. Embedded
102 * NULL-values are handled properly as well.
103 *
104 * \param fcell raster cell value
105 * \param[out] red red value
106 * \param[out] grn green value
107 * \param[out] blu blue value
108 * \param set array which indicates if color is set or not
109 * \param n number of values
110 * \param colors pointer to Colors structure which holds color info
111 */
112void Rast_lookup_f_colors(const FCELL *fcell, unsigned char *red,
113 unsigned char *grn, unsigned char *blu,
114 unsigned char *set, int n, struct Colors *colors)
115{
117 colors); /* make sure the lookup tables are in place */
118 /* in case of float color rules, fp_lookup table is created */
119
120 G_zero((char *)set, n * sizeof(unsigned char));
121
122 /* first lookup the fixed colors */
123 Rast__lookup_colors((void *)fcell, red, grn, blu, set, n, colors, 0, 0,
124 FCELL_TYPE);
125
126 /* now lookup unset colors using the modular rules */
127 Rast__lookup_colors((void *)fcell, red, grn, blu, set, n, colors, 1, 0,
128 FCELL_TYPE);
129}
130
131/*!
132 * \brief Lookup an array of colors (DCELL)
133 *
134 * Converts the <em>n</em> double-precision values in the
135 * <em>dcell</em> array to their <em>r,g,b</em> color
136 * components. Embedded NULL-values are handled properly as well.
137 *
138 * \param dcell raster cell value
139 * \param[out] red red value
140 * \param[out] grn green value
141 * \param[out] blu blue value
142 * \param set array which indicates if color is set or not
143 * \param n number of values
144 * \param colors pointer to Colors structure which holds color info
145 */
146void Rast_lookup_d_colors(const DCELL *dcell, unsigned char *red,
147 unsigned char *grn, unsigned char *blu,
148 unsigned char *set, int n, struct Colors *colors)
149{
151 colors); /* make sure the lookup tables are in place */
152 /* in case of float color rules, fp_lookup table is created */
153
154 G_zero((char *)set, n * sizeof(unsigned char));
155
156 /* first lookup the fixed colors */
157 Rast__lookup_colors((void *)dcell, red, grn, blu, set, n, colors, 0, 0,
158 DCELL_TYPE);
159
160 /* now lookup unset colors using the modular rules */
161 Rast__lookup_colors((void *)dcell, red, grn, blu, set, n, colors, 1, 0,
162 DCELL_TYPE);
163}
164
165static int less_or_equal(double x, double y)
166{
167 if (x <= y)
168 return 1;
169 else
170 return 0;
171}
172
173static int less(double x, double y)
174{
175 if (x < y)
176 return 1;
177 else
178 return 0;
179}
180
181/*!
182 * \brief Lookup an array of colors
183 *
184 * \param raster raster cell value
185 * \param[out] red red value
186 * \param[out] grn green value
187 * \param[out] blu blue value
188 * \param set array which indicates if color is set or not
189 * \param n number of values
190 * \param colors pointer to Colors structure which holds color info
191 * \param mod
192 * \param rules_only
193 * \param data_type raster type (CELL, FCELL, DCELL)
194 */
195void Rast__lookup_colors(const void *raster, unsigned char *red,
196 unsigned char *grn, unsigned char *blu,
197 unsigned char *set, int n, struct Colors *colors,
198 int mod, int rules_only, RASTER_MAP_TYPE data_type)
199{
200 struct _Color_Info_ *cp;
201 struct _Color_Rule_ *rule;
202 DCELL dmin, dmax, val, dmod = 0L, shift;
203 CELL cat, min, max;
204 const void *ptr, *last_ptr = NULL;
205 int invert;
206 int found, r, g, b;
207 int cell_type;
208 int lookup, max_ind, min_ind, try;
209 int (*lower)(double, double);
210 size_t size = Rast_cell_size(data_type);
211
212 if (mod)
213 cp = &colors->modular;
214 else
215 cp = &colors->fixed;
216
217 /* rules_only will be true only when called by Rast__organize_colors()
218 * when building the integer lookup talbes from the rules,
219 * so do not shift, invert, use lookup table or modulate cats.
220 * these operations will happen when lookup is called by user code
221 */
222 /* we want min, max for cp, not min, max overall */
223 dmin = cp->min;
224 dmax = cp->max;
225 min = (CELL)dmin;
226 max = (CELL)dmax;
227
228 cell_type = (data_type == CELL_TYPE);
229
230 if (rules_only) {
231 shift = invert = lookup = mod = 0;
232 }
233 else {
234 if (mod) {
235 dmod = dmax - dmin;
236 /* for integers color table we make a gap of 1 in order
237 to make the same colors as before */
238 if (cell_type)
239 dmod += 1;
240 }
241
242 shift = colors->shift;
243 invert = colors->invert;
244 lookup = cp->lookup.active;
245 }
246
247 ptr = raster;
248
249 for (; n-- > 0; ptr = G_incr_void_ptr(ptr, size), red++, grn++, blu++,
250 *set++ = found) {
251 /* if the cell is the same as last one, use the prev color values */
252 if (ptr != raster && Rast_raster_cmp(ptr, last_ptr, data_type) == 0) {
253 *red = *(red - 1);
254 *blu = *(blu - 1);
255 *grn = *(grn - 1);
256 found = *(set - 1);
257 last_ptr = ptr;
258 continue;
259 }
260 val = Rast_get_d_value(ptr, data_type);
261 /* DEBUG fprintf (stderr, "val: %.4lf\n", val); */
262 last_ptr = ptr;
263
264 if (*set) {
265 found = 1;
266 continue;
267 }
268
269 if (Rast_is_null_value(ptr, data_type)) {
270 /* returns integers, not unsigned chars */
271 Rast_get_null_value_color(&r, &g, &b, colors);
272 *red = r;
273 *grn = g;
274 *blu = b;
275 found = 1;
276 continue;
277 }
278
279 if (shift && val >= dmin && val <= dmax) {
280 val += shift;
281 while (val < dmin)
282 val += dmax - dmin + 1;
283 while (val > dmax)
284 val -= dmax - dmin + 1;
285 }
286
287 /* invert non-null data around midpoint of range [min:max] */
288 if (invert)
289 val = dmin + dmax - val;
290
291 if (mod) {
292 if (dmod > 0) {
293 val -= dmin;
294 while (val < 0)
295 val += dmod;
296 val = val - dmod * floor(val / dmod);
297 val += dmin;
298 }
299 else
300 val = dmin;
301 }
302
303 cat = (CELL)val;
304
305 found = 0;
306
307 /* for non-null integers try to look them up in lookup table */
308 /* note: lookup table exists only for integer maps, and we also must
309 check if val is really integer */
310
311 if (lookup && ((double)cat - val == 0.)) {
312 if (cat >= min && cat <= max) {
313 cat -= min;
314 if (cp->lookup.set[cat]) {
315 *red = cp->lookup.red[cat];
316 *grn = cp->lookup.grn[cat];
317 *blu = cp->lookup.blu[cat];
318 found = 1;
319 /*DEBUG
320 fprintf (stderr, "lookup %d %.2lf %d %d %d\n\n", cat,
321 val, *red, *grn, *blu);
322 */
323 }
324 }
325 }
326
327 if (found)
328 continue;
329
330 /* if floating point lookup table is active, look up in there */
331 if (cp->fp_lookup.active) {
332 try = (cp->fp_lookup.nalloc - 1) / 2;
333 min_ind = 0;
334 max_ind = cp->fp_lookup.nalloc - 2;
335 while (1) {
336 /* when the rule for the interval is NULL, we exclude the end
337 points. when it exists, we include the end-points */
338 if (cp->fp_lookup.rules[try])
339 lower = less;
340 else
341 lower = less_or_equal;
342 /* DEBUG
343 fprintf (stderr, "%d %d %d %lf %lf %lf\n", min_ind, try,
344 max_ind, cp->fp_lookup.vals[try-1], val,
345 cp->fp_lookup.vals[try]);
346 */
347
348 if (lower(cp->fp_lookup.vals[try + 1],
349 val)) { /* recurse to the second half */
350 min_ind = try + 1;
351 /* must be still < nalloc-1, since number is within the
352 * range */
353 try = (max_ind + min_ind) / 2;
354 if (min_ind > max_ind) {
355 rule = NULL;
356 break;
357 }
358 continue;
359 }
360 if (lower(val, cp->fp_lookup.vals[try])) { /* recurse to the
361 second half */
362 max_ind = try - 1;
363 /* must be still >= 0, since number is within the range */
364 try = (max_ind + min_ind) / 2;
365 if (max_ind < min_ind) {
366 rule = NULL;
367 break;
368 }
369 continue;
370 }
371 rule = cp->fp_lookup.rules[try];
372 break;
373 }
374 }
375 else {
376 /* find the [low:high] rule that applies */
377 for (rule = cp->rules; rule; rule = rule->next) {
378 /* DEBUG
379 fprintf (stderr, "%.2lf %.2lf %.2lf\n",
380 val, rule->low.value, rule->high.value);
381 */
382 if (rule->low.value <= val && val <= rule->high.value)
383 break;
384 }
385 }
386
387 /* if found, perform linear interpolation from low to high.
388 * else set colors to colors->undef or white if undef not set
389 */
390
391 if (rule) {
392 Rast__interpolate_color_rule(val, red, grn, blu, rule);
393 found = 1;
394 }
395 if (!found) {
396 /* otherwise use default color */
397 Rast_get_default_color(&r, &g, &b, colors);
398 *red = r;
399 *grn = g;
400 *blu = b;
401 }
402 /* DEBUG
403 if (rule)
404 fprintf (stderr, "%.2lf %d %d %d %.2lf %d %d %d \n",
405 rule->low.value , (int)rule->low.red, (int)rule->low.grn,
406 (int)rule->low.blu, rule->high.value, (int)rule->high.red,
407 (int)rule->high.grn, (int)rule->high.blu); fprintf (stderr, "rule
408 found %d %.2lf %d %d %d\n\n", cat, val, *red, *grn, *blu);
409 */
410 }
411}
412
413/*!
414 \brief Interpolate color rules
415
416 \param val raster cell value
417 \param[out] red red value
418 \param[out] grn green value
419 \param[out] blu blue value
420 \param rule pointer to _Color_Rule which holds color rules info
421 */
422void Rast__interpolate_color_rule(DCELL val, unsigned char *red,
423 unsigned char *grn, unsigned char *blu,
424 const struct _Color_Rule_ *rule)
425{
426 DCELL delta;
427
428 if ((delta = rule->high.value - rule->low.value)) {
429 val -= rule->low.value;
430
431 *red = (int)(val * (double)((int)rule->high.red - (int)rule->low.red) /
432 delta) +
433 (int)rule->low.red;
434 *grn = (int)(val * (double)((int)rule->high.grn - (int)rule->low.grn) /
435 delta) +
436 (int)rule->low.grn;
437 *blu = (int)(val * (double)((int)rule->high.blu - (int)rule->low.blu) /
438 delta) +
439 (int)rule->low.blu;
440 }
441 else {
442 *red = rule->low.red;
443 *grn = rule->low.grn;
444 *blu = rule->low.blu;
445 }
446}
#define NULL
Definition ccmath.h:32
void Rast__lookup_colors(const void *raster, unsigned char *red, unsigned char *grn, unsigned char *blu, unsigned char *set, int n, struct Colors *colors, int mod, int rules_only, RASTER_MAP_TYPE data_type)
Lookup an array of colors.
Definition color_look.c:195
void Rast_lookup_f_colors(const FCELL *fcell, unsigned char *red, unsigned char *grn, unsigned char *blu, unsigned char *set, int n, struct Colors *colors)
Lookup an array of colors (FCELL)
Definition color_look.c:112
void Rast_lookup_d_colors(const DCELL *dcell, unsigned char *red, unsigned char *grn, unsigned char *blu, unsigned char *set, int n, struct Colors *colors)
Lookup an array of colors (DCELL)
Definition color_look.c:146
void Rast_lookup_colors(const void *raster, unsigned char *red, unsigned char *grn, unsigned char *blu, unsigned char *set, int n, struct Colors *colors, RASTER_MAP_TYPE map_type)
Lookup an array of colors.
Definition color_look.c:79
void Rast_lookup_c_colors(const CELL *cell, unsigned char *red, unsigned char *grn, unsigned char *blu, unsigned char *set, int n, struct Colors *colors)
Lookup an array of colors.
Definition color_look.c:45
void Rast__interpolate_color_rule(DCELL val, unsigned char *red, unsigned char *grn, unsigned char *blu, const struct _Color_Rule_ *rule)
Interpolate color rules.
Definition color_look.c:422
void G_zero(void *, int)
Zero out a buffer, buf, of length i.
Definition gis/zero.c:23
#define G_incr_void_ptr(ptr, size)
Definition defs/gis.h:81
int Rast_is_null_value(const void *, RASTER_MAP_TYPE)
To check if a raster value is set to NULL.
Definition null_val.c:176
size_t Rast_cell_size(RASTER_MAP_TYPE)
Returns size of a raster cell in bytes.
Definition alloc_cell.c:37
void Rast__organize_colors(struct Colors *)
Definition color_org.c:12
void Rast_get_null_value_color(int *, int *, int *, const struct Colors *)
Gets color for null value.
Definition color_get.c:126
int Rast_raster_cmp(const void *, const void *, RASTER_MAP_TYPE)
Compares raster values.
DCELL Rast_get_d_value(const void *, RASTER_MAP_TYPE)
Retrieves the value of given type from pointer p (DCELL)
void Rast_get_default_color(int *, int *, int *, const struct Colors *)
Gets default color.
Definition color_get.c:154
#define min(x, y)
Definition draw2.c:29
#define max(x, y)
Definition draw2.c:30
float FCELL
Definition gis.h:636
double DCELL
Definition gis.h:635
int CELL
Definition gis.h:634
float g
Definition named_colr.c:7
double b
Definition r_raster.c:39
double r
Definition r_raster.c:39
#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:692
struct _Color_Info_ fixed
Definition gis.h:705
struct _Color_Info_ modular
Definition gis.h:706
int invert
Definition gis.h:695
DCELL shift
Definition gis.h:694
struct _Color_Rule_ * next
Definition gis.h:664
struct _Color_Value_ low high
Definition gis.h:663