Three SIXEL improvements from nincsnevem662 at gmail dot com in GitHub issue

4149:

- Pass P2 on the received image through when forwarding the image to the
  outside terminal to preserve transparency;

- Preserve raster attribute dimensions which may be smaller than the actual
  image (used to crop out parts of the image to work around the limitation that
  rows must come in groups of six);

- To avoid collapsing empty sixel lines, no longer ignore duplicate "-" new
  line specifiers.
This commit is contained in:
Nicholas Marriott 2024-10-04 07:49:07 +01:00
parent 2df15ad08c
commit 7a78cdf78c
3 changed files with 39 additions and 8 deletions

View File

@ -37,8 +37,13 @@ struct sixel_image {
u_int xpixel;
u_int ypixel;
u_int set_ra;
u_int ra_x;
u_int ra_y;
u_int *colours;
u_int ncolours;
u_int p2;
u_int dx;
u_int dy;
@ -166,6 +171,10 @@ sixel_parse_attributes(struct sixel_image *si, const char *cp, const char *end)
si->x = x;
sixel_parse_expand_lines(si, y);
si->set_ra = 1;
si->ra_x = x;
si->ra_y = y;
return (last);
}
@ -268,7 +277,7 @@ sixel_parse_repeat(struct sixel_image *si, const char *cp, const char *end)
}
struct sixel_image *
sixel_parse(const char *buf, size_t len, u_int xpixel, u_int ypixel)
sixel_parse(const char *buf, size_t len, u_int p2, u_int xpixel, u_int ypixel)
{
struct sixel_image *si;
const char *cp = buf, *end = buf + len;
@ -282,6 +291,7 @@ sixel_parse(const char *buf, size_t len, u_int xpixel, u_int ypixel)
si = xcalloc (1, sizeof *si);
si->xpixel = xpixel;
si->ypixel = ypixel;
si->p2 = p2;
while (cp != end) {
ch = *cp++;
@ -423,6 +433,18 @@ sixel_scale(struct sixel_image *si, u_int xpixel, u_int ypixel, u_int ox,
new = xcalloc (1, sizeof *si);
new->xpixel = xpixel;
new->ypixel = ypixel;
new->p2 = si->p2;
new->set_ra = si->set_ra;
/* clamp to slice end */
new->ra_x = si->ra_x < psx ? si->ra_x : psx;
new->ra_y = si->ra_y < psy ? si->ra_y : psy;
/* subtract slice origin */
new->ra_x = new->ra_x > pox ? new->ra_x - pox : 0;
new->ra_y = new->ra_y > poy ? new->ra_y - poy : 0;
/* resize */
new->ra_x = new->ra_x * xpixel / si->xpixel;
new->ra_y = new->ra_y * ypixel / si->ypixel;
for (y = 0; y < tsy; y++) {
py = poy + ((double)y * psy / tsy);
@ -497,11 +519,15 @@ sixel_print(struct sixel_image *si, struct sixel_image *map, size_t *size)
len = 8192;
buf = xmalloc(len);
sixel_print_add(&buf, &len, &used, "\033Pq", 3);
tmplen = xsnprintf(tmp, sizeof tmp, "\"1;1;%u;%u", si->x, si->y);
tmplen = xsnprintf(tmp, sizeof tmp, "\033P0;%uq", si->p2);
sixel_print_add(&buf, &len, &used, tmp, tmplen);
if (si->set_ra) {
tmplen = xsnprintf(tmp, sizeof tmp, "\"1;1;%u;%u", si->ra_x,
si->ra_y);
sixel_print_add(&buf, &len, &used, tmp, tmplen);
}
for (i = 0; i < ncolours; i++) {
c = colours[i];
tmplen = xsnprintf(tmp, sizeof tmp, "#%u;%u;%u;%u;%u",
@ -552,8 +578,7 @@ sixel_print(struct sixel_image *si, struct sixel_image *map, size_t *size)
if (buf[used - 1] == '$')
used--;
if (buf[used - 1] != '-')
sixel_print_add(&buf, &len, &used, "-", 1);
sixel_print_add(&buf, &len, &used, "-", 1);
}
if (buf[used - 1] == '$' || buf[used - 1] == '-')
used--;

View File

@ -2320,6 +2320,7 @@ input_dcs_dispatch(struct input_ctx *ictx)
#ifdef ENABLE_SIXEL
struct window *w;
struct sixel_image *si;
int p2;
#endif
if (wp == NULL)
@ -2333,7 +2334,12 @@ input_dcs_dispatch(struct input_ctx *ictx)
#ifdef ENABLE_SIXEL
w = wp->window;
if (buf[0] == 'q') {
si = sixel_parse(buf, len, w->xpixel, w->ypixel);
if (input_split(ictx) != 0)
return (0);
p2 = input_get(ictx, 1, 0, 0);
if (p2 == -1)
p2 = 0;
si = sixel_parse(buf, len, p2, w->xpixel, w->ypixel);
if (si != NULL)
screen_write_sixelimage(sctx, si, ictx->cell.cell.bg);
}

2
tmux.h
View File

@ -3493,7 +3493,7 @@ int image_scroll_up(struct screen *, u_int);
/* image-sixel.c */
#define SIXEL_COLOUR_REGISTERS 1024
struct sixel_image *sixel_parse(const char *, size_t, u_int, u_int);
struct sixel_image *sixel_parse(const char *, size_t, u_int, u_int, u_int);
void sixel_free(struct sixel_image *);
void sixel_log(struct sixel_image *);
void sixel_size_in_cells(struct sixel_image *, u_int *, u_int *);