Browse Source

Use ANSI terminal colors for term demos

rexim 2 years ago
parent
commit
fa647120a3
1 changed files with 335 additions and 21 deletions
  1. 335 21
      demos/vc.c

+ 335 - 21
demos/vc.c

@@ -151,28 +151,294 @@ defer:
 #include <errno.h>
 #include <errno.h>
 #include <time.h>
 #include <time.h>
 #include <unistd.h>
 #include <unistd.h>
+#include <math.h>
+
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+#include "stb_image_write.h"
 
 
 static size_t vc_term_actual_width = 0;
 static size_t vc_term_actual_width = 0;
 static size_t vc_term_actual_height = 0;
 static size_t vc_term_actual_height = 0;
 static size_t vc_term_scaled_down_width = 0;
 static size_t vc_term_scaled_down_width = 0;
 static size_t vc_term_scaled_down_height = 0;
 static size_t vc_term_scaled_down_height = 0;
-static char *vc_term_char_canvas = 0;
+static int *vc_term_char_canvas = 0;
+static uint32_t *vc_term_char_canvas_debug = 0;
+
+int hsl256[][3] = {
+    {0, 0, 0},
+    {0, 100, 25},
+    {120, 100, 25},
+    {60, 100, 25},
+    {240, 100, 25},
+    {300, 100, 25},
+    {180, 100, 25},
+    {0, 0, 75},
+    {0, 0, 50},
+    {0, 100, 50},
+    {120, 100, 50},
+    {60, 100, 50},
+    {240, 100, 50},
+    {300, 100, 50},
+    {180, 100, 50},
+    {0, 0, 100},
+    {0, 0, 0},
+    {240, 99, 18},
+    {240, 100, 26},
+    {240, 100, 34},
+    {240, 100, 42},
+    {240, 100, 50},
+    {120, 99, 18},
+    {180, 99, 18},
+    {197, 100, 26},
+    {207, 100, 34},
+    {213, 100, 42},
+    {217, 100, 50},
+    {120, 100, 26},
+    {162, 100, 26},
+    {180, 100, 26},
+    {193, 100, 34},
+    {202, 100, 42},
+    {208, 100, 50},
+    {120, 100, 34},
+    {152, 100, 34},
+    {166, 100, 34},
+    {180, 100, 34},
+    {191, 100, 42},
+    {198, 100, 50},
+    {120, 100, 42},
+    {146, 100, 42},
+    {157, 100, 42},
+    {168, 100, 42},
+    {180, 100, 42},
+    {189, 100, 50},
+    {120, 100, 50},
+    {142, 100, 50},
+    {151, 100, 50},
+    {161, 100, 50},
+    {170, 100, 50},
+    {180, 100, 50},
+    {0, 99, 18},
+    {300, 99, 18},
+    {282, 100, 26},
+    {272, 100, 34},
+    {266, 100, 42},
+    {262, 100, 50},
+    {60, 99, 18},
+    {0, 0, 37},
+    {240, 17, 45},
+    {240, 33, 52},
+    {240, 60, 60},
+    {240, 100, 68},
+    {77, 100, 26},
+    {120, 17, 45},
+    {180, 17, 45},
+    {210, 33, 52},
+    {220, 60, 60},
+    {225, 100, 68},
+    {87, 100, 34},
+    {120, 33, 52},
+    {150, 33, 52},
+    {180, 33, 52},
+    {200, 60, 60},
+    {210, 100, 68},
+    {93, 100, 42},
+    {120, 60, 60},
+    {140, 60, 60},
+    {160, 60, 60},
+    {180, 60, 60},
+    {195, 100, 68},
+    {97, 100, 50},
+    {120, 100, 68},
+    {135, 100, 68},
+    {150, 100, 68},
+    {165, 100, 68},
+    {180, 100, 68},
+    {0, 100, 26},
+    {317, 100, 26},
+    {300, 100, 26},
+    {286, 100, 34},
+    {277, 100, 42},
+    {271, 100, 50},
+    {42, 100, 26},
+    {0, 17, 45},
+    {300, 17, 45},
+    {270, 33, 52},
+    {260, 60, 60},
+    {255, 100, 68},
+    {60, 100, 26},
+    {60, 17, 45},
+    {0, 0, 52},
+    {240, 20, 60},
+    {240, 50, 68},
+    {240, 100, 76},
+    {73, 100, 34},
+    {90, 33, 52},
+    {120, 20, 60},
+    {180, 20, 60},
+    {210, 50, 68},
+    {220, 100, 76},
+    {82, 100, 42},
+    {100, 60, 60},
+    {120, 50, 68},
+    {150, 50, 68},
+    {180, 50, 68},
+    {200, 100, 76},
+    {88, 100, 50},
+    {105, 100, 68},
+    {120, 100, 76},
+    {140, 100, 76},
+    {160, 100, 76},
+    {180, 100, 76},
+    {0, 100, 34},
+    {327, 100, 34},
+    {313, 100, 34},
+    {300, 100, 34},
+    {288, 100, 42},
+    {281, 100, 50},
+    {32, 100, 34},
+    {0, 33, 52},
+    {330, 33, 52},
+    {300, 33, 52},
+    {280, 60, 60},
+    {270, 100, 68},
+    {46, 100, 34},
+    {30, 33, 52},
+    {0, 20, 60},
+    {300, 20, 60},
+    {270, 50, 68},
+    {260, 100, 76},
+    {60, 100, 34},
+    {60, 33, 52},
+    {60, 20, 60},
+    {0, 0, 68},
+    {240, 33, 76},
+    {240, 100, 84},
+    {71, 100, 42},
+    {80, 60, 60},
+    {90, 50, 68},
+    {120, 33, 76},
+    {180, 33, 76},
+    {210, 100, 84},
+    {78, 100, 50},
+    {90, 100, 68},
+    {100, 100, 76},
+    {120, 100, 84},
+    {150, 100, 84},
+    {180, 100, 84},
+    {0, 100, 42},
+    {333, 100, 42},
+    {322, 100, 42},
+    {311, 100, 42},
+    {300, 100, 42},
+    {290, 100, 50},
+    {26, 100, 42},
+    {0, 60, 60},
+    {340, 60, 60},
+    {320, 60, 60},
+    {300, 60, 60},
+    {285, 100, 68},
+    {37, 100, 42},
+    {20, 60, 60},
+    {0, 50, 68},
+    {330, 50, 68},
+    {300, 50, 68},
+    {280, 100, 76},
+    {48, 100, 42},
+    {40, 60, 60},
+    {30, 50, 68},
+    {0, 33, 76},
+    {300, 33, 76},
+    {270, 100, 84},
+    {60, 100, 42},
+    {60, 60, 60},
+    {60, 50, 68},
+    {60, 33, 76},
+    {0, 0, 84},
+    {240, 100, 92},
+    {69, 100, 50},
+    {75, 100, 68},
+    {80, 100, 76},
+    {90, 100, 84},
+    {120, 100, 92},
+    {180, 100, 92},
+    {0, 100, 50},
+    {337, 100, 50},
+    {328, 100, 50},
+    {318, 100, 50},
+    {309, 100, 50},
+    {300, 100, 50},
+    {22, 100, 50},
+    {0, 100, 68},
+    {345, 100, 68},
+    {330, 100, 68},
+    {315, 100, 68},
+    {300, 100, 68},
+    {31, 100, 50},
+    {15, 100, 68},
+    {0, 100, 76},
+    {340, 100, 76},
+    {320, 100, 76},
+    {300, 100, 76},
+    {41, 100, 50},
+    {30, 100, 68},
+    {20, 100, 76},
+    {0, 100, 84},
+    {330, 100, 84},
+    {300, 100, 84},
+    {50, 100, 50},
+    {45, 100, 68},
+    {40, 100, 76},
+    {30, 100, 84},
+    {0, 100, 92},
+    {300, 100, 92},
+    {60, 100, 50},
+    {60, 100, 68},
+    {60, 100, 76},
+    {60, 100, 84},
+    {60, 100, 92},
+    {0, 0, 100},
+    {0, 0, 3},
+    {0, 0, 7},
+    {0, 0, 10},
+    {0, 0, 14},
+    {0, 0, 18},
+    {0, 0, 22},
+    {0, 0, 26},
+    {0, 0, 30},
+    {0, 0, 34},
+    {0, 0, 38},
+    {0, 0, 42},
+    {0, 0, 46},
+    {0, 0, 50},
+    {0, 0, 54},
+    {0, 0, 58},
+    {0, 0, 61},
+    {0, 0, 65},
+    {0, 0, 69},
+    {0, 0, 73},
+    {0, 0, 77},
+    {0, 0, 81},
+    {0, 0, 85},
+    {0, 0, 89},
+    {0, 0, 93},
+};
+
+int distance_hsl256(int i, int h, int s, int l)
+{
+    int dh = h - hsl256[i][0];
+    int ds = s - hsl256[i][1];
+    int dl = l - hsl256[i][2];
+    return dh*dh + ds*ds + dl*dl;
+}
 
 
-// TODO: use ANSI terminal colors for color_to_char
-static char vc_term_color_to_char(uint32_t pixel)
+int find_ansi_index_by_hsl(int h, int s, int l)
 {
 {
-    size_t r = OLIVEC_RED(pixel);
-    size_t g = OLIVEC_GREEN(pixel);
-    size_t b = OLIVEC_BLUE(pixel);
-    size_t a = OLIVEC_ALPHA(pixel);
-    size_t bright = r;
-    if (bright < g) bright = g;
-    if (bright < b) bright = b;
-    bright = bright*a/255;
-
-    char table[] = " .:a@#";
-    size_t n = sizeof(table) - 1;
-    return table[bright*n/256];
+    int index = 0;
+    for (int i = 0; i < 256; ++i) {
+        if (distance_hsl256(i, h, s, l) < distance_hsl256(index, h, s, l)) {
+            index = i;
+        }
+    }
+    return index;
 }
 }
 
 
 static uint32_t vc_term_compress_pixels_chunk(Olivec_Canvas oc)
 static uint32_t vc_term_compress_pixels_chunk(Olivec_Canvas oc)
@@ -216,6 +482,39 @@ static void vc_term_resize_char_canvas(size_t new_width, size_t new_height)
     free(vc_term_char_canvas);
     free(vc_term_char_canvas);
     vc_term_char_canvas = malloc(sizeof(*vc_term_char_canvas)*vc_term_scaled_down_width*vc_term_scaled_down_height);
     vc_term_char_canvas = malloc(sizeof(*vc_term_char_canvas)*vc_term_scaled_down_width*vc_term_scaled_down_height);
     assert(vc_term_char_canvas != NULL && "Just buy more RAM");
     assert(vc_term_char_canvas != NULL && "Just buy more RAM");
+    vc_term_char_canvas_debug = malloc(sizeof(*vc_term_char_canvas_debug)*vc_term_scaled_down_width*vc_term_scaled_down_height);
+    assert(vc_term_char_canvas_debug != NULL && "Just buy more RAM");
+}
+
+void rgb_to_hsl(int r, int g, int b, int *h, int *s, int *l)
+{
+    float r01 = r/255.0f;
+    float g01 = g/255.0f;
+    float b01 = b/255.0f;
+    float cmax = r01;
+    if (g01 > cmax) cmax = g01;
+    if (b01 > cmax) cmax = b01;
+    float cmin = r01;
+    if (g01 < cmin) cmin = g01;
+    if (b01 < cmin) cmin = b01;
+    float delta = cmax - cmin;
+    float epsilon = 1e-6;
+    float hf = 0;
+    if (delta < epsilon) hf = 0;
+    else if (cmax == r01) hf = 60.0f*fmod((g01 - b01)/delta, 6.0f);
+    else if (cmax == g01) hf = 60.0f*((b01 - r01)/delta + 2);
+    else if (cmax == b01) hf = 60.0f*((r01 - g01)/delta + 4);
+    else assert(0 && "unreachable");
+
+    float lf = (cmax + cmin)/2;
+
+    float sf = 0;
+    if (delta < epsilon) sf = 0;
+    else sf = delta/(1 - fabsf(2*lf - 1));
+
+    *h = fmodf(fmodf(hf, 360.0f) + 360.0f, 360.0f);
+    *s = sf*100.0f;
+    *l = lf*100.0f;
 }
 }
 
 
 static void vc_term_compress_pixels(Olivec_Canvas oc)
 static void vc_term_compress_pixels(Olivec_Canvas oc)
@@ -226,11 +525,24 @@ static void vc_term_compress_pixels(Olivec_Canvas oc)
 
 
     for (size_t y = 0; y < vc_term_scaled_down_height; ++y) {
     for (size_t y = 0; y < vc_term_scaled_down_height; ++y) {
         for (size_t x = 0; x < vc_term_scaled_down_width; ++x) {
         for (size_t x = 0; x < vc_term_scaled_down_width; ++x) {
-            Olivec_Canvas soc = olivec_subcanvas(oc, x*VC_TERM_SCALE_DOWN_FACTOR, y*VC_TERM_SCALE_DOWN_FACTOR, VC_TERM_SCALE_DOWN_FACTOR,
-VC_TERM_SCALE_DOWN_FACTOR);
-            vc_term_char_canvas[y*vc_term_scaled_down_width + x] = vc_term_color_to_char(vc_term_compress_pixels_chunk(soc));
+            Olivec_Canvas soc = olivec_subcanvas(oc, x*VC_TERM_SCALE_DOWN_FACTOR, y*VC_TERM_SCALE_DOWN_FACTOR, VC_TERM_SCALE_DOWN_FACTOR, VC_TERM_SCALE_DOWN_FACTOR);
+            uint32_t cp = vc_term_compress_pixels_chunk(soc);
+            int r = OLIVEC_RED(cp);
+            int g = OLIVEC_GREEN(cp);
+            int b = OLIVEC_BLUE(cp);
+            int a = OLIVEC_ALPHA(cp);
+            r = a*r/255;
+            g = a*g/255;
+            b = a*b/255;
+            int h, s, l;
+            rgb_to_hsl(r, g, b, &h, &s, &l);
+            vc_term_char_canvas[y*vc_term_scaled_down_width + x] = find_ansi_index_by_hsl(h, s, l);
+            vc_term_char_canvas_debug[y*vc_term_scaled_down_width + x] = cp;
         }
         }
     }
     }
+
+    // stbi_write_png("debug.png", vc_term_scaled_down_width, vc_term_scaled_down_height, 4, vc_term_char_canvas_debug, sizeof(uint32_t)*vc_term_scaled_down_width);
+    // exit(1);
 }
 }
 
 
 int main(void)
 int main(void)
@@ -241,11 +553,13 @@ int main(void)
             for (size_t x = 0; x < vc_term_scaled_down_width; ++x) {
             for (size_t x = 0; x < vc_term_scaled_down_width; ++x) {
                 // TODO: different halfs of the double pixels
                 // TODO: different halfs of the double pixels
                 // We can do stuff like putc('<', stdout); putc('>', stdout);
                 // We can do stuff like putc('<', stdout); putc('>', stdout);
-                putc(vc_term_char_canvas[y*vc_term_scaled_down_width + x], stdout);
-                putc(vc_term_char_canvas[y*vc_term_scaled_down_width + x], stdout);
+                // putc(vc_term_char_canvas[y*vc_term_scaled_down_width + x], stdout);
+                // putc(vc_term_char_canvas[y*vc_term_scaled_down_width + x], stdout);
+                printf("\033[48;5;%dm  ", vc_term_char_canvas[y*vc_term_scaled_down_width + x]);
                 // TODO: explore the idea of figuring out aspect ratio of the character using escape ANSI codes of the terminal and rendering the image accordingly
                 // TODO: explore the idea of figuring out aspect ratio of the character using escape ANSI codes of the terminal and rendering the image accordingly
             }
             }
-            putc('\n', stdout);
+            printf("\033[0m\n");
+            // putc('\n', stdout);
         }
         }
 
 
         usleep(1000*1000/60);
         usleep(1000*1000/60);