mirror of
https://github.com/tmux/tmux.git
synced 2026-08-28 17:41:35 +00:00
Dither alpha in SIXEL output
This commit is contained in:
@@ -1033,10 +1033,10 @@ sixel_from_image(struct image *im, u_int ox, u_int oy, u_int cells_x,
|
||||
const u_char *pixel;
|
||||
uint16_t *cache;
|
||||
int *current, *next, *tmp;
|
||||
int red_error, green_error, blue_error;
|
||||
int red_error, green_error, blue_error, alpha_error;
|
||||
u_int x, y, sx, sy, index, error_index;
|
||||
u_int sourcex0, sourcey0, sourcewidth, sourceheight;
|
||||
u_int red, green, blue, colour, i, ncolours;
|
||||
u_int red, green, blue, alpha, colour, i, ncolours;
|
||||
uint64_t destination_width, destination_height;
|
||||
uint64_t content_width, content_height, x0, x1, y0, y1;
|
||||
|
||||
@@ -1078,7 +1078,7 @@ sixel_from_image(struct image *im, u_int ox, u_int oy, u_int cells_x,
|
||||
for (x = 0; x < sx; x++) {
|
||||
pixel = sixel_from_image_pixel(&source, sourcex0, sourcey0,
|
||||
sourcewidth, sourceheight, sx, sy, x, y);
|
||||
if (pixel[3] < 128)
|
||||
if (pixel[3] == 0)
|
||||
continue;
|
||||
index = ((pixel[0] >> 3) << 10)|
|
||||
((pixel[1] >> 3) << 5)|(pixel[2] >> 3);
|
||||
@@ -1112,46 +1112,55 @@ sixel_from_image(struct image *im, u_int ox, u_int oy, u_int cells_x,
|
||||
|
||||
cache = xmalloc(SIXEL_HISTOGRAM_SIZE * sizeof *cache);
|
||||
memset(cache, 0xff, SIXEL_HISTOGRAM_SIZE * sizeof *cache);
|
||||
current = xcalloc(((size_t)sx + 2) * 3, sizeof *current);
|
||||
next = xcalloc(((size_t)sx + 2) * 3, sizeof *next);
|
||||
current = xcalloc(((size_t)sx + 2) * 4, sizeof *current);
|
||||
next = xcalloc(((size_t)sx + 2) * 4, sizeof *next);
|
||||
for (y = 0; y < sy; y++) {
|
||||
for (x = 0; x < sx; x++) {
|
||||
pixel = sixel_from_image_pixel(&source, sourcex0, sourcey0,
|
||||
sourcewidth, sourceheight, sx, sy, x, y);
|
||||
if (pixel[3] < 128)
|
||||
continue;
|
||||
error_index = (x + 1) * 3;
|
||||
red = sixel_clamp_colour((int)pixel[0] +
|
||||
current[error_index] / 16);
|
||||
green = sixel_clamp_colour((int)pixel[1] +
|
||||
current[error_index + 1] / 16);
|
||||
blue = sixel_clamp_colour((int)pixel[2] +
|
||||
current[error_index + 2] / 16);
|
||||
colour = sixel_nearest_colour(palette, ncolours, cache,
|
||||
red, green, blue);
|
||||
if (sixel_set_pixel(si, x, y, colour + 1) != 0)
|
||||
goto fail;
|
||||
error_index = (x + 1) * 4;
|
||||
/* SIXEL pixels are binary, so dither alpha separately. */
|
||||
alpha = sixel_clamp_colour((int)pixel[3] +
|
||||
current[error_index + 3] / 16);
|
||||
alpha_error = (int)alpha;
|
||||
if (alpha >= 128) {
|
||||
alpha_error -= 255;
|
||||
red = sixel_clamp_colour((int)pixel[0] +
|
||||
current[error_index] / 16);
|
||||
green = sixel_clamp_colour((int)pixel[1] +
|
||||
current[error_index + 1] / 16);
|
||||
blue = sixel_clamp_colour((int)pixel[2] +
|
||||
current[error_index + 2] / 16);
|
||||
colour = sixel_nearest_colour(palette, ncolours, cache,
|
||||
red, green, blue);
|
||||
if (sixel_set_pixel(si, x, y, colour + 1) != 0)
|
||||
goto fail;
|
||||
|
||||
red_error = (int)red - palette[colour].red;
|
||||
green_error = (int)green - palette[colour].green;
|
||||
blue_error = (int)blue - palette[colour].blue;
|
||||
current[error_index + 3] += red_error * 7;
|
||||
current[error_index + 4] += green_error * 7;
|
||||
current[error_index + 5] += blue_error * 7;
|
||||
next[error_index - 3] += red_error * 3;
|
||||
next[error_index - 2] += green_error * 3;
|
||||
next[error_index - 1] += blue_error * 3;
|
||||
next[error_index] += red_error * 5;
|
||||
next[error_index + 1] += green_error * 5;
|
||||
next[error_index + 2] += blue_error * 5;
|
||||
next[error_index + 3] += red_error;
|
||||
next[error_index + 4] += green_error;
|
||||
next[error_index + 5] += blue_error;
|
||||
red_error = (int)red - palette[colour].red;
|
||||
green_error = (int)green - palette[colour].green;
|
||||
blue_error = (int)blue - palette[colour].blue;
|
||||
current[error_index + 4] += red_error * 7;
|
||||
current[error_index + 5] += green_error * 7;
|
||||
current[error_index + 6] += blue_error * 7;
|
||||
next[error_index - 4] += red_error * 3;
|
||||
next[error_index - 3] += green_error * 3;
|
||||
next[error_index - 2] += blue_error * 3;
|
||||
next[error_index] += red_error * 5;
|
||||
next[error_index + 1] += green_error * 5;
|
||||
next[error_index + 2] += blue_error * 5;
|
||||
next[error_index + 4] += red_error;
|
||||
next[error_index + 5] += green_error;
|
||||
next[error_index + 6] += blue_error;
|
||||
}
|
||||
current[error_index + 7] += alpha_error * 7;
|
||||
next[error_index - 1] += alpha_error * 3;
|
||||
next[error_index + 3] += alpha_error * 5;
|
||||
next[error_index + 7] += alpha_error;
|
||||
}
|
||||
tmp = current;
|
||||
current = next;
|
||||
next = tmp;
|
||||
memset(next, 0, ((size_t)sx + 2) * 3 * sizeof *next);
|
||||
memset(next, 0, ((size_t)sx + 2) * 4 * sizeof *next);
|
||||
}
|
||||
free(current);
|
||||
free(next);
|
||||
|
||||
Reference in New Issue
Block a user