From 3818f0b31fce63967b285974992c69603c6309b2 Mon Sep 17 00:00:00 2001 From: nick black Date: Mon, 8 Mar 2021 23:10:00 -0500 Subject: [PATCH] kitty: get graphics protocol syntactic #1095 --- src/lib/kitty.c | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/src/lib/kitty.c b/src/lib/kitty.c index 2358f5d2f..777047f45 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -1,33 +1,54 @@ #include "internal.h" +static unsigned const char b64subs[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + // we can only write 4KiB at a time static int write_kitty_data(FILE* fp, int linesize, int leny, int lenx, const uint32_t* data){ +#define KITTY_MAXLEN 4096 // 4096B maximum payload if(linesize % sizeof(*data)){ return -1; } - // FIXME must write m=1 for initial chunks, m=0 for final (assuming > 1) - fprintf(fp, "\e_Gf=24,s=%d,v=%d;", lenx, leny); - // FIXME need to base64 encode payload. each 3B RGB goes to a 4B base64 - for(int y = 0 ; y < leny ; ++y){ - const uint32_t* line = data + (linesize / sizeof(*data)) * y; - for(int x = 0 ; x < lenx ; ++x){ + int total = leny * lenx * 4; // 3B RGB -> 4B Base64, total bytes + int chunks = (total + (KITTY_MAXLEN - 1)) / KITTY_MAXLEN; + int totalout = 0; // total bytes of payload out + int y = 0; + int x = 0; + int targetout = 0; +//fprintf(stderr, "total: %d chunks = %d, s=%d,v=%d\n", total, chunks, lenx, leny); + while(chunks--){ + if(totalout == 0){ + fprintf(fp, "\e_Gf=24,s=%d,v=%d,a=T%s;", lenx, leny, chunks > 1 ? ",m=1" : ""); + }else{ + fprintf(fp, "\e_Gm=%d;", chunks ? 1 : 0); + } + if((targetout += KITTY_MAXLEN) > total){ + targetout = total; + } + while(totalout < targetout){ + if(x == lenx){ + x = 0; + ++y; + } + const uint32_t* line = data + (linesize / sizeof(*data)) * y; uint32_t pixel = line[x]; unsigned r = ncpixel_r(pixel); unsigned g = ncpixel_g(pixel); unsigned b = ncpixel_b(pixel); unsigned char b64[4] = { - ((r & 0xfc) >> 2) + 'A', - ((r & 0x3 << 2) | ((g & 0xf0) >> 4)) + 'A', - (((g & 0xf) << 2) | ((b & 0xc0) >> 6)) + 'A', - (b & 0x3f) + 'A' + b64subs[((r & 0xfc) >> 2)], + b64subs[((r & 0x3 << 2) | ((g & 0xf0) >> 4))], + b64subs[(((g & 0xf) << 2) | ((b & 0xc0) >> 6))], + b64subs[(b & 0x3f)] }; -// this isn't the correct base64 distribution FIXME -fprintf(stderr, "%u/%u/%u -> %c%c%c%c %u %u %u %u\n", r, g, b, b64[0], b64[1], b64[2], b64[3], b64[0], b64[1], b64[2], b64[3]); +//fprintf(stderr, "%u/%u/%u -> %c%c%c%c %u %u %u %u\n", r, g, b, b64[0], b64[1], b64[2], b64[3], b64[0], b64[1], b64[2], b64[3]); fprintf(fp, "%c%c%c%c", b64[0], b64[1], b64[2], b64[3]); + totalout += 4; + ++x; } + fprintf(fp, "\e\\"); } - fprintf(fp, "\e\\"); if(fclose(fp) == EOF){ return -1; } @@ -65,6 +86,7 @@ int kitty_blit(ncplane* nc, int placey, int placex, int linesize, int leny, int lenx, unsigned cellpixx){ (void)begy; (void)begx; +//fprintf(stderr, "s=%d,v=%d\n", lenx, leny); int r = kitty_blit_inner(nc, placey, placex, linesize, leny, lenx, cellpixx, data); if(r < 0){ return -1;