ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
ANSI Utilities

Data Structures

struct  ansi_rle_context_t
 
struct  ansi_timing_t
 
struct  rgb_error_t
 

Enumerations

enum  ansi_color_mode_t { ANSI_MODE_FOREGROUND = 0 , ANSI_MODE_BACKGROUND , ANSI_MODE_FOREGROUND_BACKGROUND }
 

Functions

char * ansi_strip_escapes (const char *input, size_t input_len)
 Strip all ANSI escape sequences from a string.
 
const char * ansi_skip_escape (const char *ptr, const char *end)
 Find the end of an ANSI CSI escape sequence.
 
bool ansi_is_already_colorized (const char *message, size_t pos)
 Check if a position in text is already colored.
 
char * append_truecolor_fg (char *dst, uint8_t r, uint8_t g, uint8_t b)
 
char * append_truecolor_bg (char *dst, uint8_t r, uint8_t g, uint8_t b)
 
char * append_truecolor_fg_bg (char *dst, uint8_t fg_r, uint8_t fg_g, uint8_t fg_b, uint8_t bg_r, uint8_t bg_g, uint8_t bg_b)
 
void ansi_rle_init (ansi_rle_context_t *ctx, char *buffer, size_t capacity, ansi_color_mode_t mode)
 
void ansi_rle_add_pixel (ansi_rle_context_t *ctx, uint8_t r, uint8_t g, uint8_t b, char ascii_char)
 
void ansi_rle_finish (ansi_rle_context_t *ctx)
 
void ansi_fast_init (void)
 
void ansi_fast_init_256color (void)
 
void ansi_fast_init_16color (void)
 
char * append_256color_fg (char *dst, uint8_t color_index)
 
char * append_256color_bg (char *dst, uint8_t color_index)
 
uint8_t rgb_to_256color (uint8_t r, uint8_t g, uint8_t b)
 
char * append_16color_fg (char *dst, uint8_t color_index)
 
char * append_16color_bg (char *dst, uint8_t color_index)
 
uint8_t rgb_to_16color (uint8_t r, uint8_t g, uint8_t b)
 
void get_16color_rgb (uint8_t color_index, uint8_t *r, uint8_t *g, uint8_t *b)
 
uint8_t rgb_to_16color_dithered (int r, int g, int b, int x, int y, int width, int height, rgb_error_t *error_buffer)
 
char * append_color_fg_for_mode (char *dst, uint8_t r, uint8_t g, uint8_t b, terminal_color_mode_t mode)
 

Detailed Description

Enumeration Type Documentation

◆ ansi_color_mode_t

#include <ansi.h>

Enumerator
ANSI_MODE_FOREGROUND 
ANSI_MODE_BACKGROUND 
ANSI_MODE_FOREGROUND_BACKGROUND 

Definition at line 38 of file ansi.h.

38 {
ansi_color_mode_t
Definition ansi.h:38
@ ANSI_MODE_FOREGROUND_BACKGROUND
Definition ansi.h:41
@ ANSI_MODE_FOREGROUND
Definition ansi.h:39
@ ANSI_MODE_BACKGROUND
Definition ansi.h:40

Function Documentation

◆ ansi_fast_init()

void ansi_fast_init ( void  )

#include <ansi.h>

Initialize fast ANSI generation (call once at startup)

Definition at line 319 of file ansi.c.

319 {
320 // Initialize the dec3 cache used by truecolor functions
322}
void ascii_simd_init(void)
Initialize SIMD subsystem.

References ascii_simd_init().

Referenced by client_init_with_args(), mirror_init_with_args(), and session_display_create().

◆ ansi_fast_init_16color()

void ansi_fast_init_16color ( void  )

#include <ansi.h>

Initialize 16-color mode (thread-safe, called on first use)

Definition at line 398 of file ansi.c.

398 {
399 if (!lifecycle_init(&g_color16_lc, "ansi_16color")) {
400 return; // Already initialized
401 }
402 do_init_16color();
403}
bool lifecycle_init(lifecycle_t *lc, const char *name)
Definition lifecycle.c:26

References lifecycle_init().

Referenced by append_16color_bg(), append_16color_fg(), image_print_16color(), image_print_16color_dithered(), image_print_16color_dithered_with_background(), rgb_to_16color_halfblocks_scalar(), and session_display_create().

◆ ansi_fast_init_256color()

void ansi_fast_init_256color ( void  )

#include <ansi.h>

Initialize 256-color mode (thread-safe, called on first use)

Definition at line 334 of file ansi.c.

334 {
335 if (!lifecycle_init(&g_color256_lc, "ansi_256color")) {
336 return; // Already initialized
337 }
338 do_init_256color();
339}

References lifecycle_init().

Referenced by image_print_256color(), rgb_to_256color_halfblocks_scalar(), and session_display_create().

◆ ansi_is_already_colorized()

bool ansi_is_already_colorized ( const char *  message,
size_t  pos 
)

#include <ansi.h>

Check if a position in text is already colored.

Scans from the start of the message to the given position, tracking ANSI escape codes. Returns true if there is an active color code (not in reset state).

Detects reset codes: \x1b[0m and \x1b[m

Parameters
messageThe full message
posPosition to check
Returns
true if already colored (not in reset state), false if in reset state

Definition at line 98 of file ansi.c.

98 {
99 if (!message) {
100 return false;
101 }
102
103 bool in_reset = true; // Start in reset state
104
105 // Scan from beginning to current position looking for ANSI codes
106 for (size_t i = 0; i < pos && message[i] != '\0'; i++) {
107 if (message[i] == '\x1b' && message[i + 1] == '[') {
108 // Found ANSI escape sequence start
109 // Look for the end marker 'm'
110 size_t j = i + 2;
111 while (message[j] != '\0' && message[j] != 'm') {
112 j++;
113 }
114
115 if (message[j] == 'm') {
116 // Extract the color code part (between [ and m)
117 // Check if it's a reset code: \x1b[0m or \x1b[m
118 in_reset = ((j == i + 3 && message[i + 2] == '0') || (j == i + 2));
119 }
120 }
121 }
122
123 // Return true if NOT in reset state (already colorized)
124 return !in_reset;
125}

Referenced by colorize_log_message().

◆ ansi_rle_add_pixel()

void ansi_rle_add_pixel ( ansi_rle_context_t *  ctx,
uint8_t  r,
uint8_t  g,
uint8_t  b,
char  ascii_char 
)

#include <ansi.h>

Add pixel with run-length encoding (only emits SGR when color changes)

Parameters
ctxRLE context
rRed component
gGreen component
bBlue component
ascii_charASCII character to append

Definition at line 261 of file ansi.c.

261 {
262 // Check if we need to emit a new SGR sequence
263 bool color_changed = ctx->first_pixel || (r != ctx->last_r) || (g != ctx->last_g) || (b != ctx->last_b);
264
265 if (color_changed) {
266 if (ctx->length + 40 >= ctx->capacity) {
267 // Log when we can't add a color change due to buffer capacity
268 log_warn_every(US_PER_SEC_INT, "RLE_CAPACITY: Cannot add SGR at length=%zu, capacity=%zu (need 40 bytes)",
269 ctx->length, ctx->capacity);
270 }
271 }
272
273 if (color_changed && (ctx->length + 40 < ctx->capacity)) { // Reserve 40 bytes for SGR (FG+BG max is 38)
274 char *pos = ctx->buffer + ctx->length;
275
276 switch (ctx->mode) {
278 pos = append_truecolor_fg(pos, r, g, b);
279 break;
281 pos = append_truecolor_bg(pos, r, g, b);
282 break;
284 // For FG+BG mode, use a default background (black) or implement dual-color logic
285 pos = append_truecolor_fg_bg(pos, r, g, b, 0, 0, 0);
286 break;
287 }
288
289 ctx->length = (size_t)(pos - ctx->buffer);
290 ctx->last_r = r;
291 ctx->last_g = g;
292 ctx->last_b = b;
293 ctx->first_pixel = false;
294 }
295
296 // Add the ASCII character
297 if (ctx->length < ctx->capacity - 1) {
298 ctx->buffer[ctx->length++] = ascii_char;
299 }
300}
char * append_truecolor_fg(char *dst, uint8_t r, uint8_t g, uint8_t b)
Definition ansi.c:143
char * append_truecolor_fg_bg(char *dst, uint8_t fg_r, uint8_t fg_g, uint8_t fg_b, uint8_t bg_r, uint8_t bg_g, uint8_t bg_b)
Definition ansi.c:199
char * append_truecolor_bg(char *dst, uint8_t r, uint8_t g, uint8_t b)
Definition ansi.c:173
#define US_PER_SEC_INT
Definition time.h:161
#define log_warn_every(interval_us, fmt,...)
Rate-limited WARN logging.
Definition log/log.h:708
uint8_t last_b
Definition ansi.h:53
uint8_t last_g
Definition ansi.h:52
size_t capacity
Definition ansi.h:47
uint8_t last_r
Definition ansi.h:51
char * buffer
Definition ansi.h:46
bool first_pixel
Definition ansi.h:50
size_t length
Definition ansi.h:48
ansi_color_mode_t mode
Definition ansi.h:49

References ANSI_MODE_BACKGROUND, ANSI_MODE_FOREGROUND, ANSI_MODE_FOREGROUND_BACKGROUND, append_truecolor_bg(), append_truecolor_fg(), append_truecolor_fg_bg(), ansi_rle_context_t::buffer, ansi_rle_context_t::capacity, ansi_rle_context_t::first_pixel, ansi_rle_context_t::last_b, ansi_rle_context_t::last_g, ansi_rle_context_t::last_r, ansi_rle_context_t::length, log_warn_every, ansi_rle_context_t::mode, and US_PER_SEC_INT.

Referenced by image_print_color().

◆ ansi_rle_finish()

void ansi_rle_finish ( ansi_rle_context_t *  ctx)

#include <ansi.h>

Finish RLE sequence with reset and null terminator

Parameters
ctxRLE context

Definition at line 303 of file ansi.c.

303 {
304 // Add reset sequence (requires 4 bytes + 1 for null terminator = 5 bytes total)
305 if (ctx->length + 5 <= ctx->capacity) {
306 SAFE_MEMCPY(ctx->buffer + ctx->length, 4, "\033[0m", 4);
307 ctx->length += 4;
308 }
309
310 // Null terminate
311 if (ctx->length < ctx->capacity) {
312 ctx->buffer[ctx->length] = '\0';
313 }
314}
#define SAFE_MEMCPY(dest, dest_size, src, count)
Definition common.h:468

References ansi_rle_context_t::buffer, ansi_rle_context_t::capacity, ansi_rle_context_t::length, and SAFE_MEMCPY.

Referenced by image_print_color().

◆ ansi_rle_init()

void ansi_rle_init ( ansi_rle_context_t *  ctx,
char *  buffer,
size_t  capacity,
ansi_color_mode_t  mode 
)

#include <ansi.h>

Initialize RLE context for efficient ANSI generation

Parameters
ctxContext to initialize
bufferOutput buffer
capacityBuffer capacity
modeColor mode (foreground/background/both)

Definition at line 248 of file ansi.c.

248 {
249 ctx->buffer = buffer;
250 ctx->capacity = capacity;
251 ctx->length = 0;
252 ctx->mode = mode;
253 ctx->first_pixel = true;
254 // Initialize with impossible color values to force first SGR
255 ctx->last_r = 0xFF;
256 ctx->last_g = 0xFF;
257 ctx->last_b = 0xFF;
258}

References ansi_rle_context_t::buffer, ansi_rle_context_t::capacity, ansi_rle_context_t::first_pixel, ansi_rle_context_t::last_b, ansi_rle_context_t::last_g, ansi_rle_context_t::last_r, ansi_rle_context_t::length, and ansi_rle_context_t::mode.

Referenced by image_print_color().

◆ ansi_skip_escape()

const char * ansi_skip_escape ( const char *  ptr,
const char *  end 
)

#include <ansi.h>

Find the end of an ANSI CSI escape sequence.

Given a pointer to an ESC character (\x1b) that starts a CSI sequence, returns a pointer past the final byte of the sequence. If the pointer does not point to a valid CSI sequence start, returns ptr + 1.

Parameters
ptrPointer to the ESC (\x1b) character
endPointer past the end of the string
Returns
Pointer to the first byte after the escape sequence

Definition at line 74 of file ansi.c.

74 {
75 if (!ptr || ptr >= end || *ptr != '\x1b') {
76 return ptr ? ptr + 1 : ptr;
77 }
78
79 const char *p = ptr + 1;
80 if (p >= end || *p != '[') {
81 return p; // Not a CSI sequence, skip just the ESC byte
82 }
83 p++; // Skip '['
84
85 // Skip parameter bytes (0x30-0x3F) and intermediate bytes (0x20-0x2F)
86 while (p < end && ((*p >= 0x30 && *p <= 0x3F) || (*p >= 0x20 && *p <= 0x2F))) {
87 p++;
88 }
89
90 // Skip final byte (0x40-0x7E)
91 if (p < end && *p >= 0x40 && *p <= 0x7E) {
92 p++;
93 }
94
95 return p;
96}

Referenced by truncate_with_ellipsis().

◆ ansi_strip_escapes()

char * ansi_strip_escapes ( const char *  input,
size_t  input_len 
)

#include <ansi.h>

Strip all ANSI escape sequences from a string.

Removes all ANSI CSI sequences (ESC [ ... final_byte) from the input, leaving only printable text. Useful for creating plain text output from colorized ASCII art.

Parameters
inputInput string containing ANSI escape sequences
input_lenLength of input string
Returns
Newly allocated string with escapes removed (caller must free), or NULL on error

Definition at line 23 of file ansi.c.

23 {
24 if (!input || input_len == 0) {
25 return NULL;
26 }
27
28 // Allocate buffer directly for output (at most input_len bytes)
29 char *output = SAFE_MALLOC(input_len + 1, char *);
30 if (!output) {
31 return NULL;
32 }
33
34 size_t out_pos = 0;
35 size_t i = 0;
36
37 while (i < input_len) {
38 // Check for ESC character (start of ANSI sequence)
39 if (input[i] == '\x1b' && i + 1 < input_len && input[i + 1] == '[') {
40 // Skip ESC[
41 i += 2;
42
43 // Skip parameter bytes (digits, semicolons, and intermediate bytes)
44 while (i < input_len) {
45 char c = input[i];
46 // Parameter bytes: 0x30-0x3F (digits, semicolon, etc.)
47 // Intermediate bytes: 0x20-0x2F (space, !, ", etc.)
48 if ((c >= 0x30 && c <= 0x3F) || (c >= 0x20 && c <= 0x2F)) {
49 i++;
50 } else {
51 break;
52 }
53 }
54
55 // Skip final byte (0x40-0x7E: @, A-Z, [, \, ], ^, _, `, a-z, {, |, }, ~)
56 if (i < input_len) {
57 char final = input[i];
58 if (final >= 0x40 && final <= 0x7E) {
59 i++;
60 }
61 }
62 } else {
63 // Regular character - copy to output
64 output[out_pos++] = input[i];
65 i++;
66 }
67 }
68
69 // Null-terminate the output
70 output[out_pos] = '\0';
71 return output;
72}
#define SAFE_MALLOC(size, cast)
Definition common.h:264

References SAFE_MALLOC.

Referenced by display_height(), display_width(), layout_print_two_column_row(), and log_mmap_write().

◆ append_16color_bg()

char * append_16color_bg ( char *  dst,
uint8_t  color_index 
)

#include <ansi.h>

Append 16-color ANSI background SGR sequence

Parameters
dstDestination buffer
color_index16-color index (0-15)
Returns
Pointer to end of written data

Definition at line 421 of file ansi.c.

421 {
422 // Ensure initialization before use
424
425 if (color_index >= 16) {
426 color_index = 0; // Default to black background
427 }
428
429 const char *color_str = color16_bg_strings[color_index];
430 while (*color_str) {
431 *dst++ = *color_str++;
432 }
433
434 return dst;
435}
void ansi_fast_init_16color(void)
Definition ansi.c:398

References ansi_fast_init_16color().

Referenced by image_print_16color_dithered_with_background(), and rgb_to_16color_halfblocks_scalar().

◆ append_16color_fg()

char * append_16color_fg ( char *  dst,
uint8_t  color_index 
)

#include <ansi.h>

Append 16-color ANSI foreground SGR sequence

Parameters
dstDestination buffer
color_index16-color index (0-15)
Returns
Pointer to end of written data

Definition at line 405 of file ansi.c.

405 {
406 // Ensure initialization before use
408
409 if (color_index >= 16) {
410 color_index = 7; // Default to white
411 }
412
413 const char *color_str = color16_fg_strings[color_index];
414 while (*color_str) {
415 *dst++ = *color_str++;
416 }
417
418 return dst;
419}

References ansi_fast_init_16color().

Referenced by append_color_fg_for_mode(), image_print_16color(), image_print_16color_dithered(), image_print_16color_dithered_with_background(), and rgb_to_16color_halfblocks_scalar().

◆ append_256color_bg()

char * append_256color_bg ( char *  dst,
uint8_t  color_index 
)

#include <ansi.h>

Append 256-color background SGR sequence

Parameters
dstDestination buffer
color_index256-color palette index (0-255)
Returns
Pointer to end of written data

Definition at line 352 of file ansi.c.

352 {
353 const char *color_str = color256_bg_strings[color_index];
354 size_t len = strlen(color_str);
355 SAFE_MEMCPY(dst, len, color_str, len);
356 return dst + len;
357}

References SAFE_MEMCPY.

Referenced by rgb_to_256color_halfblocks_scalar().

◆ append_256color_fg()

char * append_256color_fg ( char *  dst,
uint8_t  color_index 
)

#include <ansi.h>

Append 256-color foreground SGR sequence

Parameters
dstDestination buffer
color_index256-color palette index (0-255)
Returns
Pointer to end of written data

Definition at line 344 of file ansi.c.

344 {
345 const char *color_str = color256_strings[color_index];
346 size_t len = strlen(color_str);
347 SAFE_MEMCPY(dst, len, color_str, len);
348 return dst + len;
349}

References SAFE_MEMCPY.

Referenced by append_color_fg_for_mode(), image_print_256color(), and rgb_to_256color_halfblocks_scalar().

◆ append_color_fg_for_mode()

char * append_color_fg_for_mode ( char *  dst,
uint8_t  r,
uint8_t  g,
uint8_t  b,
terminal_color_mode_t  mode 
)

#include <ansi.h>

Append color SGR sequence for the appropriate terminal color mode

Parameters
dstDestination buffer
rRed component
gGreen component
bBlue component
modeTerminal color mode capability
Returns
Pointer to end of written data

Definition at line 588 of file ansi.c.

588 {
589 switch (mode) {
591 return append_truecolor_fg(dst, r, g, b);
592
594 uint8_t color_index = rgb_to_256color(r, g, b);
595 return append_256color_fg(dst, color_index);
596 }
597
598 case COLOR_MODE_16_COLOR: {
599 uint8_t color_index = rgb_to_16color(r, g, b);
600 return append_16color_fg(dst, color_index);
601 }
602
603 case COLOR_MODE_NONE:
604 case COLOR_MODE_AUTO:
605 default:
606 // No color output for monochrome mode or auto mode (fallback)
607 return dst;
608 }
609}
char * append_16color_fg(char *dst, uint8_t color_index)
Definition ansi.c:405
uint8_t rgb_to_16color(uint8_t r, uint8_t g, uint8_t b)
Definition ansi.c:437
char * append_256color_fg(char *dst, uint8_t color_index)
Definition ansi.c:344
uint8_t rgb_to_256color(uint8_t r, uint8_t g, uint8_t b)
Definition ansi.c:360
unsigned char uint8_t
Definition common.h:56
#define COLOR_MODE_16_COLOR
16-color mode (full name)
#define COLOR_MODE_256_COLOR
256-color mode (full name)
#define COLOR_MODE_TRUECOLOR
24-bit truecolor mode
#define COLOR_MODE_AUTO
Backward compatibility aliases for color mode enum values.
#define COLOR_MODE_NONE
Monochrome mode.

References append_16color_fg(), append_256color_fg(), append_truecolor_fg(), COLOR_MODE_16_COLOR, COLOR_MODE_256_COLOR, COLOR_MODE_AUTO, COLOR_MODE_NONE, COLOR_MODE_TRUECOLOR, rgb_to_16color(), and rgb_to_256color().

◆ append_truecolor_bg()

char * append_truecolor_bg ( char *  dst,
uint8_t  r,
uint8_t  g,
uint8_t  b 
)

#include <ansi.h>

Append truecolor background SGR sequence Maximum output: 19 bytes (\033[48;2;255;255;255m)

Parameters
dstDestination buffer
rRed component
gGreen component
bBlue component
Returns
Pointer to end of written data

Definition at line 173 of file ansi.c.

173 {
174 // Ensure dec3 cache is initialized
176 init_dec3();
177 }
178
179 SAFE_MEMCPY(dst, 19, "\033[48;2;", 7);
180 dst += 7;
181
183 dst += g_dec3_cache.dec3_table[r].len;
184 *dst++ = ';';
185
187 dst += g_dec3_cache.dec3_table[g].len;
188 *dst++ = ';';
189
191 dst += g_dec3_cache.dec3_table[b].len;
192 *dst++ = 'm';
193
194 return dst;
195}
global_dec3_cache_t g_dec3_cache
Global decimal cache instance.
void init_dec3(void)
Initialize decimal-to-ASCII cache (0-255 → "0" to "255")

References global_dec3_cache_t::dec3_initialized, global_dec3_cache_t::dec3_table, g_dec3_cache, init_dec3(), dec3_t::len, dec3_t::s, and SAFE_MEMCPY.

Referenced by ansi_rle_add_pixel(), grep_highlight(), and grep_highlight_colored().

◆ append_truecolor_fg()

char * append_truecolor_fg ( char *  dst,
uint8_t  r,
uint8_t  g,
uint8_t  b 
)

#include <ansi.h>

Append truecolor foreground SGR sequence Maximum output: 19 bytes (\033[38;2;255;255;255m)

Parameters
dstDestination buffer
rRed component
gGreen component
bBlue component
Returns
Pointer to end of written data

Definition at line 143 of file ansi.c.

143 {
144 // Ensure dec3 cache is initialized
146 init_dec3();
147 }
148
149 // Static prefix - 7 bytes
150 SAFE_MEMCPY(dst, 19, "\033[38;2;", 7);
151 dst += 7;
152
153 // Red component + semicolon
155 dst += g_dec3_cache.dec3_table[r].len;
156 *dst++ = ';';
157
158 // Green component + semicolon
160 dst += g_dec3_cache.dec3_table[g].len;
161 *dst++ = ';';
162
163 // Blue component + suffix
165 dst += g_dec3_cache.dec3_table[b].len;
166 *dst++ = 'm';
167
168 return dst;
169}

References global_dec3_cache_t::dec3_initialized, global_dec3_cache_t::dec3_table, g_dec3_cache, init_dec3(), dec3_t::len, dec3_t::s, and SAFE_MEMCPY.

Referenced by ansi_rle_add_pixel(), and append_color_fg_for_mode().

◆ append_truecolor_fg_bg()

char * append_truecolor_fg_bg ( char *  dst,
uint8_t  fg_r,
uint8_t  fg_g,
uint8_t  fg_b,
uint8_t  bg_r,
uint8_t  bg_g,
uint8_t  bg_b 
)

#include <ansi.h>

Append combined foreground + background truecolor SGR Maximum output: 38 bytes (\033[38;2;255;255;255;48;2;255;255;255m)

Parameters
dstDestination buffer
fg_rForeground red component
fg_gForeground green component
fg_bForeground blue component
bg_rBackground red component
bg_gBackground green component
bg_bBackground blue component
Returns
Pointer to end of written data

Definition at line 199 of file ansi.c.

200 {
201 // Ensure dec3 cache is initialized
203 init_dec3();
204 }
205
206 SAFE_MEMCPY(dst, 38, "\033[38;2;", 7);
207 dst += 7;
208
209 // Foreground RGB (remaining: 31 bytes max)
211 dst += g_dec3_cache.dec3_table[fg_r].len;
212 *dst++ = ';';
213
214 // Remaining: 27 bytes max
216 dst += g_dec3_cache.dec3_table[fg_g].len;
217 *dst++ = ';';
218
219 // Remaining: 23 bytes max
221 dst += g_dec3_cache.dec3_table[fg_b].len;
222
223 // Background RGB (remaining: 20 bytes max)
224 SAFE_MEMCPY(dst, 20, ";48;2;", 6);
225 dst += 6;
226
227 // Remaining: 14 bytes max
229 dst += g_dec3_cache.dec3_table[bg_r].len;
230 *dst++ = ';';
231
232 // Remaining: 10 bytes max
234 dst += g_dec3_cache.dec3_table[bg_g].len;
235 *dst++ = ';';
236
237 // Remaining: 6 bytes max
239 dst += g_dec3_cache.dec3_table[bg_b].len;
240 *dst++ = 'm';
241
242 return dst;
243}

References global_dec3_cache_t::dec3_initialized, global_dec3_cache_t::dec3_table, g_dec3_cache, init_dec3(), dec3_t::len, dec3_t::s, and SAFE_MEMCPY.

Referenced by ansi_rle_add_pixel().

◆ get_16color_rgb()

void get_16color_rgb ( uint8_t  color_index,
uint8_t *  r,
uint8_t *  g,
uint8_t *  b 
)

#include <ansi.h>

Get RGB values for a 16-color ANSI index

Parameters
color_index16-color index (0-15)
rOutput red component
gOutput green component
bOutput blue component

Definition at line 480 of file ansi.c.

480 {
481 // Same color table as rgb_to_16color()
482 static const uint8_t ansi_colors[16][3] = {
483 {0, 0, 0}, // 0: Black
484 {128, 0, 0}, // 1: Dark Red
485 {0, 128, 0}, // 2: Dark Green
486 {128, 128, 0}, // 3: Dark Yellow (Brown)
487 {0, 0, 128}, // 4: Dark Blue
488 {128, 0, 128}, // 5: Dark Magenta
489 {0, 128, 128}, // 6: Dark Cyan
490 {192, 192, 192}, // 7: Light Gray
491 {128, 128, 128}, // 8: Dark Gray
492 {255, 0, 0}, // 9: Bright Red
493 {0, 255, 0}, // 10: Bright Green
494 {255, 255, 0}, // 11: Bright Yellow
495 {0, 0, 255}, // 12: Bright Blue
496 {255, 0, 255}, // 13: Bright Magenta
497 {0, 255, 255}, // 14: Bright Cyan
498 {255, 255, 255} // 15: White
499 };
500
501 if (color_index >= 16) {
502 color_index = 7; // Default to light gray
503 }
504
505 *r = ansi_colors[color_index][0];
506 *g = ansi_colors[color_index][1];
507 *b = ansi_colors[color_index][2];
508}

Referenced by image_print_16color_dithered_with_background(), and rgb_to_16color_dithered().

◆ rgb_to_16color()

uint8_t rgb_to_16color ( uint8_t  r,
uint8_t  g,
uint8_t  b 
)

#include <ansi.h>

Convert RGB to closest 16-color ANSI index Uses distance-based matching against standard ANSI colors

Parameters
rRed component
gGreen component
bBlue component
Returns
16-color index (0-15)

Definition at line 437 of file ansi.c.

437 {
438 // Convert RGB to the closest 16-color ANSI color
439 // This uses a simple distance-based approach
440
441 // Define the 16 ANSI colors in RGB
442 static const uint8_t ansi_colors[16][3] = {
443 {0, 0, 0}, // 0: Black
444 {128, 0, 0}, // 1: Dark Red
445 {0, 128, 0}, // 2: Dark Green
446 {128, 128, 0}, // 3: Dark Yellow (Brown)
447 {0, 0, 128}, // 4: Dark Blue
448 {128, 0, 128}, // 5: Dark Magenta
449 {0, 128, 128}, // 6: Dark Cyan
450 {192, 192, 192}, // 7: Light Gray
451 {128, 128, 128}, // 8: Dark Gray
452 {255, 0, 0}, // 9: Bright Red
453 {0, 255, 0}, // 10: Bright Green
454 {255, 255, 0}, // 11: Bright Yellow
455 {0, 0, 255}, // 12: Bright Blue
456 {255, 0, 255}, // 13: Bright Magenta
457 {0, 255, 255}, // 14: Bright Cyan
458 {255, 255, 255} // 15: White
459 };
460
461 uint8_t best_match = 0;
462 int min_distance = INT_MAX;
463
464 for (int i = 0; i < 16; i++) {
465 int dr = (int)r - (int)ansi_colors[i][0];
466 int dg = (int)g - (int)ansi_colors[i][1];
467 int db = (int)b - (int)ansi_colors[i][2];
468 int distance = dr * dr + dg * dg + db * db;
469
470 if (distance < min_distance) {
471 min_distance = distance;
472 best_match = i;
473 }
474 }
475
476 return best_match;
477}

Referenced by append_color_fg_for_mode(), colorscheme_compile_scheme(), image_print_16color(), rgb_to_16color_dithered(), and rgb_to_16color_halfblocks_scalar().

◆ rgb_to_16color_dithered()

uint8_t rgb_to_16color_dithered ( int  r,
int  g,
int  b,
int  x,
int  y,
int  width,
int  height,
rgb_error_t *  error_buffer 
)

#include <ansi.h>

Convert RGB to 16-color with Floyd-Steinberg dithering

Parameters
rRed component
gGreen component
bBlue component
xCurrent pixel X coordinate
yCurrent pixel Y coordinate
widthImage width
heightImage height
error_bufferDithering error buffer (width*height elements)
Returns
16-color index with dithering applied

Definition at line 511 of file ansi.c.

511 {
512 // Add accumulated error from previous pixels
513 if (error_buffer) {
514 // Use size_t for index calculation to prevent integer overflow on large images
515 size_t error_idx = (size_t)y * (size_t)width + (size_t)x;
516 r += error_buffer[error_idx].r;
517 g += error_buffer[error_idx].g;
518 b += error_buffer[error_idx].b;
519
520 // Reset error for this pixel
521 error_buffer[error_idx].r = 0;
522 error_buffer[error_idx].g = 0;
523 error_buffer[error_idx].b = 0;
524 }
525
526 // Clamp values to [0, 255]
527 uint8_t r_clamped = clamp_rgb((int)r);
528 uint8_t g_clamped = clamp_rgb((int)g);
529 uint8_t b_clamped = clamp_rgb((int)b);
530
531 // Find the closest 16-color match
532 uint8_t closest_color = rgb_to_16color(r_clamped, g_clamped, b_clamped);
533
534 // Calculate quantization error if dithering is enabled
535 if (error_buffer) {
536 uint8_t actual_r, actual_g, actual_b;
537 get_16color_rgb(closest_color, &actual_r, &actual_g, &actual_b);
538
539 int error_r = r - (int)actual_r;
540 int error_g = g - (int)actual_g;
541 int error_b = b - (int)actual_b;
542
543 // Distribute error using Floyd-Steinberg weights:
544 // * 7/16
545 // 3/16 5/16 1/16
546
547 // Error to right pixel (x+1, y)
548 // Use size_t for all index calculations to prevent integer overflow
549 if (x + 1 < width) {
550 size_t right_idx = (size_t)y * (size_t)width + (size_t)(x + 1);
551 error_buffer[right_idx].r += (error_r * 7) / 16;
552 error_buffer[right_idx].g += (error_g * 7) / 16;
553 error_buffer[right_idx].b += (error_b * 7) / 16;
554 }
555
556 // Error to pixels on next row (y+1)
557 if (y + 1 < height) {
558 // Bottom-left pixel (x-1, y+1)
559 if (x - 1 >= 0) {
560 size_t bl_idx = (size_t)(y + 1) * (size_t)width + (size_t)(x - 1);
561 error_buffer[bl_idx].r += (error_r * 3) / 16;
562 error_buffer[bl_idx].g += (error_g * 3) / 16;
563 error_buffer[bl_idx].b += (error_b * 3) / 16;
564 }
565
566 // Bottom pixel (x, y+1)
567 size_t bottom_idx = (size_t)(y + 1) * (size_t)width + (size_t)x;
568 error_buffer[bottom_idx].r += (error_r * 5) / 16;
569 error_buffer[bottom_idx].g += (error_g * 5) / 16;
570 error_buffer[bottom_idx].b += (error_b * 5) / 16;
571
572 // Bottom-right pixel (x+1, y+1)
573 if (x + 1 < width) {
574 size_t br_idx = (size_t)(y + 1) * (size_t)width + (size_t)(x + 1);
575 error_buffer[br_idx].r += (error_r * 1) / 16;
576 error_buffer[br_idx].g += (error_g * 1) / 16;
577 error_buffer[br_idx].b += (error_b * 1) / 16;
578 }
579 }
580 }
581
582 return closest_color;
583}
void get_16color_rgb(uint8_t color_index, uint8_t *r, uint8_t *g, uint8_t *b)
Definition ansi.c:480
int b
Definition ansi.h:66
int g
Definition ansi.h:65
int r
Definition ansi.h:64

References rgb_error_t::b, rgb_error_t::g, get_16color_rgb(), rgb_error_t::r, and rgb_to_16color().

Referenced by image_print_16color_dithered(), and image_print_16color_dithered_with_background().

◆ rgb_to_256color()

uint8_t rgb_to_256color ( uint8_t  r,
uint8_t  g,
uint8_t  b 
)

#include <ansi.h>

Convert RGB to closest 256-color palette index Uses 6x6x6 color cube + grayscale ramp

Parameters
rRed component
gGreen component
bBlue component
Returns
256-color palette index (0-255)

Definition at line 360 of file ansi.c.

360 {
361 // Map to 6x6x6 color cube (216 colors) + grayscale ramp
362
363 // Check if it's close to grayscale
364 int avg = (r + g + b) / 3;
365 int gray_diff = abs(r - avg) + abs(g - avg) + abs(b - avg);
366
367 if (gray_diff < 30) {
368 // Use grayscale ramp (colors 232-255)
369 int gray_level = (avg * 23) / 255;
370 return (uint8_t)(232 + gray_level);
371 }
372
373 // Use 6x6x6 color cube (colors 16-231)
374 int r6 = (r * 5) / 255;
375 int g6 = (g * 5) / 255;
376 int b6 = (b * 5) / 255;
377
378 return (uint8_t)(16 + (r6 * 36) + (g6 * 6) + b6);
379}

Referenced by append_color_fg_for_mode(), colorscheme_compile_scheme(), image_print_256color(), and rgb_to_256color_halfblocks_scalar().