diff --git a/src/lib/sixel.c b/src/lib/sixel.c index ba727826d..2c929cb79 100644 --- a/src/lib/sixel.c +++ b/src/lib/sixel.c @@ -1,17 +1,18 @@ #include "internal.h" +#define RGBSIZE 3 +// FIXME you can have more (or fewer) than 256 registers...detect? +#define MAXCOLORS 256 +#define CENTSIZE (RGBSIZE + 2) // size of a color table entry + static inline void -break_sixel_comps(unsigned char comps[static 3], uint32_t rgba, unsigned char mask){ +break_sixel_comps(unsigned char comps[static RGBSIZE], uint32_t rgba, unsigned char mask){ comps[0] = (ncpixel_r(rgba) & mask) * 100 / 255; comps[1] = (ncpixel_g(rgba) & mask) * 100 / 255; comps[2] = (ncpixel_b(rgba) & mask) * 100 / 255; //fprintf(stderr, "%u %u %u\n", comps[0], comps[1], comps[2]); } -// FIXME you can have more (or fewer) than 256 registers...detect? -#define MAXCOLORS 256 -#define CENTSIZE 5 // size of a color table entry - // first pass: extract up to 256 sixelspace colors over arbitrarily many sixels // sixelspace is 0..100 corresponding to 0..255, lame =[ typedef struct colortable { @@ -20,10 +21,16 @@ typedef struct colortable { unsigned char table[CENTSIZE * MAXCOLORS]; // components + dtable index } colortable; +typedef struct cdetails { + uint32_t sums[3]; + int32_t count; +} cdetails; + // second pass: construct data for extracted colors over the sixels typedef struct sixeltable { colortable* ctab; unsigned char* data; // |colors|x|sixelcount|-byte arrays + cdetails* deets; // |colors| } sixeltable; static inline int @@ -40,9 +47,8 @@ dtable_to_ctable(int dtable, unsigned char* ctable){ // returns the index at which the provided color can be found *in the // dtable*, possibly inserting it into the ctable. returns -1 if the // color is not in the table and the table is full. -// FIXME replace all these 3s static int -find_color(colortable* ctab, unsigned char comps[static 3]){ +find_color(colortable* ctab, unsigned char comps[static RGBSIZE]){ int i; if(ctab->colors){ int l, r; @@ -51,7 +57,7 @@ find_color(colortable* ctab, unsigned char comps[static 3]){ do{ i = l + (r - l) / 2; //fprintf(stderr, "%02x%02x%02x L %d R %d m %d\n", comps[0], comps[1], comps[2], l, r, i); - int cmp = memcmp(ctab->table + i * CENTSIZE, comps, 3); + int cmp = memcmp(ctab->table + i * CENTSIZE, comps, RGBSIZE); if(cmp == 0){ return ctable_to_dtable(ctab->table + i * CENTSIZE); } @@ -73,13 +79,15 @@ find_color(colortable* ctab, unsigned char comps[static 3]){ return -1; } if(i < ctab->colors){ +//fprintf(stderr, "INSERTING COLOR %u %u %u AT %d\n", comps[0], comps[1], comps[2], i); memmove(ctab->table + (i + 1) * CENTSIZE, ctab->table + i * CENTSIZE, (ctab->colors - i) * CENTSIZE); } }else{ i = 0; } - memcpy(ctab->table + i * CENTSIZE, comps, 3); +//fprintf(stderr, "NEW COLOR CONCAT %u %u %u AT %d\n", comps[0], comps[1], comps[2], i); + memcpy(ctab->table + i * CENTSIZE, comps, RGBSIZE); dtable_to_ctable(ctab->colors, ctab->table + i * CENTSIZE); ++ctab->colors; return ctab->colors - 1; @@ -99,7 +107,7 @@ extract_ctable_inner(const uint32_t* data, int linesize, int begy, int begx, if(rgba_trans_p(ncpixel_a(*rgb))){ continue; } - unsigned char comps[3]; + unsigned char comps[RGBSIZE]; break_sixel_comps(comps, *rgb, mask); int c = find_color(stab->ctab, comps); if(c < 0){ @@ -107,7 +115,12 @@ extract_ctable_inner(const uint32_t* data, int linesize, int begy, int begx, return -1; } stab->data[c * stab->ctab->sixelcount + pos] |= (1u << (sy - visy)); + stab->deets[c].sums[0] += ncpixel_r(*rgb); + stab->deets[c].sums[1] += ncpixel_g(*rgb); + stab->deets[c].sums[2] += ncpixel_b(*rgb); + ++stab->deets[c].count; //fprintf(stderr, "color %d pos %d: 0x%x\n", c, pos, stab->data[c * stab->ctab->sixelcount + pos]); +//fprintf(stderr, " sums: %u %u %u count: %d r/g/b: %u %u %u\n", stab->deets[c].sums[0], stab->deets[c].sums[1], stab->deets[c].sums[2], stab->deets[c].count, ncpixel_r(*rgb), ncpixel_g(*rgb), ncpixel_b(*rgb)); } ++pos; } @@ -119,6 +132,7 @@ static inline void initialize_stable(sixeltable* stab){ stab->ctab->colors = 0; memset(stab->data, 0, stab->ctab->sixelcount * MAXCOLORS); + memset(stab->deets, 0, sizeof(*stab->deets) * MAXCOLORS); } // Use as many of the original colors as we can, but not more than will fit @@ -181,7 +195,13 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab){ for(int i = 0 ; i < stab->ctab->colors ; ++i){ const unsigned char* rgb = stab->ctab->table + i * CENTSIZE; - fprintf(fp, "#%d;2;%u;%u;%u", i, rgb[0], rgb[1], rgb[2]); + int idx = ctable_to_dtable(rgb); + int count = stab->deets[idx].count; +//fprintf(stderr, "RGB: %3u %3u %3u DT: %d SUMS: %3d %3d %3d COUNT: %d\n", rgb[0], rgb[1], rgb[2], idx, stab->deets[idx].sums[0] / count * 100 / 255, stab->deets[idx].sums[1] / count * 100 / 255, stab->deets[idx].sums[2] / count * 100 / 255, count); +//fprintf(fp, "#%d;2;%u;%u;%u", i, rgb[0], rgb[1], rgb[2]); + fprintf(fp, "#%d;2;%u;%u;%u", i, stab->deets[idx].sums[0] / count * 100 / 255, + stab->deets[idx].sums[1] / count * 100 / 255, + stab->deets[idx].sums[2] / count * 100 / 255); } int p = 0; while(p < stab->ctab->sixelcount){ @@ -269,8 +289,11 @@ int sixel_blit(ncplane* nc, int placey, int placex, int linesize, sixeltable stable = { .ctab = ctab, .data = malloc(MAXCOLORS * ctab->sixelcount), + .deets = malloc(MAXCOLORS * sizeof(cdetails)), }; - if(stable.data == NULL){ + if(stable.data == NULL || stable.deets == NULL){ + free(stable.deets); + free(stable.data); free(ctab); return -1; } @@ -278,10 +301,12 @@ int sixel_blit(ncplane* nc, int placey, int placex, int linesize, if(extract_color_table(data, linesize, begy, begx, leny, lenx, &stable, &mask)){ free(ctab); free(stable.data); + free(stable.deets); return -1; } int r = sixel_blit_inner(nc, placey, placex, lenx, &stable, cellpixx); free(stable.data); + free(stable.deets); free(ctab); return r; }