GRASS 8 Programmer's Manual  8.5.0dev(2025)-c070206eb1
color_xform.c
Go to the documentation of this file.
1 /*!
2  * \file lib/raster/color_xform.c
3  *
4  * \brief Raster Library - Colors management
5  *
6  * (C) 2001-2021 by the GRASS Development Team
7  *
8  * This program is free software under the GNU General Public License
9  * (>=v2). Read the file COPYING that comes with GRASS for details.
10  *
11  * \author Original author CERL
12  */
13 
14 #include <math.h>
15 
16 #include <grass/gis.h>
17 #include <grass/raster.h>
18 
19 /*!
20  * \brief Make histogram-stretched version of existing color table
21  *
22  * Generates a histogram contrast-stretched color table that goes from
23  * the histogram information in the Cell_stats structure <i>statf</i>.
24  * (See \ref Raster_Histograms).
25  *
26  * \param[out] dst struct to hold new colors
27  * \param src struct containing original colors
28  * \param statf cell stats info
29  */
30 void Rast_histogram_eq_colors(struct Colors *dst, struct Colors *src,
31  struct Cell_stats *statf)
32 {
33  DCELL min, max;
34  int red, grn, blu;
35  int red2, grn2, blu2;
36  long count, total, sum;
37  CELL cat, prev;
38  int first;
39 
40  Rast_init_colors(dst);
41 
43 
44  Rast_get_default_color(&red, &grn, &blu, src);
45  Rast_set_default_color(red, grn, blu, dst);
46 
47  Rast_get_null_value_color(&red, &grn, &blu, src);
48  Rast_set_null_value_color(red, grn, blu, dst);
49 
50  total = 0;
51 
53  while (Rast_next_cell_stat(&cat, &count, statf))
54  if (count > 0)
55  total += count;
56 
57  if (total <= 0)
58  return;
59 
60  sum = 0;
61  prev = 0;
62  first = 1;
63 
65  while (Rast_next_cell_stat(&cat, &count, statf)) {
66  DCELL x;
67 
68  if (count <= 0)
69  continue;
70 
71  x = min + (max - min) * (sum + count / 2.0) / total;
72  Rast_get_d_color(&x, &red2, &grn2, &blu2, src);
73 
74  sum += count;
75 
76  if (!first && red2 == red && blu2 == blu && grn2 == grn)
77  continue;
78 
79  if (!first)
80  Rast_add_c_color_rule(&prev, red, grn, blu, &cat, red2, grn2, blu2,
81  dst);
82 
83  first = 0;
84 
85  prev = cat;
86  red = red2;
87  grn = grn2;
88  blu = blu2;
89  }
90 
91  if (!first && cat > prev)
92  Rast_add_c_color_rule(&prev, red, grn, blu, &cat, red2, grn2, blu2,
93  dst);
94 }
95 
96 /*!
97  * \brief Make histogram-stretched version of existing color table (FP version)
98  *
99  * Generates a histogram contrast-stretched color table that goes from
100  * the histogram information in the FP_stats structure <b>statf.</b>
101  * (See \ref Raster_Histograms).
102  *
103  * \param[out] dst struct to hold new colors
104  * \param src struct containing original colors
105  * \param statf cell stats info
106  */
107 void Rast_histogram_eq_fp_colors(struct Colors *dst, struct Colors *src,
108  struct FP_stats *statf)
109 {
110  DCELL min, max;
111  int red, grn, blu;
112  int red2, grn2, blu2;
113  unsigned long sum;
114  DCELL val, val2;
115  int first;
116  int i;
117 
118  Rast_init_colors(dst);
119 
120  Rast_get_d_color_range(&min, &max, src);
121 
122  Rast_get_default_color(&red, &grn, &blu, src);
123  Rast_set_default_color(red, grn, blu, dst);
124 
125  Rast_get_null_value_color(&red, &grn, &blu, src);
126  Rast_set_null_value_color(red, grn, blu, dst);
127 
128  if (!statf->total)
129  return;
130 
131  sum = 0;
132  first = 1;
133 
134  for (i = 0; i <= statf->count; i++) {
135  DCELL x;
136 
137  val2 = statf->min + (statf->max - statf->min) * i / statf->count;
138  if (statf->geometric)
139  val2 = exp(val2);
140  if (statf->geom_abs)
141  val2 = exp(val2) - 1;
142  if (statf->flip)
143  val2 = -val2;
144  x = min + (max - min) * sum / statf->total;
145  Rast_get_d_color(&x, &red2, &grn2, &blu2, src);
146 
147  if (i < statf->count)
148  sum += statf->stats[i];
149 
150  if (!first && red2 == red && blu2 == blu && grn2 == grn)
151  continue;
152 
153  if (!first)
154  Rast_add_d_color_rule(&val, red, grn, blu, &val2, red2, grn2, blu2,
155  dst);
156 
157  first = 0;
158 
159  if (i == statf->count)
160  break;
161 
162  val = val2;
163  red = red2;
164  grn = grn2;
165  blu = blu2;
166  }
167 
168  if (!first && val2 > val)
169  Rast_add_d_color_rule(&val, red, grn, blu, &val2, red2, grn2, blu2,
170  dst);
171 }
172 
173 /*!
174  * \brief Make logarithmically-scaled version of an existing color table
175  *
176  * \param[out] dst struct to hold new colors
177  * \param src struct containing original colors
178  * \param samples number of samples
179  */
180 void Rast_log_colors(struct Colors *dst, struct Colors *src, int samples)
181 {
182  DCELL min, max;
183  double delta, lmin, lmax;
184  int red, grn, blu;
185  DCELL prev;
186  int i;
187 
188  Rast_init_colors(dst);
189 
190  Rast_get_d_color_range(&min, &max, src);
191 
192  if (min <= 0.0) {
193  /* shift cell values by 1 - min so that they are in [1, max - min + 1]
194  */
195  delta = 1 - min;
196  lmin = log(min + delta);
197  lmax = log(max + delta);
198  }
199  else {
200  delta = 0;
201  lmin = log(min);
202  lmax = log(max);
203  }
204 
205  Rast_get_default_color(&red, &grn, &blu, src);
206  Rast_set_default_color(red, grn, blu, dst);
207 
208  Rast_get_null_value_color(&red, &grn, &blu, src);
209  Rast_set_null_value_color(red, grn, blu, dst);
210 
211  for (i = 0; i <= samples; i++) {
212  int red2, grn2, blu2;
213  double lx;
214  DCELL x, y;
215 
216  y = min + (max - min) * i / samples;
217  Rast_get_d_color(&y, &red2, &grn2, &blu2, src);
218 
219  if (i == 0)
220  x = min;
221  else if (i == samples)
222  x = max;
223  else {
224  lx = lmin + (lmax - lmin) * i / samples;
225  /* restore cell values approximately */
226  x = exp(lx) - delta;
227  }
228 
229  if (i > 0)
230  Rast_add_d_color_rule(&prev, red, grn, blu, &x, red2, grn2, blu2,
231  dst);
232 
233  prev = x;
234 
235  red = red2;
236  grn = grn2;
237  blu = blu2;
238  }
239 }
240 
241 /*!
242  * \brief Make logarithmically-scaled version of an existing color
243  * table, allowing for signed values
244  *
245  * \param[out] dst struct to hold new colors
246  * \param src struct containing original colors
247  * \param samples number of samples
248  */
249 void Rast_abs_log_colors(struct Colors *dst, struct Colors *src, int samples)
250 {
251  DCELL min, max;
252  double absmin, absmax, amin, amax, delta, lamin, lamax;
253  int red, grn, blu;
254  DCELL prev;
255  int i;
256 
257  Rast_init_colors(dst);
258 
259  Rast_get_d_color_range(&min, &max, src);
260 
261  absmin = fabs(min);
262  absmax = fabs(max);
263  amin = MIN(absmin, absmax);
264  amax = MAX(absmin, absmax);
265 
266  if (min * max <= 0.0) {
267  /* 0 <= abs(cell) <= amax */
268  amin = 0;
269  /* use the same shifting for Rast_log_colors */
270  delta = 1 - amin;
271  lamin = log(amin + delta);
272  lamax = log(amax + delta);
273  }
274  else {
275  /* 0 < amin <= abs(cell) <= amax */
276  delta = 0;
277  lamin = log(amin);
278  lamax = log(amax);
279  }
280 
281  Rast_get_default_color(&red, &grn, &blu, src);
282  Rast_set_default_color(red, grn, blu, dst);
283 
284  Rast_get_null_value_color(&red, &grn, &blu, src);
285  Rast_set_null_value_color(red, grn, blu, dst);
286 
287  for (i = 0; i <= samples; i++) {
288  int red2, grn2, blu2;
289  double lx;
290  DCELL x, y;
291 
292  y = min + (max - min) * i / samples;
293  Rast_get_d_color(&y, &red2, &grn2, &blu2, src);
294 
295  if (i == 0)
296  x = amin;
297  else if (i == samples)
298  x = amax;
299  else {
300  lx = lamin + (lamax - lamin) * i / samples;
301  /* restore cell values approximately */
302  x = exp(lx) - delta;
303  }
304 
305  if (i > 0) {
306  DCELL x0 = prev, x1 = x;
307 
308  Rast_add_d_color_rule(&x0, red, grn, blu, &x1, red2, grn2, blu2,
309  dst);
310  x0 = -x0;
311  x1 = -x1;
312  Rast_add_d_color_rule(&x0, red, grn, blu, &x1, red2, grn2, blu2,
313  dst);
314  }
315 
316  prev = x;
317 
318  red = red2;
319  grn = grn2;
320  blu = blu2;
321  }
322 }
void Rast_abs_log_colors(struct Colors *dst, struct Colors *src, int samples)
Make logarithmically-scaled version of an existing color table, allowing for signed values.
Definition: color_xform.c:249
void Rast_histogram_eq_colors(struct Colors *dst, struct Colors *src, struct Cell_stats *statf)
Make histogram-stretched version of existing color table.
Definition: color_xform.c:30
void Rast_log_colors(struct Colors *dst, struct Colors *src, int samples)
Make logarithmically-scaled version of an existing color table.
Definition: color_xform.c:180
void Rast_histogram_eq_fp_colors(struct Colors *dst, struct Colors *src, struct FP_stats *statf)
Make histogram-stretched version of existing color table (FP version)
Definition: color_xform.c:107
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
void Rast_set_null_value_color(int, int, int, struct Colors *)
Set color for NULL-value.
Definition: color_set.c:79
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
int Rast_rewind_cell_stats(struct Cell_stats *)
Reset/rewind cell stats.
Definition: cell_stats.c:248
void Rast_init_colors(struct Colors *)
Initialize color structure.
Definition: color_init.c:25
int Rast_next_cell_stat(CELL *, long *, struct Cell_stats *)
Retrieve sorted cell stats.
Definition: cell_stats.c:312
void Rast_get_d_color_range(DCELL *, DCELL *, const struct Colors *)
Get color range values (DCELL)
Definition: color_range.c:86
void Rast_get_null_value_color(int *, int *, int *, const struct Colors *)
Gets color for null value.
Definition: color_get.c:126
int Rast_get_d_color(const DCELL *, int *, int *, int *, struct Colors *)
Gets color from raster map (DCELL)
Definition: color_get.c:109
void Rast_set_default_color(int, int, int, struct Colors *)
Set default color value.
Definition: color_set.c:99
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
#define MIN(a, b)
Definition: gis.h:153
double DCELL
Definition: gis.h:635
int CELL
Definition: gis.h:634
#define MAX(a, b)
Definition: gis.h:148
int count
Definition: gis.h:692
int geometric
Definition: raster.h:226
int flip
Definition: raster.h:228
DCELL max
Definition: raster.h:230
unsigned long * stats
Definition: raster.h:231
unsigned long total
Definition: raster.h:232
int geom_abs
Definition: raster.h:227
DCELL min
Definition: raster.h:230
int count
Definition: raster.h:229
#define x