sixel: merge color and sixeltables

pull/1409/head
nick black 4 years ago committed by Nick Black
parent 6debae3906
commit 0e0a074703

@ -13,13 +13,6 @@ break_sixel_comps(unsigned char comps[static RGBSIZE], uint32_t rgba, unsigned c
//fprintf(stderr, "%u %u %u\n", comps[0], comps[1], comps[2]); //fprintf(stderr, "%u %u %u\n", comps[0], comps[1], comps[2]);
} }
// first pass: extract up to 256 sixelspace colors over arbitrarily many sixels
// sixelspace is 0..100 corresponding to 0..255, lame =[
typedef struct colortable {
int colors;
unsigned char table[CENTSIZE * MAXCOLORS]; // components + dtable index
} colortable;
typedef struct cdetails { typedef struct cdetails {
int64_t sums[3]; int64_t sums[3];
int64_t count; int64_t count;
@ -27,9 +20,11 @@ typedef struct cdetails {
// second pass: construct data for extracted colors over the sixels // second pass: construct data for extracted colors over the sixels
typedef struct sixeltable { typedef struct sixeltable {
colortable* ctab; // FIXME keep these internal to palette extraction; finalize there
unsigned char* data; // |maxcolors|x|sixelcount|-byte arrays int colors;
cdetails* deets; // |maxcolors| cdetails structures cdetails* deets; // |maxcolors| cdetails structures
unsigned char* data; // |maxcolors| x |sixelcount|-byte arrays
unsigned char* table; // |maxcolors| x CENTSIZE: components + dtable index
int sixelcount; int sixelcount;
} sixeltable; } sixeltable;
@ -48,18 +43,18 @@ dtable_to_ctable(int dtable, unsigned char* ctable){
// dtable*, possibly inserting it into the ctable. returns -1 if the // dtable*, possibly inserting it into the ctable. returns -1 if the
// color is not in the table and the table is full. // color is not in the table and the table is full.
static int static int
find_color(colortable* ctab, unsigned char comps[static RGBSIZE]){ find_color(sixeltable* stab, unsigned char comps[static RGBSIZE]){
int i; int i;
if(ctab->colors){ if(stab->colors){
int l, r; int l, r;
l = 0; l = 0;
r = ctab->colors - 1; r = stab->colors - 1;
do{ do{
i = l + (r - l) / 2; 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); //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, RGBSIZE); int cmp = memcmp(stab->table + i * CENTSIZE, comps, RGBSIZE);
if(cmp == 0){ if(cmp == 0){
return ctable_to_dtable(ctab->table + i * CENTSIZE); return ctable_to_dtable(stab->table + i * CENTSIZE);
} }
if(cmp < 0){ if(cmp < 0){
l = i + 1; l = i + 1;
@ -70,28 +65,28 @@ find_color(colortable* ctab, unsigned char comps[static RGBSIZE]){
}while(l <= r); }while(l <= r);
if(r < 0){ if(r < 0){
i = 0; i = 0;
}else if(l == ctab->colors){ }else if(l == stab->colors){
i = ctab->colors; i = stab->colors;
}else{ }else{
i = l; i = l;
} }
if(ctab->colors == MAXCOLORS){ if(stab->colors == MAXCOLORS){
return -1; return -1;
} }
if(i < ctab->colors){ if(i < stab->colors){
//fprintf(stderr, "INSERTING COLOR %u %u %u AT %d\n", comps[0], comps[1], comps[2], i); //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, memmove(stab->table + (i + 1) * CENTSIZE, stab->table + i * CENTSIZE,
(ctab->colors - i) * CENTSIZE); (stab->colors - i) * CENTSIZE);
} }
}else{ }else{
i = 0; i = 0;
} }
//fprintf(stderr, "NEW COLOR CONCAT %u %u %u AT %d\n", comps[0], comps[1], comps[2], i); //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); memcpy(stab->table + i * CENTSIZE, comps, RGBSIZE);
dtable_to_ctable(ctab->colors, ctab->table + i * CENTSIZE); dtable_to_ctable(stab->colors, stab->table + i * CENTSIZE);
++ctab->colors; ++stab->colors;
return ctab->colors - 1; return stab->colors - 1;
//return ctable_to_dtable(ctab->table + i * CENTSIZE); //return ctable_to_dtable(stab->table + i * CENTSIZE);
} }
// rather inelegant preprocess of the entire image. colors are converted to the // rather inelegant preprocess of the entire image. colors are converted to the
@ -109,7 +104,7 @@ extract_ctable_inner(const uint32_t* data, int linesize, int begy, int begx,
} }
unsigned char comps[RGBSIZE]; unsigned char comps[RGBSIZE];
break_sixel_comps(comps, *rgb, mask); break_sixel_comps(comps, *rgb, mask);
int c = find_color(stab->ctab, comps); int c = find_color(stab, comps);
if(c < 0){ if(c < 0){
//fprintf(stderr, "FAILED FINDING COLOR AUGH 0x%02x\n", mask); //fprintf(stderr, "FAILED FINDING COLOR AUGH 0x%02x\n", mask);
return -1; return -1;
@ -128,21 +123,15 @@ extract_ctable_inner(const uint32_t* data, int linesize, int begy, int begx,
return 0; return 0;
} }
static inline void
initialize_stable(sixeltable* stab){
stab->ctab->colors = 0;
memset(stab->data, 0, stab->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 // Use as many of the original colors as we can, but not more than will fit
// into the set of color registers. We're already losing some precision by the // into the set of color registers. We're already losing some precision by the
// RGB -> sixelspace conversion (256->100); try with the complete colors, and // RGB -> sixelspace conversion (256->100); try with the complete colors, and
// progressively mask more out until they all fit. // progressively mask more out until they all fit.
static int static inline int
extract_color_table(const uint32_t* data, int linesize, int begy, int begx, extract_color_table(const uint32_t* data, int linesize, int begy, int begx,
int leny, int lenx, sixeltable* stab){ int leny, int lenx, sixeltable* stab){
initialize_stable(stab); memset(stab->data, 0, stab->sixelcount * MAXCOLORS);
memset(stab->deets, 0, sizeof(*stab->deets) * MAXCOLORS);
if(extract_ctable_inner(data, linesize, begy, begx, leny, lenx, stab, 0xc0) == 0){ if(extract_ctable_inner(data, linesize, begy, begx, leny, lenx, stab, 0xc0) == 0){
return 0; return 0;
} }
@ -188,8 +177,8 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab){
// unspecified pixels, which we do not want. // unspecified pixels, which we do not want.
//fprintf(fp, "\"1;1;%d;%d", lenx, leny); //fprintf(fp, "\"1;1;%d;%d", lenx, leny);
for(int i = 0 ; i < stab->ctab->colors ; ++i){ for(int i = 0 ; i < stab->colors ; ++i){
const unsigned char* rgb = stab->ctab->table + i * CENTSIZE; const unsigned char* rgb = stab->table + i * CENTSIZE;
int idx = ctable_to_dtable(rgb); int idx = ctable_to_dtable(rgb);
int count = stab->deets[idx].count; 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(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);
@ -201,11 +190,11 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab){
} }
int p = 0; int p = 0;
while(p < stab->sixelcount){ while(p < stab->sixelcount){
for(int i = 0 ; i < stab->ctab->colors ; ++i){ for(int i = 0 ; i < stab->colors ; ++i){
int printed = 0; int printed = 0;
int seenrle = 0; // number of repetitions int seenrle = 0; // number of repetitions
unsigned char crle = 0; // character being repeated unsigned char crle = 0; // character being repeated
int idx = ctable_to_dtable(stab->ctab->table + i * CENTSIZE); int idx = ctable_to_dtable(stab->table + i * CENTSIZE);
for(int m = p ; m < stab->sixelcount && m < p + lenx ; ++m){ for(int m = p ; m < stab->sixelcount && m < p + lenx ; ++m){
//fprintf(stderr, "%d ", idx * stab->sixelcount + m); //fprintf(stderr, "%d ", idx * stab->sixelcount + m);
//fputc(stab->data[idx * stab->sixelcount + m] + 63, stderr); //fputc(stab->data[idx * stab->sixelcount + m] + 63, stderr);
@ -225,7 +214,7 @@ write_sixel_data(FILE* fp, int lenx, sixeltable* stab){
if(crle){ if(crle){
write_rle(&printed, i, fp, seenrle, crle); write_rle(&printed, i, fp, seenrle, crle);
} }
if(i + 1 < stab->ctab->colors){ if(i + 1 < stab->colors){
if(printed){ if(printed){
fputc('$', fp); fputc('$', fp);
} }
@ -277,25 +266,22 @@ int sixel_blit_inner(ncplane* nc, int placey, int placex, int lenx,
int sixel_blit(ncplane* nc, int placey, int placex, int linesize, int sixel_blit(ncplane* nc, int placey, int placex, int linesize,
const void* data, int begy, int begx, const void* data, int begy, int begx,
int leny, int lenx, unsigned cellpixx){ int leny, int lenx, unsigned cellpixx){
colortable* ctab = malloc(sizeof(*ctab));
if(ctab == NULL){
return -1;
}
int sixelcount = (lenx - begx) * ((leny - begy + 5) / 6); int sixelcount = (lenx - begx) * ((leny - begy + 5) / 6);
sixeltable stable = { sixeltable stable = {
.ctab = ctab,
.data = malloc(MAXCOLORS * sixelcount), .data = malloc(MAXCOLORS * sixelcount),
.deets = malloc(MAXCOLORS * sizeof(cdetails)), .deets = malloc(MAXCOLORS * sizeof(cdetails)),
.table = malloc(MAXCOLORS * CENTSIZE),
.sixelcount = sixelcount, .sixelcount = sixelcount,
.colors = 0,
}; };
if(stable.data == NULL || stable.deets == NULL){ if(stable.data == NULL || stable.deets == NULL || stable.table == NULL){
free(stable.table);
free(stable.deets); free(stable.deets);
free(stable.data); free(stable.data);
free(ctab);
return -1; return -1;
} }
if(extract_color_table(data, linesize, begy, begx, leny, lenx, &stable)){ if(extract_color_table(data, linesize, begy, begx, leny, lenx, &stable)){
free(ctab); free(stable.table);
free(stable.data); free(stable.data);
free(stable.deets); free(stable.deets);
return -1; return -1;
@ -303,6 +289,6 @@ int sixel_blit(ncplane* nc, int placey, int placex, int linesize,
int r = sixel_blit_inner(nc, placey, placex, lenx, &stable, cellpixx); int r = sixel_blit_inner(nc, placey, placex, lenx, &stable, cellpixx);
free(stable.data); free(stable.data);
free(stable.deets); free(stable.deets);
free(ctab); free(stable.table);
return r; return r;
} }

Loading…
Cancel
Save