Rizin
unix-like reverse engineering framework and cli tools
rgb.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2013-2020 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2013-2020 xarkes <antide.petit@gmail.com>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 /* ansi 256 color extension for rz_cons */
5 /* https://en.wikipedia.org/wiki/ANSI_color */
6 
7 #include <rz_cons.h>
8 
9 int color_table[256] = { 0 };
10 int value_range[6] = { 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff };
11 
12 static void init_color_table(void) {
13  int i, r, g, b;
14  // ansi colors
15  color_table[0] = 0x000000;
16  color_table[1] = 0x800000;
17  color_table[2] = 0x008000;
18  color_table[3] = 0x808000;
19  color_table[4] = 0x000080;
20  color_table[5] = 0x800080;
21  color_table[6] = 0x008080;
22  color_table[7] = 0xc0c0c0;
23  color_table[8] = 0x808080;
24  color_table[9] = 0xff0000;
25  color_table[10] = 0x00ff00;
26  color_table[11] = 0xffff00;
27  color_table[12] = 0x0000ff;
28  color_table[13] = 0xff00ff;
29  color_table[14] = 0x00ffff;
30  color_table[15] = 0xffffff;
31  // color palette
32  for (i = 0; i < 216; i++) {
33  r = value_range[(i / 36) % 6];
34  g = value_range[(i / 6) % 6];
35  b = value_range[i % 6];
36  color_table[i + 16] = ((r << 16) & 0xffffff) +
37  ((g << 8) & 0xffff) + (b & 0xff);
38  }
39  // grayscale
40  for (i = 0; i < 24; i++) {
41  r = 8 + (i * 10);
42  color_table[i + 232] = ((r << 16) & 0xffffff) +
43  ((r << 8) & 0xffff) + (r & 0xff);
44  }
45 }
46 
47 static int __lookup_rgb(int r, int g, int b) {
48  int i, color = (r << 16) + (g << 8) + b;
49  // lookup extended colors only, coz non-extended can be changed by users.
50  for (i = 16; i < 256; i++) {
51  if (color_table[i] == color) {
52  return i;
53  }
54  }
55  return -1;
56 }
57 
58 static ut32 __approximate_rgb(int r, int g, int b) {
59  bool grey = (r > 0 && r < 255 && r == g && r == b);
60  if (grey) {
61  return 232 + (int)((double)r / (255 / 24.1));
62  }
63 #if 0
64  const double M = 16;
65  double R = r;
66  double G = g;
67  double B = b;
68  R = R /256 * 216;
69  R /= 256 * 216;
70  R /= 256 * 216;
71  r = R = RZ_DIM (R / 16, 0, 16);
72  g = G = RZ_DIM (G / 16, 0, 16);
73  b = B = RZ_DIM (B / 16, 0, 16);
74  r &= 0xff;
75  g &= 0xff;
76  b &= 0xff;
77  return (ut32)((G * M * M) + (g * M) + b) + 16;
78 #else
79  const int k = (256.0 / 6);
80  r = RZ_DIM(r / k, 0, 6);
81  g = RZ_DIM(g / k, 0, 6);
82  b = RZ_DIM(b / k, 0, 6);
83  return 16 + (r * 36) + (g * 6) + b;
84 #endif
85 }
86 
87 static int rgb(int r, int g, int b) {
88  int c = __lookup_rgb(r, g, b);
89  if (c == -1) {
90  return __approximate_rgb(r, g, b);
91  }
92  return c;
93 }
94 
95 static void __unrgb(int color, int *r, int *g, int *b) {
96  if (color < 0 || color > 255) {
97  *r = *g = *b = 0;
98  } else {
99  int rgb = color_table[color];
100  *r = (rgb >> 16) & 0xff;
101  *g = (rgb >> 8) & 0xff;
102  *b = rgb & 0xff;
103  }
104 }
105 
107  if (color_table[255] == 0) {
109  }
110 }
111 
112 /* Parse an ANSI code string into RGB values -- Used by HTML filter only */
113 RZ_API int rz_cons_rgb_parse(const char *p, ut8 *r, ut8 *g, ut8 *b, ut8 *a) {
114  const char *q = 0;
115  ut8 isbg = 0, bold = 127;
116  if (!p) {
117  return 0;
118  }
119  if (*p == 0x1b) {
120  p++;
121  if (!*p) {
122  return 0;
123  }
124  }
125  if (*p == '[') {
126  p++;
127  if (!*p) {
128  return 0;
129  }
130  }
131  // here, p should be just after the '['
132  switch (*p) {
133  case '1':
134  bold = 255;
135  if (!p[1] || !p[2]) {
136  return 0;
137  }
138  p += 2;
139  break;
140  case '3': isbg = 0; break;
141  case '4': isbg = 1; break;
142  }
143 #define SETRGB(x, y, z) \
144  if (r) \
145  *r = (x); \
146  if (g) \
147  *g = (y); \
148  if (b) \
149  *b = (z)
150  if (bold != 255 && strchr(p, ';')) {
151  if (!p[0] || !p[1] || !p[2]) {
152  return 0;
153  }
154  if (p[3] == '5') { // \x1b[%d;5;%dm is 256 colors
155  int x, y, z;
156  if (!p[3] || !p[4]) {
157  return 0;
158  }
159  int n = atoi(p + 5);
160  __unrgb(n, &x, &y, &z);
161  SETRGB(x, y, z);
162  } else { // 16M colors (truecolor)
163  /* complex rgb */
164  if (!p[3] || !p[4]) {
165  return 0;
166  }
167  p += 5;
168  if (r) {
169  *r = atoi(p);
170  }
171  q = strchr(p, ';');
172  if (!q) {
173  return 0;
174  }
175  if (g) {
176  *g = atoi(q + 1);
177  }
178  q = strchr(q + 1, ';');
179  if (!q) {
180  return 0;
181  }
182  if (b) {
183  *b = atoi(q + 1);
184  }
185  }
186  return 1;
187  } else {
188  /* plain ansi escape codes */
189  if (a) {
190  *a = isbg;
191  }
192  if (!*p) {
193  return 0;
194  }
195  switch (p[1]) {
196  case '0': SETRGB(0, 0, 0); break;
197  case '1': SETRGB(bold, 0, 0); break;
198  case '2': SETRGB(0, bold, 0); break;
199  case '3': SETRGB(bold, bold, 0); break;
200  case '4': SETRGB(0, 0, bold); break;
201  case '5': SETRGB(bold, 0, bold); break;
202  case '6': SETRGB(0, bold, bold); break;
203  case '7': SETRGB(bold, bold, bold); break;
204  }
205  }
206  return 1;
207 }
208 
209 RZ_API char *rz_cons_rgb_str_off(char *outstr, size_t sz, ut64 off) {
210  RzColor rc = RzColor_BLACK;
211  rc.id16 = -1;
212  rc.r = (off >> 2) & 0xff;
213  rc.g = (off >> 6) & 0xff;
214  rc.b = (off >> 12) & 0xff;
215  return rz_cons_rgb_str(outstr, sz, &rc);
216 }
217 
218 /* Compute color string depending on cons->color */
219 static void rz_cons_rgb_gen(RzConsColorMode mode, char *outstr, size_t sz, ut8 attr, ut8 a, ut8 r, ut8 g, ut8 b,
220  st8 id16) {
221  ut8 fgbg = (a == ALPHA_BG) ? 48 : 38; // ANSI codes for Background/Foreground
222 
223  if (sz < 4) { // must have at least room for "<esc>[m\0"
224  if (sz > 0) {
225  outstr[0] = '\0';
226  }
227  return;
228  }
229 
230  size_t i = 2;
231  outstr[0] = '\x1b';
232  outstr[1] = '[';
233  for (; attr; attr &= attr - 1) {
234  if (sz < i + 4) { // must have at least room for e.g. "1;m\0"
235  outstr[0] = '\0';
236  return;
237  }
238  switch (attr & -attr) {
239  case RZ_CONS_ATTR_BOLD: outstr[i] = '1'; break;
240  case RZ_CONS_ATTR_DIM: outstr[i] = '2'; break;
241  case RZ_CONS_ATTR_ITALIC: outstr[i] = '3'; break;
242  case RZ_CONS_ATTR_UNDERLINE: outstr[i] = '4'; break;
243  case RZ_CONS_ATTR_BLINK: outstr[i] = '5'; break;
244  }
245  outstr[i + 1] = ';';
246  i += 2;
247  }
248 
249  int written = -1;
250  switch (mode) {
251  case COLOR_MODE_256: // 256 color palette
252  written = snprintf(outstr + i, sz - i, "%d;5;%dm", fgbg, rgb(r, g, b));
253  break;
254  case COLOR_MODE_16M: // 16M (truecolor)
255  written = snprintf(outstr + i, sz - i, "%d;2;%d;%d;%dm", fgbg, r, g, b);
256  break;
257  case COLOR_MODE_16: { // ansi 16 colors
258  ut8 bright, c;
259  fgbg -= 8;
260  if (id16 >= 0 && id16 <= 15) {
261  c = id16 % 8;
262  bright = id16 >= 8 ? 60 : 0;
263  } else {
264  bright = (r == 0x80 && g == 0x80 && b == 0x80) ? 53
265  : (r == 0xff || g == 0xff || b == 0xff) ? 60
266  : 0; // eco bright-specific
267  if (r == g && g == b) {
268  r = (r > 0x7f) ? 1 : 0;
269  g = (g > 0x7f) ? 1 : 0;
270  b = (b > 0x7f) ? 1 : 0;
271  } else {
272  ut8 k = (r + g + b) / 3;
273  r = (r >= k) ? 1 : 0;
274  g = (g >= k) ? 1 : 0;
275  b = (b >= k) ? 1 : 0;
276  }
277  c = (r ? 1 : 0) + (g ? (b ? 6 : 2) : (b ? 4 : 0));
278  }
279  written = snprintf(outstr + i, sz - i, "%dm", fgbg + bright + c);
280  break;
281  }
282  default:
283  break;
284  }
285 
286  if (written < 0 || written >= sz - i) {
287  outstr[0] = '\0';
288  }
289 }
290 
291 /* Return the computed color string for the specified color in the specified mode */
292 RZ_API char *rz_cons_rgb_str_mode(RzConsColorMode mode, char *outstr, size_t sz, const RzColor *rcolor) {
293  if (!rcolor) {
294  return NULL;
295  }
296  if (!outstr) {
297  sz = 64;
298  outstr = calloc(sz, 1);
299  }
300  *outstr = 0;
301  if (rcolor->a == ALPHA_RESET) {
302  strcpy(outstr, Color_RESET);
303  return outstr;
304  }
305  // If the color handles both foreground and background, also add background
306  if (rcolor->a == ALPHA_FGBG) {
307  rz_cons_rgb_gen(mode, outstr, sz, 0, ALPHA_BG, rcolor->r2, rcolor->g2, rcolor->b2, rcolor->id16);
308  }
309  // APPEND
310  size_t len = strlen(outstr);
311  rz_cons_rgb_gen(mode, outstr + len, sz - len, rcolor->attr, rcolor->a, rcolor->r, rcolor->g, rcolor->b,
312  rcolor->id16);
313 
314  return outstr;
315 }
316 
317 /* Return the computed color string for the specified color */
318 RZ_API char *rz_cons_rgb_str(char *outstr, size_t sz, const RzColor *rcolor) {
319  return rz_cons_rgb_str_mode(rz_cons_singleton()->context->color_mode, outstr, sz, rcolor);
320 }
321 
323  const char *str = NULL;
324  if (r == 0x00 && g == b && g == 0) {
325  str = "black";
326  }
327  if (r == 0xff && g == b && g == 0xff) {
328  str = "white";
329  }
330  if (r == 0xff && g == b && g == 0) {
331  str = "red";
332  }
333  if (g == 0xff && r == b && r == 0) {
334  str = "green";
335  }
336  if (b == 0xff && r == g && r == 0) {
337  str = "blue";
338  }
339  if (r == 0xff && g == 0xff && b == 0x00) {
340  str = "yellow";
341  }
342  if (r == 0x00 && g == 0xff && b == 0xff) {
343  str = "cyan";
344  }
345  if (r == 0xff && g == 0x00 && b == 0xff) {
346  str = "magenta";
347  }
348  return str ? strdup(str) : rz_str_newf("#%02x%02x%02x", r, g, b);
349 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
#define R(x, b, m)
Definition: arc.h:168
#define B(x)
Definition: arc.h:166
RZ_API RzCons * rz_cons_singleton(void)
Definition: cons.c:300
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
uint32_t ut32
const char * k
Definition: dsignal.c:11
struct @667 g
const char int mode
Definition: ioapi.h:137
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
#define M
Definition: common.h:37
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
int x
Definition: mipsasm.c:20
int n
Definition: mipsasm.c:19
int off
Definition: pal.c:13
RzColor rcolor
Definition: pal.c:97
RZ_API void rz_cons_rgb_init(void)
Definition: rgb.c:106
#define SETRGB(x, y, z)
RZ_API char * rz_cons_rgb_str_mode(RzConsColorMode mode, char *outstr, size_t sz, const RzColor *rcolor)
Definition: rgb.c:292
RZ_API int rz_cons_rgb_parse(const char *p, ut8 *r, ut8 *g, ut8 *b, ut8 *a)
Definition: rgb.c:113
static void init_color_table(void)
Definition: rgb.c:12
RZ_API char * rz_cons_rgb_str_off(char *outstr, size_t sz, ut64 off)
Definition: rgb.c:209
RZ_API char * rz_cons_rgb_str(char *outstr, size_t sz, const RzColor *rcolor)
Definition: rgb.c:318
RZ_API char * rz_cons_rgb_tostring(ut8 r, ut8 g, ut8 b)
Definition: rgb.c:322
int color_table[256]
Definition: rgb.c:9
static int rgb(int r, int g, int b)
Definition: rgb.c:87
int value_range[6]
Definition: rgb.c:10
static void rz_cons_rgb_gen(RzConsColorMode mode, char *outstr, size_t sz, ut8 attr, ut8 a, ut8 r, ut8 g, ut8 b, st8 id16)
Definition: rgb.c:219
static ut32 __approximate_rgb(int r, int g, int b)
Definition: rgb.c:58
static int __lookup_rgb(int r, int g, int b)
Definition: rgb.c:47
static void __unrgb(int color, int *r, int *g, int *b)
Definition: rgb.c:95
#define RzColor_BLACK
Definition: rz_cons.h:702
@ ALPHA_RESET
Definition: rz_cons.h:167
@ ALPHA_FGBG
Definition: rz_cons.h:170
@ ALPHA_BG
Definition: rz_cons.h:169
#define Color_RESET
Definition: rz_cons.h:617
RzConsColorMode
Definition: rz_cons.h:441
@ COLOR_MODE_16
Definition: rz_cons.h:443
@ COLOR_MODE_16M
Definition: rz_cons.h:445
@ COLOR_MODE_256
Definition: rz_cons.h:444
@ RZ_CONS_ATTR_BLINK
Definition: rz_cons.h:175
@ RZ_CONS_ATTR_ITALIC
Definition: rz_cons.h:173
@ RZ_CONS_ATTR_DIM
Definition: rz_cons.h:172
@ RZ_CONS_ATTR_UNDERLINE
Definition: rz_cons.h:174
@ RZ_CONS_ATTR_BOLD
Definition: rz_cons.h:171
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_DIM(x, y, z)
#define st8
Definition: rz_types_base.h:16
static int
Definition: sfsocketcall.h:114
#define b(i)
Definition: sha256.c:42
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
ut8 r2
Definition: rz_cons.h:185
st8 id16
Definition: rz_cons.h:188
ut8 g2
Definition: rz_cons.h:186
ut8 g
Definition: rz_cons.h:183
ut8 b
Definition: rz_cons.h:184
ut8 b2
Definition: rz_cons.h:187
ut8 r
Definition: rz_cons.h:182
ut8 a
Definition: rz_cons.h:181
ut8 attr
Definition: rz_cons.h:180
static int color
Definition: visual.c:20
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
#define G
Definition: zip_err_str.c:13