sixel: if the client has specified a size, do not change that

We used to auto-resize images to always be a multiple of 6.

This is incorrect. The client may, for example, have specified a size
to align the image to a cell boundary, which may not be a multiple of
6.

Furthermore, in e.g. Jexer, which splits up an image into stripes,
that the next image would "overwrite" the previous one. Since the next
image was started on a cell row that the previous image had overflowed
into.
This commit is contained in:
Daniel Eklöf 2020-06-11 18:40:52 +02:00
parent 957e482f45
commit dec796f525
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 20 additions and 6 deletions

View file

@ -63,7 +63,9 @@
a `;`.
* Palette re-use in sixel images. Previously, the palette was reset
after each image.
* Do not auto-resize a sixel image for which the cllent has specified
a size. This fixes an issue where an image would incorrectly
overflow into the cell row beneath.
### Security

21
sixel.c
View file

@ -41,6 +41,7 @@ sixel_init(struct terminal *term)
term->sixel.image.data = malloc(1 * 6 * sizeof(term->sixel.image.data[0]));
term->sixel.image.width = 1;
term->sixel.image.height = 6;
term->sixel.image.autosize = true;
if (term->sixel.palette == NULL) {
term->sixel.palette = calloc(
@ -212,6 +213,9 @@ max_height(const struct terminal *term)
static bool
resize(struct terminal *term, int new_width, int new_height)
{
if (!term->sixel.image.autosize)
return false;
LOG_DBG("resizing image: %dx%d -> %dx%d",
term->sixel.image.width, term->sixel.image.height,
new_width, new_height);
@ -220,6 +224,11 @@ resize(struct terminal *term, int new_width, int new_height)
const int old_width = term->sixel.image.width;
const int old_height = term->sixel.image.height;
int alloc_new_width = new_width;
int alloc_new_height = (new_height + 6 - 1) / 6 * 6;
assert(alloc_new_height >= new_height);
assert(alloc_new_height - new_height < 6);
assert(new_width >= old_width);
assert(new_height >= old_height);
@ -229,7 +238,7 @@ resize(struct terminal *term, int new_width, int new_height)
/* Width (and thus stride) is the same, so we can simply
* re-alloc the existing buffer */
new_data = realloc(old_data, new_width * new_height * sizeof(uint32_t));
new_data = realloc(old_data, alloc_new_width * alloc_new_height * sizeof(uint32_t));
if (new_data == NULL) {
LOG_ERRNO("failed to reallocate sixel image buffer");
return false;
@ -240,7 +249,7 @@ resize(struct terminal *term, int new_width, int new_height)
} else {
/* Width (and thus stride) change - need to allocate a new buffer */
assert(new_width > old_width);
new_data = malloc(new_width * new_height * sizeof(uint32_t));
new_data = malloc(alloc_new_width * alloc_new_height * sizeof(uint32_t));
/* Copy old rows, and initialize new columns to background color */
for (int r = 0; r < old_height; r++) {
@ -278,7 +287,7 @@ sixel_add(struct terminal *term, uint32_t color, uint8_t sixel)
}
if (term->sixel.pos.col >= term->sixel.image.width ||
term->sixel.pos.row * 6 + 5 >= term->sixel.image.height)
term->sixel.pos.row * 6 + 5 >= (term->sixel.image.height + 6 - 1) / 6 * 6)
{
int width = max(
term->sixel.image.width,
@ -288,7 +297,8 @@ sixel_add(struct terminal *term, uint32_t color, uint8_t sixel)
term->sixel.image.height,
(term->sixel.pos.row + 1) * 6);
resize(term, width, height);
if (!resize(term, width, height))
return;
}
for (int i = 0; i < 6; i++, sixel >>= 1) {
@ -389,7 +399,8 @@ decgra(struct terminal *term, uint8_t c)
if (ph >= term->sixel.image.height && pv >= term->sixel.image.width &&
ph <= max_height(term) && pv <= max_width(term))
{
resize(term, ph, pv);
if (resize(term, ph, pv))
term->sixel.image.autosize = false;
}
term->sixel.state = SIXEL_DECSIXEL;

View file

@ -416,6 +416,7 @@ struct terminal {
uint32_t *data; /* Raw image data, in ARGB */
int width; /* Image width, in pixels */
int height; /* Image height, in pixels */
bool autosize;
} image;
unsigned params[5]; /* Collected parmaeters, for RASTER, COLOR_SPEC */