GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-f22b1278f8
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 #define COLOR_STRING_LENGTH 30
26 
27 /*!
28  \brief Closes the file if it is not stdout.
29 
30  \param fp file where to print color table rules
31  */
32 static void close_file(FILE *fp)
33 {
34  if (fp != stdout)
35  fclose(fp);
36 }
37 
38 /*!
39  \brief Writes color entry in JSON in specified clr_frmt.
40 
41  \param r red component of RGB color
42  \param g green component of RGB color
43  \param b blue component of RGB color
44  \param clr_frmt color format to be used (RGB, HEX, HSV, TRIPLET).
45  \param color_object pointer to the JSON object
46  */
47 static void set_color(int r, int g, int b, ColorFormat clr_frmt,
48  JSON_Object *color_object)
49 {
50  char color_string[COLOR_STRING_LENGTH];
51  float h, s, v;
52 
53  switch (clr_frmt) {
54  case RGB:
55  snprintf(color_string, sizeof(color_string), "rgb(%d, %d, %d)", r, g,
56  b);
57  G_json_object_set_string(color_object, "color", color_string);
58  break;
59 
60  case HEX:
61  snprintf(color_string, sizeof(color_string), "#%02X%02X%02X", r, g, b);
62  G_json_object_set_string(color_object, "color", color_string);
63  break;
64 
65  case HSV:
66  G_rgb_to_hsv(r, g, b, &h, &s, &v);
67  snprintf(color_string, sizeof(color_string), "hsv(%d, %d, %d)", (int)h,
68  (int)s, (int)v);
69  G_json_object_set_string(color_object, "color", color_string);
70  break;
71 
72  case TRIPLET:
73  snprintf(color_string, sizeof(color_string), "%d:%d:%d", r, g, b);
74  G_json_object_set_string(color_object, "color", color_string);
75  break;
76  }
77 }
78 
79 /*!
80  \brief Writes a JSON rule for a specific color entry.
81 
82  \param val pointer to the DCELL value
83  \param min,max minimum and maximum value for percentage output (used only
84  when \p perc is non-zero)
85  \param r red component of RGB color
86  \param g green component of RGB color
87  \param b blue component of RGB color
88  \param root_array pointer to the JSON array
89  \param perc TRUE for percentage output
90  \param clr_frmt color format to be used (RBG, HEX, HSV, TRIPLET).
91  \param fp file where to print color table rules
92  \param root_value pointer to json value
93  */
94 static void write_json_rule(DCELL *val, DCELL *min, DCELL *max, int r, int g,
95  int b, JSON_Array *root_array, int perc,
96  ColorFormat clr_frmt, FILE *fp,
97  JSON_Value *root_value)
98 {
99  static DCELL v0;
100  static int r0 = -1, g0 = -1, b0 = -1;
101 
102  // Skip writing if the current color is the same as the last one
103  if (v0 == *val && r0 == r && g0 == g && b0 == b)
104  return;
105  // Update last processed values
106  v0 = *val, r0 = r, g0 = g, b0 = b;
107 
108  JSON_Value *color_value = G_json_value_init_object();
109  if (color_value == NULL) {
110  G_json_value_free(root_value);
111  close_file(fp);
112  G_fatal_error(_("Failed to initialize JSON object. Out of memory?"));
113  }
114  JSON_Object *color_object = G_json_object(color_value);
115 
116  // Set the value as a percentage if requested, otherwise set it as-is
117  if (perc)
118  G_json_object_set_number(color_object, "value",
119  100 * (*val - *min) / (*max - *min));
120  else
121  G_json_object_set_number(color_object, "value", *val);
122 
123  set_color(r, g, b, clr_frmt, color_object);
124 
125  G_json_array_append_value(root_array, color_value);
126 }
127 
128 /*!
129  \brief Print color table in JSON format
130 
131  \param colors pointer to Colors structure
132  \param min,max minimum and maximum value for percentage output (used only
133  when \p perc is non-zero)
134  \param fp file where to print color table rules
135  \param perc TRUE for percentage output
136  \param clr_frmt color format to be used (RBG, HEX, HSV, TRIPLET).
137  */
139  FILE *fp, int perc, ColorFormat clr_frmt)
140 {
141  JSON_Value *root_value = G_json_value_init_array();
142  if (root_value == NULL) {
143  close_file(fp);
144  G_fatal_error(_("Failed to initialize JSON array. Out of memory?"));
145  }
146  JSON_Array *root_array = G_json_array(root_value);
147 
148  if (colors->version < 0) {
149  /* 3.0 format */
150  CELL lo, hi;
151 
152  // Retrieve the integer color range
153  Rast_get_c_color_range(&lo, &hi, colors);
154 
155  for (int i = lo; i <= hi; i++) {
156  unsigned char r, g, b, set;
157  DCELL val = (DCELL)i;
158 
159  // Look up the color for the current value and write JSON rule
160  Rast_lookup_c_colors(&i, &r, &g, &b, &set, 1, colors);
161  write_json_rule(&val, &min, &max, r, g, b, root_array, perc,
162  clr_frmt, fp, root_value);
163  }
164  }
165  else {
166  // Get the count of floating-point color rules
167  int count = Rast_colors_count(colors);
168 
169  for (int i = 0; i < count; i++) {
170  DCELL val1, val2;
171  unsigned char r1, g1, b1, r2, g2, b2;
172 
173  // Retrieve the color rule values and their respective RGB colors
174  Rast_get_fp_color_rule(&val1, &r1, &g1, &b1, &val2, &r2, &g2, &b2,
175  colors, count - 1 - i);
176 
177  // write JSON rule
178  write_json_rule(&val1, &min, &max, r1, g1, b1, root_array, perc,
179  clr_frmt, fp, root_value);
180  write_json_rule(&val2, &min, &max, r2, g2, b2, root_array, perc,
181  clr_frmt, fp, root_value);
182  }
183  }
184 
185  // Add special color entries for "null" and "default" values
186  {
187  int r, g, b;
188 
189  // Get RGB color for null values and create JSON entry
190  Rast_get_null_value_color(&r, &g, &b, colors);
191  JSON_Value *nv_value = G_json_value_init_object();
192  if (nv_value == NULL) {
193  G_json_value_free(root_value);
194  close_file(fp);
196  _("Failed to initialize JSON object. Out of memory?"));
197  }
198  JSON_Object *nv_object = G_json_object(nv_value);
199  G_json_object_set_string(nv_object, "value", "nv");
200  set_color(r, g, b, clr_frmt, nv_object);
201  G_json_array_append_value(root_array, nv_value);
202 
203  // Get RGB color for default values and create JSON entry
204  Rast_get_default_color(&r, &g, &b, colors);
205  JSON_Value *default_value = G_json_value_init_object();
206  if (default_value == NULL) {
207  G_json_value_free(root_value);
208  close_file(fp);
210  _("Failed to initialize JSON object. Out of memory?"));
211  }
212  JSON_Object *default_object = G_json_object(default_value);
213  G_json_object_set_string(default_object, "value", "default");
214  set_color(r, g, b, clr_frmt, default_object);
215  G_json_array_append_value(root_array, default_value);
216  }
217 
218  // Serialize JSON array to a string and print to the file
220  if (!json_string) {
221  G_json_value_free(root_value);
222  close_file(fp);
223  G_fatal_error(_("Failed to serialize JSON to pretty format."));
224  }
225 
226  fputs(json_string, fp);
227 
229  G_json_value_free(root_value);
230 
231  close_file(fp);
232 }
#define NULL
Definition: ccmath.h:32
void G_rgb_to_hsv(int, int, int, float *, float *, float *)
Converts RGB color values to HSV format.
Definition: color_str.c:167
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:629
int CELL
Definition: gis.h:628
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
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.
#define COLOR_STRING_LENGTH
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
ColorFormat
Color format identifiers (enum)
Definition: raster.h:178
@ HSV
Definition: raster.h:178
@ RGB
Definition: raster.h:178
@ TRIPLET
Definition: raster.h:178
@ HEX
Definition: raster.h:178
Definition: gis.h:686
int version
Definition: gis.h:687