19static char color256_strings[256][16];
20static bool color256_initialized =
false;
180 if (color256_initialized)
183 for (
int i = 0; i < 256; i++) {
184 SAFE_SNPRINTF(color256_strings[i],
sizeof(color256_strings[i]),
"\033[38;5;%dm", i);
187 color256_initialized =
true;
192 const char *color_str = color256_strings[color_index];
193 size_t len = strlen(color_str);
203 int avg = (r + g + b) / 3;
204 int gray_diff = abs(r - avg) + abs(g - avg) + abs(b - avg);
206 if (gray_diff < 30) {
208 int gray_level = (avg * 23) / 255;
209 return (
uint8_t)(232 + gray_level);
213 int r6 = (r * 5) / 255;
214 int g6 = (g * 5) / 255;
215 int b6 = (b * 5) / 255;
217 return (
uint8_t)(16 + (r6 * 36) + (g6 * 6) + b6);
221static char color16_fg_strings[16][16];
222static char color16_bg_strings[16][16];
223static bool color16_initialized =
false;
226 if (color16_initialized)
230 const char *fg_codes[] = {
"30",
"31",
"32",
"33",
"34",
"35",
"36",
"37",
231 "90",
"91",
"92",
"93",
"94",
"95",
"96",
"97"};
232 const char *bg_codes[] = {
"40",
"41",
"42",
"43",
"44",
"45",
"46",
"47",
233 "100",
"101",
"102",
"103",
"104",
"105",
"106",
"107"};
235 for (
int i = 0; i < 16; i++) {
236 SAFE_SNPRINTF(color16_fg_strings[i],
sizeof(color16_fg_strings[i]),
"\033[%sm", fg_codes[i]);
237 SAFE_SNPRINTF(color16_bg_strings[i],
sizeof(color16_bg_strings[i]),
"\033[%sm", bg_codes[i]);
240 color16_initialized =
true;
244 if (!color16_initialized) {
248 if (color_index >= 16) {
252 const char *color_str = color16_fg_strings[color_index];
254 *dst++ = *color_str++;
261 if (!color16_initialized) {
265 if (color_index >= 16) {
269 const char *color_str = color16_bg_strings[color_index];
271 *dst++ = *color_str++;
282 static const uint8_t ansi_colors[16][3] = {
302 int min_distance = INT_MAX;
304 for (
int i = 0; i < 16; i++) {
305 int dr = (int)r - (
int)ansi_colors[i][0];
306 int dg = (int)g - (
int)ansi_colors[i][1];
307 int db = (int)b - (
int)ansi_colors[i][2];
308 int distance = dr * dr + dg * dg + db * db;
310 if (distance < min_distance) {
311 min_distance = distance;
322 static const uint8_t ansi_colors[16][3] = {
341 if (color_index >= 16) {
345 *r = ansi_colors[color_index][0];
346 *g = ansi_colors[color_index][1];
347 *b = ansi_colors[color_index][2];
355 size_t error_idx = (size_t)y * (
size_t)width + (size_t)x;
356 r += error_buffer[error_idx].
r;
357 g += error_buffer[error_idx].
g;
358 b += error_buffer[error_idx].
b;
361 error_buffer[error_idx].
r = 0;
362 error_buffer[error_idx].
g = 0;
363 error_buffer[error_idx].
b = 0;
367 uint8_t r_clamped = clamp_rgb((
int)r);
368 uint8_t g_clamped = clamp_rgb((
int)g);
369 uint8_t b_clamped = clamp_rgb((
int)b);
376 uint8_t actual_r, actual_g, actual_b;
379 int error_r = r - (int)actual_r;
380 int error_g = g - (int)actual_g;
381 int error_b = b - (int)actual_b;
390 size_t right_idx = (size_t)y * (
size_t)width + (size_t)(x + 1);
391 error_buffer[right_idx].
r += (error_r * 7) / 16;
392 error_buffer[right_idx].
g += (error_g * 7) / 16;
393 error_buffer[right_idx].
b += (error_b * 7) / 16;
397 if (y + 1 < height) {
400 size_t bl_idx = (size_t)(y + 1) * (size_t)width + (
size_t)(x - 1);
401 error_buffer[bl_idx].
r += (error_r * 3) / 16;
402 error_buffer[bl_idx].
g += (error_g * 3) / 16;
403 error_buffer[bl_idx].
b += (error_b * 3) / 16;
407 size_t bottom_idx = (size_t)(y + 1) * (size_t)width + (
size_t)x;
408 error_buffer[bottom_idx].
r += (error_r * 5) / 16;
409 error_buffer[bottom_idx].
g += (error_g * 5) / 16;
410 error_buffer[bottom_idx].
b += (error_b * 5) / 16;
414 size_t br_idx = (size_t)(y + 1) * (size_t)width + (
size_t)(x + 1);
415 error_buffer[br_idx].
r += (error_r * 1) / 16;
416 error_buffer[br_idx].
g += (error_g * 1) / 16;
417 error_buffer[br_idx].
b += (error_b * 1) / 16;
422 return closest_color;
Fast ANSI escape sequence generation.
SIMD-optimized ASCII conversion interface.
#define SAFE_SNPRINTF(buffer, buffer_size,...)
#define SAFE_MEMCPY(dest, dest_size, src, count)
#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.
global_dec3_cache_t g_dec3_cache
Global decimal cache instance.
char * append_16color_fg(char *dst, uint8_t color_index)
Append 16-color foreground ANSI sequence.
char * append_16color_bg(char *dst, uint8_t color_index)
Append 16-color background ANSI sequence.
char * append_truecolor_fg(char *dst, uint8_t r, uint8_t g, uint8_t b)
Append truecolor foreground ANSI sequence.
void ansi_fast_init_256color(void)
Initialize 256-color mode lookup tables.
uint8_t rgb_to_16color(uint8_t r, uint8_t g, uint8_t b)
Convert RGB to 16-color ANSI index.
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)
Convert RGB to 16-color with Floyd-Steinberg dithering.
ansi_color_mode_t
Color mode for ANSI generation.
void ansi_rle_init(ansi_rle_context_t *ctx, char *buffer, size_t capacity, ansi_color_mode_t mode)
Initialize run-length encoding context.
void ansi_fast_init(void)
Initialize the decimal lookup table.
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)
Append truecolor foreground and background ANSI sequence.
void ansi_rle_finish(ansi_rle_context_t *ctx)
Finish RLE sequence.
void get_16color_rgb(uint8_t color_index, uint8_t *r, uint8_t *g, uint8_t *b)
Get the actual RGB values for a 16-color ANSI index.
void ansi_rle_add_pixel(ansi_rle_context_t *ctx, uint8_t r, uint8_t g, uint8_t b, char ascii_char)
Add a pixel with run-length encoding.
char * append_256color_fg(char *dst, uint8_t color_index)
Append 256-color foreground ANSI sequence.
char * append_color_fg_for_mode(char *dst, uint8_t r, uint8_t g, uint8_t b, terminal_color_mode_t mode)
Append color foreground sequence for specified mode.
void ascii_simd_init(void)
Initialize SIMD subsystem.
uint8_t rgb_to_256color(uint8_t r, uint8_t g, uint8_t b)
Convert RGB to 256-color palette index.
void ansi_fast_init_16color(void)
Initialize 16-color mode lookup tables.
char * append_truecolor_bg(char *dst, uint8_t r, uint8_t g, uint8_t b)
Append truecolor background ANSI sequence.
@ ANSI_MODE_FOREGROUND_BACKGROUND
Application limits and constraints.
🔢 Mathematical Utility Functions
Run-length encoded color output context.
RGB error structure for dithering.
⏱️ High-precision timing utilities using sokol_time.h and uthash