From 51182e3315f1866d3c767eafccaf023fd6c1c2b7 Mon Sep 17 00:00:00 2001 From: nick black Date: Sat, 27 Mar 2021 14:23:52 -0400 Subject: [PATCH] [sixel] reproduce surgery map #1457 --- src/lib/kitty.c | 16 ++------- src/lib/render.c | 18 +---------- src/lib/sixel.c | 84 ++++++++++++++++++++++++++---------------------- 3 files changed, 50 insertions(+), 68 deletions(-) diff --git a/src/lib/kitty.c b/src/lib/kitty.c index 34837fe78..655b6532b 100644 --- a/src/lib/kitty.c +++ b/src/lib/kitty.c @@ -238,7 +238,6 @@ write_kitty_data(FILE* fp, int linesize, int leny, int lenx, int cols, int totalout = 0; // total pixels of payload out int y = 0; // position within source image (pixels) int x = 0; - int tyx = 0; // postition within tamatrix (cells) int targetout = 0; // number of pixels expected out after this chunk //fprintf(stderr, "total: %d chunks = %d, s=%d,v=%d\n", total, chunks, lenx, leny); while(chunks--){ @@ -261,26 +260,17 @@ write_kitty_data(FILE* fp, int linesize, int leny, int lenx, int cols, for(int e = 0 ; e < encodeable ; ++e){ if(x == lenx){ x = 0; - if(x % cdimx){ - ++tyx; - } - if(++y % cdimy){ - tyx -= cols; - } + ++y; } const uint32_t* line = data + (linesize / sizeof(*data)) * y; source[e] = line[x]; //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]); - if(++x % cdimx == 0){ - ++tyx; - } + ++x; + int tyx = (x / cdimx) + (y / cdimy) * cols; wipe[e] = (tacache[tyx] == SPRIXCELL_ANNIHILATED); } totalout += encodeable; char out[17]; -if(wipe[0] || wipe[1] || wipe[2]){ -fprintf(stderr, "TYX: %d lenx: %d y: %d x: %d %d %d %d\n", tyx, lenx, y, x, wipe[0], wipe[1], wipe[2]); -} base64_rgba3(source, encodeable, out, wipe); ncfputs(out, fp); } diff --git a/src/lib/render.c b/src/lib/render.c index be5e95c7e..30b81825b 100644 --- a/src/lib/render.c +++ b/src/lib/render.c @@ -926,23 +926,7 @@ int sprite_sixel_annihilate(const notcurses* nc, const ncpile* p, FILE* out, spr (void)p; (void)out; (void)s; - /* - struct crender* rvec = p->crender; - // FIXME need to cap by ends minus bottom, right margins also - const int ycap = nc->stdplane->leny + nc->margin_t; - const int xcap = nc->stdplane->lenx + nc->margin_l; -//fprintf(stderr, "yCAP: %d xCAP: %d\n", ycap, xcap); - for(int y = s->y + nc->stdplane->absy ; y < s->y + nc->stdplane->absy + s->dimy && y < ycap ; ++y){ - const int innery = y - nc->stdplane->absy; - for(int x = s->x + nc->stdplane->absx ; x < s->x + nc->stdplane->absx + s->dimx && x < xcap ; ++x){ - const int innerx = x - nc->stdplane->absx; - const size_t damageidx = innery * nc->lfdimx + innerx; -//fprintf(stderr, "DAMAGING %zu %d * %d + %d (max %d/%d)\n", damageidx, innery, nc->lfdimx, innerx, ycap, xcap); - rvec[damageidx].s.damaged = 1; - } - } - */ - return 1; + return 0; } // returns -1 on error, 0 on success, 1 on success + invalidations requiring diff --git a/src/lib/sixel.c b/src/lib/sixel.c index 8bf6386cd..465e7484b 100644 --- a/src/lib/sixel.c +++ b/src/lib/sixel.c @@ -245,18 +245,24 @@ update_deets(uint32_t rgb, cdetails* deets){ // (assumed to have at least 256 registers). at each color, we store a pixel // count, and a sum of all three channels. in addition, we track whether we've // seen at least two colors in the chunk. -static int -extract_color_table(const uint32_t* data, int linesize, int begy, int begx, - int leny, int lenx, sixeltable* stab){ +static inline int +extract_color_table(const uint32_t* data, int linesize, int begy, int begx, int cols, + int leny, int lenx, int cdimy, int cdimx, sixeltable* stab, + sprixcell_e* tacache){ unsigned char mask = 0xc0; int pos = 0; - for(int visy = begy ; visy < (begy + leny) ; visy += 6){ - for(int visx = begx ; visx < (begx + lenx) ; visx += 1){ - for(int sy = visy ; sy < (begy + leny) && sy < visy + 6 ; ++sy){ - const uint32_t* rgb = (const uint32_t*)(data + (linesize / 4 * sy) + visx); + for(int visy = begy ; visy < (begy + leny) ; visy += 6){ // pixel row + for(int visx = begx ; visx < (begx + lenx) ; visx += 1){ // pixel column + for(int sy = visy ; sy < (begy + leny) && sy < visy + 6 ; ++sy){ // offset within sprixel + const uint32_t* rgb = (data + (linesize / 4 * sy) + visx); if(rgba_trans_p(ncpixel_a(*rgb))){ continue; } + int txyidx = (sy / cdimy) * cols + (visx / cdimx); + if(tacache[txyidx] == SPRIXCELL_ANNIHILATED){ +//fprintf(stderr, "TRANS SKIP %d %d %d %d\n", visy, visx, sy, txyidx); + continue; + } unsigned char comps[RGBSIZE]; break_sixel_comps(comps, *rgb, mask); int c = find_color(stab, comps); @@ -416,7 +422,7 @@ write_rle(int* printed, int color, FILE* fp, int seenrle, unsigned char crle){ // Emit the sprixel in its entirety, plus enable and disable pixel mode. // Closes |fp| on all paths. static int -write_sixel_data(FILE* fp, int lenx, sixeltable* stab, int* parse_start, sprixcell_e* tacache){ +write_sixel_data(FILE* fp, int lenx, sixeltable* stab, int* parse_start){ *parse_start = fprintf(fp, "\ePq"); // Set Raster Attributes - pan/pad=1 (pixel aspect ratio), Ph=lenx, Pv=leny // using Ph/Pv causes a background to be drawn using color register 0 for all @@ -435,7 +441,6 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab, int* parse_start, sprixce (intmax_t)(stab->deets[idx].sums[2] * 100 / count / 255)); } int p = 0; - (void)tacache; // FIXME fill in tacache when we hit transparencies while(p < stab->sixelcount){ for(int i = 0 ; i < stab->colors ; ++i){ int printed = 0; @@ -486,8 +491,10 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab, int* parse_start, sprixce // are programmed as a set of registers, which are then referenced by the // stacks. There is also a RLE component, handled in rasterization. // A pixel block is indicated by setting cell_pixels_p(). -int sixel_blit_inner(ncplane* n, int leny, int lenx, sixeltable* stab, - const blitterargs* bargs){ +static inline int +sixel_blit_inner(ncplane* n, int leny, int lenx, sixeltable* stab, + const blitterargs* bargs, unsigned reuse, + sprixcell_e* tacache){ char* buf = NULL; size_t size = 0; FILE* fp = open_memstream(&buf, &size); @@ -497,31 +504,8 @@ int sixel_blit_inner(ncplane* n, int leny, int lenx, sixeltable* stab, int parse_start = 0; int cols = lenx / bargs->u.pixel.celldimx + !!(lenx % bargs->u.pixel.celldimx); int rows = leny / bargs->u.pixel.celldimy + !!(leny % bargs->u.pixel.celldimy); - sprixcell_e* tacache = NULL; - bool reuse = false; - // if we have a sprixel attached to this plane, see if we can reuse it - // (we need the same dimensions) and thus immediately apply its T-A table. - if(n->sprite){ - sprixel* s = n->sprite; - if(s->dimy == rows && s->dimx == cols){ - tacache = s->tacache; - reuse = true; - } - } - if(!reuse){ - tacache = malloc(sizeof(*tacache) * rows * cols); - if(tacache == NULL){ - fclose(fp); - free(buf); - return -1; - } - memset(tacache, 0, sizeof(*tacache) * rows * cols); - } // calls fclose() on success - if(write_sixel_data(fp, lenx, stab, &parse_start, tacache)){ - if(!reuse){ - free(tacache); - } + if(write_sixel_data(fp, lenx, stab, &parse_start)){ free(buf); return -1; } @@ -532,7 +516,6 @@ int sixel_blit_inner(ncplane* n, int leny, int lenx, sixeltable* stab, if(plane_blit_sixel(n, buf, size, bargs->placey, bargs->placex, rows, cols, bargs->u.pixel.sprixelid, leny, lenx, parse_start, tacache) < 0){ - free(tacache); free(buf); return -1; } @@ -567,14 +550,39 @@ int sixel_blit(ncplane* n, int linesize, const void* data, // stable.table doesn't need initializing; we start from the bottom memset(stable.data, 0, sixelcount * colorregs); memset(stable.deets, 0, sizeof(*stable.deets) * colorregs); - if(extract_color_table(data, linesize, bargs->begy, bargs->begx, leny, lenx, &stable)){ + int cols = lenx / bargs->u.pixel.celldimx + !!(lenx % bargs->u.pixel.celldimx); + int rows = leny / bargs->u.pixel.celldimy + !!(leny % bargs->u.pixel.celldimy); + sprixcell_e* tacache = NULL; + bool reuse = false; + // if we have a sprixel attached to this plane, see if we can reuse it + // (we need the same dimensions) and thus immediately apply its T-A table. + if(n->sprite){ + sprixel* s = n->sprite; + if(s->dimy == rows && s->dimx == cols){ + tacache = s->tacache; + reuse = true; + } + } + if(!reuse){ + tacache = malloc(sizeof(*tacache) * rows * cols); + if(tacache == NULL){ + return -1; + } + memset(tacache, 0, sizeof(*tacache) * rows * cols); + } + if(extract_color_table(data, linesize, bargs->begy, bargs->begx, cols, leny, lenx, + bargs->u.pixel.celldimy, bargs->u.pixel.celldimx, + &stable, tacache)){ + if(!reuse){ + free(tacache); + } free(stable.table); free(stable.data); free(stable.deets); return -1; } refine_color_table(data, linesize, bargs->begy, bargs->begx, leny, lenx, &stable); - int r = sixel_blit_inner(n, leny, lenx, &stable, bargs); + int r = sixel_blit_inner(n, leny, lenx, &stable, bargs, reuse, tacache); free(stable.data); free(stable.deets); free(stable.table);