example/std-imagedumper: use Unicode half-blocks
diff --git a/example/stb-imagedumper/stb-imagedumper.c b/example/stb-imagedumper/stb-imagedumper.c
index df4d584..b0c0167 100644
--- a/example/stb-imagedumper/stb-imagedumper.c
+++ b/example/stb-imagedumper/stb-imagedumper.c
@@ -645,11 +645,11 @@
 
 #define MAX_INCL_DIMENSION 10000
 
-// BYTES_PER_COLOR_PIXEL is long enough to contain "\x1B[38;2;255;255;255mABC"
-// plus a trailing NUL byte and a few bytes of slack. It starts with a true
-// color terminal escape code. ABC is three bytes for the UTF-8 representation
-// "\xE2\x96\x88" of "█", U+2588 FULL BLOCK.
-#define BYTES_PER_COLOR_PIXEL 32
+// BYTES_PER_COLOR_OUTPUT_CHARACTER is long enough to contain
+// "\x1B[38;2;255;255;255m\x1B[48;2;255;255;255mABC" plus a trailing NUL byte.
+// It starts with a true color terminal escape code. ABC is three bytes for the
+// UTF-8 representation "\xE2\x96\x80" of "▀", U+2580 UPPER HALF BLOCK.
+#define BYTES_PER_COLOR_OUTPUT_CHARACTER 42
 
 static void  //
 handle(const char* filename,
@@ -697,14 +697,17 @@
     return;
   }
 
-  static char buffer[MAX_INCL_DIMENSION * BYTES_PER_COLOR_PIXEL];
+  // The +16 is some slack for a new-line and ANSI reset code.
+  static char
+      buffer[(MAX_INCL_DIMENSION * BYTES_PER_COLOR_OUTPUT_CHARACTER) + 16];
+
   if (g_flags.ascii_art) {
     unsigned char* src = pixels;
     for (int y = 0; y < h; y++) {
       char* dst = buffer;
       for (int x = 0; x < w; x++) {
         *dst++ = "-:=+IOX@"[(src[0] & 0xff) >> 5];
-        src += bytes_per_pixel;
+        src++;
       }
       *dst++ = '\n';
       fwrite(buffer, sizeof(char), dst - buffer, stdout);
@@ -742,21 +745,36 @@
 
   } else {
     unsigned char* src = pixels;
-    for (int y = 0; y < h; y++) {
+    for (int y = 0; y < h; y += 2) {
       char* dst = buffer;
       for (int x = 0; x < w; x++) {
-        // "\xE2\x96\x88" is U+2588 FULL BLOCK. Before that is a true color
-        // terminal escape code.
-        dst += sprintf(dst, "\x1B[38;2;%d;%d;%dm\xE2\x96\x88",  //
-                       (uint8_t)src[0], (uint8_t)src[1], (uint8_t)src[2]);
-        src += bytes_per_pixel;
+        // "\xE2\x96\x80" is U+2588 UPPER HALF BLOCK. Before that is a true
+        // color terminal escape code for foreground and background color, to
+        // dump two pixels per output character.
+        uint8_t upper0 = (uint8_t)src[0];
+        uint8_t upper1 = (uint8_t)src[1];
+        uint8_t upper2 = (uint8_t)src[2];
+        if ((y + 1) >= h) {
+          dst += sprintf(dst, "\x1B[38;2;%d;%d;%dm\xE2\x96\x80",  //
+                         upper0, upper1, upper2);
+        } else {
+          uint8_t lower0 = (uint8_t)src[(w * 3) + 0];
+          uint8_t lower1 = (uint8_t)src[(w * 3) + 1];
+          uint8_t lower2 = (uint8_t)src[(w * 3) + 2];
+          dst +=
+              sprintf(dst,
+                      "\x1B[38;2;%d;%d;%dm\x1B[48;2;%d;%d;%dm\xE2\x96\x80",  //
+                      upper0, upper1, upper2, lower0, lower1, lower2);
+        }
+        src += 3;
       }
-      *dst++ = '\n';
+      memcpy(dst, "\x1B[0m\n", 5);
+      dst += 5;
       fwrite(buffer, sizeof(char), dst - buffer, stdout);
+      if ((y + 1) < h) {
+        src += w * 3;
+      }
     }
-    const char* reset_color_str = "\x1B[0m";
-    const size_t reset_color_len = 4;
-    fwrite(reset_color_str, sizeof(char), reset_color_len, stdout);
   }
 
   fflush(stdout);