|
|
@ -1,59 +1,84 @@
|
|
|
|
#include "internal.h"
|
|
|
|
#include "internal.h"
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
static inline void
|
|
|
|
// monochromatic blitter for testing
|
|
|
|
break_sixel_comps(unsigned char comps[static 3], uint32_t rgba){
|
|
|
|
static inline int
|
|
|
|
comps[0] = ncpixel_r(rgba) * 100 / 255;
|
|
|
|
sixel_blit(ncplane* nc, int placey, int placex, int linesize,
|
|
|
|
comps[1] = ncpixel_g(rgba) * 100 / 255;
|
|
|
|
const void* data, int begy, int begx,
|
|
|
|
comps[2] = ncpixel_b(rgba) * 100 / 255;
|
|
|
|
int leny, int lenx, bool blendcolors){
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct colortable {
|
|
|
|
|
|
|
|
int colors;
|
|
|
|
|
|
|
|
unsigned char table[3 * 256];
|
|
|
|
|
|
|
|
} colortable;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// returns the index at which the provided color can be found, possibly
|
|
|
|
|
|
|
|
// inserting it into the table. returns -1 if the color is not in the
|
|
|
|
|
|
|
|
// table and the table is full.
|
|
|
|
|
|
|
|
// FIXME switch to binary search, duh
|
|
|
|
|
|
|
|
// FIXME replace all these 3s with sizeof(comps)
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
|
|
|
find_color(colortable* ctab, unsigned char comps[static 3]){
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i = 0 ; i < ctab->colors ; ++i){
|
|
|
|
|
|
|
|
int cmp = memcmp(ctab->table + i * 3, comps, 3);
|
|
|
|
|
|
|
|
if(cmp == 0){
|
|
|
|
|
|
|
|
return i;
|
|
|
|
|
|
|
|
}else if(cmp > 0){
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ctab->colors == sizeof(ctab->table) / 3){
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(i < ctab->colors){
|
|
|
|
|
|
|
|
memmove(ctab->table + (i + 1) * 3, ctab->table + i * 3, (ctab->colors - i) * 3);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(ctab->table + i * 3, comps, 3);
|
|
|
|
|
|
|
|
++ctab->colors;
|
|
|
|
|
|
|
|
return i;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// rather inelegant preprocess of the entire image. colors are converted to the
|
|
|
|
|
|
|
|
// 100x100x100 sixel colorspace, and built into a table. if there are more than
|
|
|
|
|
|
|
|
// 255 converted colors, we (currently) reject it FIXME. ideally we'd do the
|
|
|
|
|
|
|
|
// image piecemeal, allowing us to get complete color fidelity; barring that,
|
|
|
|
|
|
|
|
// we'd have something sensibly quantize us down first FIXME. we ought do
|
|
|
|
|
|
|
|
// everything in a single pass FIXME.
|
|
|
|
|
|
|
|
// what do we do if every pixel is transparent (0 colors)? FIXME
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
|
|
|
extract_color_table(ncplane* nc, const uint32_t* data, int placey, int placex,
|
|
|
|
|
|
|
|
int linesize, int begy, int begx, int leny, int lenx,
|
|
|
|
|
|
|
|
colortable* ctab){
|
|
|
|
int dimy, dimx, x, y;
|
|
|
|
int dimy, dimx, x, y;
|
|
|
|
int total = 0; // number of cells written
|
|
|
|
|
|
|
|
ncplane_dim_yx(nc, &dimy, &dimx);
|
|
|
|
ncplane_dim_yx(nc, &dimy, &dimx);
|
|
|
|
int visy = begy;
|
|
|
|
int visy = begy;
|
|
|
|
for(y = placey ; visy < (begy + leny) && y < dimy ; ++y, visy += 6){
|
|
|
|
for(y = placey ; visy < (begy + leny) && y < dimy ; ++y, visy += 6){
|
|
|
|
if(ncplane_cursor_move_yx(nc, y, placex)){
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int visx = begx;
|
|
|
|
int visx = begx;
|
|
|
|
for(x = placex ; visx < (begx + lenx) && x < dimx ; ++x, visx += 1){
|
|
|
|
for(x = placex ; visx < (begx + lenx) && x < dimx ; ++x, visx += 1){
|
|
|
|
char sixel[128];
|
|
|
|
|
|
|
|
unsigned bitsused = 0; // once 63, we're done
|
|
|
|
|
|
|
|
for(int sy = visy ; sy < dimy && sy < visy + 6 ; ++sy){
|
|
|
|
for(int sy = visy ; sy < dimy && sy < visy + 6 ; ++sy){
|
|
|
|
const uint32_t* rgb = (const uint32_t*)(data + (linesize * sy) + (visx * 4));
|
|
|
|
const uint32_t* rgb = (const uint32_t*)(data + (linesize * sy) + (visx * 4));
|
|
|
|
if(rgba_trans_p(ncpixel_a(*rgb))){
|
|
|
|
if(rgba_trans_p(ncpixel_a(*rgb))){
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bitsused |= (1u << (sy - visy));
|
|
|
|
unsigned char comps[3];
|
|
|
|
}
|
|
|
|
break_sixel_comps(comps, *rgb);
|
|
|
|
nccell* c = ncplane_cell_ref_yx(nc, y, x);
|
|
|
|
if(find_color(ctab, comps) < 0){
|
|
|
|
int n = snprintf(sixel, sizeof(sixel), "#1;2;100;100;100#1%c", bitsused + 63);
|
|
|
|
|
|
|
|
if(n){
|
|
|
|
|
|
|
|
if(pool_blit_direct(&nc->pool, c, sixel, n, 1) <= 0){
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // FIXME otherwise, reset?
|
|
|
|
|
|
|
|
cell_set_pixels(c, 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(void)blendcolors; // FIXME
|
|
|
|
|
|
|
|
return total;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
|
|
|
|
break_sixel_comps(unsigned char comps[static 3], uint32_t rgba){
|
|
|
|
|
|
|
|
comps[0] = ncpixel_r(rgba) * 100 / 255;
|
|
|
|
|
|
|
|
comps[1] = ncpixel_g(rgba) * 100 / 255;
|
|
|
|
|
|
|
|
comps[2] = ncpixel_b(rgba) * 100 / 255;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Sixel blitter. Sixels are stacks 6 pixels high, and 1 pixel wide. RGB colors
|
|
|
|
// Sixel blitter. Sixels are stacks 6 pixels high, and 1 pixel wide. RGB colors
|
|
|
|
// are programmed as a set of registers, which are then referenced by the
|
|
|
|
// are programmed as a set of registers, which are then referenced by the
|
|
|
|
// stacks. There is also a RLE component, handled in rasterization.
|
|
|
|
// stacks. There is also a RLE component, handled in rasterization.
|
|
|
|
// A pixel block is indicated by setting cell_pixels_p().
|
|
|
|
// A pixel block is indicated by setting cell_pixels_p().
|
|
|
|
int sixel_blit(ncplane* nc, int placey, int placex, int linesize,
|
|
|
|
int sixel_blit_inner(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, bool blendcolors){
|
|
|
|
int leny, int lenx, colortable* ctab){
|
|
|
|
int dimy, dimx, x, y;
|
|
|
|
int dimy, dimx, x, y;
|
|
|
|
int total = 0; // number of cells written
|
|
|
|
int total = 0; // number of cells written
|
|
|
|
ncplane_dim_yx(nc, &dimy, &dimx);
|
|
|
|
ncplane_dim_yx(nc, &dimy, &dimx);
|
|
|
@ -124,8 +149,27 @@ int sixel_blit(ncplane* nc, int placey, int placex, int linesize,
|
|
|
|
free(sixel);
|
|
|
|
free(sixel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(void)blendcolors; // FIXME
|
|
|
|
|
|
|
|
return total;
|
|
|
|
return total;
|
|
|
|
#undef GROWTHFACTOR
|
|
|
|
#undef GROWTHFACTOR
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sixel_blit(ncplane* nc, int placey, int placex, int linesize,
|
|
|
|
|
|
|
|
const void* data, int begy, int begx,
|
|
|
|
|
|
|
|
int leny, int lenx, bool blendcolors){
|
|
|
|
|
|
|
|
(void)blendcolors; // FIXME
|
|
|
|
|
|
|
|
colortable* ctab = malloc(sizeof(*ctab));
|
|
|
|
|
|
|
|
if(ctab == NULL){
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ctab->colors = 0;
|
|
|
|
|
|
|
|
memset(ctab->table, 0xff, 3);
|
|
|
|
|
|
|
|
if(extract_color_table(nc, data, placey, placex, linesize,
|
|
|
|
|
|
|
|
begy, begx, leny, lenx, ctab)){
|
|
|
|
|
|
|
|
free(ctab);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int r = sixel_blit_inner(nc, placey, placex, linesize, data,
|
|
|
|
|
|
|
|
begy, begx, leny, lenx, ctab);
|
|
|
|
|
|
|
|
free(ctab);
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
|
|
|
}
|
|
|
|