GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-c23b602b1d
json_color_out.c
Go to the documentation of this file.
1 /*!
2  * \file lib/raster/json_color_out.c
3  *
4  * \brief Raster Library - Print color table in json format
5  *
6  * (C) 2010-2024 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 Nishant Bansal
13  */
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include <grass/gis.h>
20 #include <grass/colors.h>
21 #include <grass/gjson.h>
22 #include <grass/glocale.h>
23 #include <grass/raster.h>
24 
25 /*!
26  \brief Closes the file if it is not stdout.
27 
28  \param fp file where to print color table rules
29  */
30 static void close_file(FILE *fp)
31 {
32  if (fp != stdout)
33  fclose(fp);
34 }
35 
36 /*!
37  \brief Writes a JSON rule for a specific color entry.
38 
39  \param val pointer to the DCELL value
40  \param min,max minimum and maximum value for percentage output (used only
41  when \p perc is non-zero)
42  \param r red component of RGB color
43  \param g green component of RGB color
44  \param b blue component of RGB color
45  \param root_array pointer to the JSON array
46  \param perc TRUE for percentage output
47  \param clr_frmt color format to be used (RBG, HEX, HSV, TRIPLET).
48  \param fp file where to print color table rules
49  \param root_value pointer to json value
50  */
51 static void write_json_rule(DCELL *val, DCELL *min, DCELL *max, int r, int g,
52  int b, JSON_Array *root_array, int perc,
53  ColorFormat clr_frmt, FILE *fp,
54  JSON_Value *root_value)
55 {
56  static DCELL v0;
57  static int r0 = -1, g0 = -1, b0 = -1;
58 
59  // Skip writing if the current color is the same as the last one
60  if (v0 == *val && r0 == r && g0 == g && b0 == b)
61  return;
62  // Update last processed values
63  v0 = *val, r0 = r, g0 = g, b0 = b;
64 
65  JSON_Value *color_value = G_json_value_init_object();
66  if (color_value == NULL) {
67  G_json_value_free(root_value);
68  close_file(fp);
69  G_fatal_error(_("Failed to initialize JSON object. Out of memory?"));
70  }
71  JSON_Object *color_object = G_json_object(color_value);
72 
73  // Set the value as a percentage if requested, otherwise set it as-is
74  if (perc)
75  G_json_object_set_number(color_object, "value",
76  100 * (*val - *min) / (*max - *min));
77  else
78  G_json_object_set_number(color_object, "value", *val);
79 
80  char color_str[COLOR_STRING_LENGTH];
81  G_color_to_str(r, g, b, clr_frmt, color_str);
82  G_json_object_set_string(color_object, "color", color_str);
83 
84  G_json_array_append_value(root_array, color_value);
85 }
86 
87 /*!
88  \brief Print color table in JSON format
89 
90  \param colors pointer to Colors structure
91  \param min,max minimum and maximum value for percentage output (used only
92  when \p perc is non-zero)
93  \param fp file where to print color table rules
94  \param perc TRUE for percentage output
95  \param clr_frmt color format to be used (RBG, HEX, HSV, TRIPLET).
96  */
98  FILE *fp, int perc, ColorFormat clr_frmt)
99 {
100  JSON_Value *root_value = G_json_value_init_array();
101  if (root_value == NULL) {
102  close_file(fp);
103  G_fatal_error(_("Failed to initialize JSON array. Out of memory?"));
104  }
105  JSON_Array *root_array = G_json_array(root_value);
106 
107  char color_str[COLOR_STRING_LENGTH];
108 
109  if (colors->version < 0) {
110  /* 3.0 format */
111  CELL lo, hi;
112 
113  // Retrieve the integer color range
114  Rast_get_c_color_range(&lo, &hi, colors);
115 
116  for (int i = lo; i <= hi; i++) {
117  unsigned char r, g, b, set;
118  DCELL val = (DCELL)i;
119 
120  // Look up the color for the current value and write JSON rule
121  Rast_lookup_c_colors(&i, &r, &g, &b, &set, 1, colors);
122  write_json_rule(&val, &min, &max, r, g, b, root_array, perc,
123  clr_frmt, fp, root_value);
124  }
125  }
126  else {
127  // Get the count of floating-point color rules
128  int count = Rast_colors_count(colors);
129 
130  for (int i = 0; i < count; i++) {
131  DCELL val1, val2;
132  unsigned char r1, g1, b1, r2, g2, b2;
133 
134  // Retrieve the color rule values and their respective RGB colors
135  Rast_get_fp_color_rule(&val1, &r1, &g1, &b1, &val2, &r2, &g2, &b2,
136  colors, count - 1 - i);
137 
138  // write JSON rule
139  write_json_rule(&val1, &min, &max, r1, g1, b1, root_array, perc,
140  clr_frmt, fp, root_value);
141  write_json_rule(&val2, &min, &max, r2, g2, b2, root_array, perc,
142  clr_frmt, fp, root_value);
143  }
144  }
145 
146  // Add special color entries for "null" and "default" values
147  {
148  int r, g, b;
149 
150  // Get RGB color for null values and create JSON entry
151  Rast_get_null_value_color(&r, &g, &b, colors);
152  JSON_Value *nv_value = G_json_value_init_object();
153  if (nv_value == NULL) {
154  G_json_value_free(root_value);
155  close_file(fp);
157  _("Failed to initialize JSON object. Out of memory?"));
158  }
159  JSON_Object *nv_object = G_json_object(nv_value);
160  G_json_object_set_string(nv_object, "value", "nv");
161  G_color_to_str(r, g, b, clr_frmt, color_str);
162  G_json_object_set_string(nv_object, "color", color_str);
163  G_json_array_append_value(root_array, nv_value);
164 
165  // Get RGB color for default values and create JSON entry
166  Rast_get_default_color(&r, &g, &b, colors);
167  JSON_Value *default_value = G_json_value_init_object();
168  if (default_value == NULL) {
169  G_json_value_free(root_value);
170  close_file(fp);
172  _("Failed to initialize JSON object. Out of memory?"));
173  }
174  JSON_Object *default_object = G_json_object(default_value);
175  G_json_object_set_string(default_object, "value", "default");
176  G_color_to_str(r, g, b, clr_frmt, color_str);
177  G_json_object_set_string(default_object, "color", color_str);
178  G_json_array_append_value(root_array, default_value);
179  }
180 
181  // Serialize JSON array to a string and print to the file
183  if (!json_string) {
184  G_json_value_free(root_value);
185  close_file(fp);
186  G_fatal_error(_("Failed to serialize JSON to pretty format."));
187  }
188 
189  fputs(json_string, fp);
190 
192  G_json_value_free(root_value);
193 
194  close_file(fp);
195 }
#define NULL
Definition: ccmath.h:32
ColorFormat
Color format identifiers (enum)
Definition: colors.h:55
#define COLOR_STRING_LENGTH
Definition: colors.h:28
void G_color_to_str(int, int, int, ColorFormat, char *)
Parse red,green,blue and set color string.
Definition: color_str.c:210
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int Rast_colors_count(const struct Colors *)
Get both modular and fixed rules count.
void Rast_get_c_color_range(CELL *, CELL *, const struct Colors *)
Get color range values (CELL)
Definition: color_range.c:64
int Rast_get_fp_color_rule(DCELL *, unsigned char *, unsigned char *, unsigned char *, DCELL *, unsigned char *, unsigned char *, unsigned char *, const struct Colors *, int)
Get color rule from both modular and fixed rules.
void Rast_get_null_value_color(int *, int *, int *, const struct Colors *)
Gets color for null value.
Definition: color_get.c:126
void Rast_lookup_c_colors(const CELL *, unsigned char *, unsigned char *, unsigned char *, unsigned char *, int, struct Colors *)
Lookup an array of colors.
Definition: color_look.c:45
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
double DCELL
Definition: gis.h:635
int CELL
Definition: gis.h:634
char * G_json_serialize_to_string_pretty(const JSON_Value *value)
Definition: gjson.c:143
void G_json_value_free(JSON_Value *value)
Definition: gjson.c:152
void G_json_free_serialized_string(char *string)
Definition: gjson.c:148
JSON_Status G_json_object_set_number(JSON_Object *object, const char *name, double number)
Definition: gjson.c:83
JSON_Array * G_json_array(const JSON_Value *value)
Definition: gjson.c:97
JSON_Value * G_json_value_init_object(void)
Definition: gjson.c:24
JSON_Value * G_json_value_init_array(void)
Definition: gjson.c:29
JSON_Status G_json_object_set_string(JSON_Object *object, const char *name, const char *string)
Definition: gjson.c:78
JSON_Status G_json_array_append_value(JSON_Array *array, JSON_Value *value)
Definition: gjson.c:118
JSON_Object * G_json_object(const JSON_Value *value)
Definition: gjson.c:39
#define _(str)
Definition: glocale.h:10
GRASS_INTERPFL_EXPORT int count
void Rast_print_json_colors(struct Colors *colors, DCELL min, DCELL max, FILE *fp, int perc, ColorFormat clr_frmt)
Print color table in JSON format.
float g
Definition: named_colr.c:7
const char * json_string(const JSON_Value *value)
Definition: parson.c:2805
struct json_array_t JSON_Array
Definition: parson.h:46
struct json_value_t JSON_Value
Definition: parson.h:47
struct json_object_t JSON_Object
Definition: parson.h:45
double b
Definition: r_raster.c:39
double r
Definition: r_raster.c:39
Definition: gis.h:692
int version
Definition: gis.h:693