From fdeff5cc974594e91adfb6bccb9e6b632fb4228f Mon Sep 17 00:00:00 2001 From: nick black Date: Fri, 26 Feb 2021 01:53:11 -0500 Subject: [PATCH] first go at sixel blitter #200 --- src/lib/blit.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/src/lib/blit.c b/src/lib/blit.c index 3cae86ec4..b52c790a9 100644 --- a/src/lib/blit.c +++ b/src/lib/blit.c @@ -853,7 +853,53 @@ sixel_blit(ncplane* nc, int placey, int placex, int linesize, return -1; } int visx = begx; - for(x = placex ; visx < (begx + lenx) && x < dimx ; ++x, visx += 2){ + for(x = placex ; visx < (begx + lenx) && x < dimx ; ++x, visx += 1){ + size_t offset = 0; + char sixel[128]; // FIXME + // FIXME find sixels with common colors for single register program + unsigned bitsused = 0; // once 63, we're done + int colorreg = 1; // leave 0 as background + for(int sy = y ; sy < dimy && sy < y + 6 ; ++sy){ + const uint32_t* rgb = (const uint32_t*)(data + (linesize * sy) + (visx * 4)); + if(ffmpeg_trans_p(ncpixel_a(*rgb))){ + continue; + } + if(bitsused & (1u << (sy - y))){ + continue; + } + unsigned thesebits = 1u << (sy - y); + for(int ty = sy + 1 ; ty < dimy && ty < y + 6 ; ++ty){ + const uint32_t* trgb = (const uint32_t*)(data + (linesize * ty) + (visx * 4)); + if(!ffmpeg_trans_p(ncpixel_a(*trgb))){ + if(memcmp(rgb + 1, trgb + 1, 3) == 0){ + thesebits |= (1u << (ty - y)); + } + } + } + if(thesebits){ + bitsused |= thesebits; + char c = 63 + thesebits; + // FIXME use percentages(rgb) + // bitstring is added to 63, resulting in [63, 126] aka '?'..'~' + int n = snprintf(sixel + offset, sizeof(sixel) - offset, + "#%d;2;%d;%d;%d%c", colorreg, 100, 100, 100, c); + if(n < 0){ + return -1; + } + offset += n; + ++colorreg; + } + if(bitsused == 63){ + break; + } + } + if(offset){ + nccell* c = ncplane_cell_ref_yx(nc, y, x); + if(pool_blit_direct(&nc->pool, c, sixel, offset, 1) <= 0){ + return -1; + } + cell_set_pixels(c); + } // FIXME otherwise, reset? } } return total; @@ -876,7 +922,7 @@ static const struct blitset notcurses_blitters[] = { .blit = tria_blit, .name = "fourstep", .fill = false, }, { .geom = NCBLIT_BRAILLE, .width = 2, .height = 4, .egcs = L"⠀⢀⢠⢰⢸⡀⣀⣠⣰⣸⡄⣄⣤⣴⣼⡆⣆⣦⣶⣾⡇⣇⣧⣷⣿", .blit = braille_blit, .name = "braille", .fill = true, }, - { .geom = NCBLIT_PIXEL, .width = 2, .height = 6, .egcs = L"", + { .geom = NCBLIT_PIXEL, .width = 1, .height = 6, .egcs = L"", .blit = sixel_blit, .name = "pixel", .fill = true, }, { .geom = 0, .width = 0, .height = 0, .egcs = NULL, .blit = NULL, .name = NULL, .fill = false, }, @@ -973,6 +1019,14 @@ const struct blitset* lookup_blitset(const tinfo* tcache, ncblitter_e setid, boo return NULL; } } + // without pixel support, NCBLIT_PIXEL decays to NCBLIT_3x2 + if(!tcache->pixelon && setid == NCBLIT_PIXEL){ + if(may_degrade){ + setid = NCBLIT_3x2; + }else{ + return NULL; + } + } // without sextant support, NCBLIT_3x2 decays to NCBLIT_2x2 if(!tcache->sextants && setid == NCBLIT_3x2){ if(may_degrade){