Files
tmux/regress/image-sixel-output.sh
Nicholas Marriott 1de5f662cb Image regress tests.
2026-10-14 12:44:53 +01:00

97 lines
3.7 KiB
Bash
Executable File

#!/bin/sh
# Check RGBA to SIXEL output, palette splitting, transparent edges, source
# clipping and repeated redraws at different terminal pixel sizes.
PATH=/bin:/usr/bin
TERM=screen
export TERM
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
python3 -B - "$TEST_TMUX" <<'PY'
import sys
from image_test import image_test, sixel, check_image
palette = [(100, 0, 0), (0, 100, 0), (0, 0, 100), (100, 100, 100)]
rgb = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 255)]
pixels = [2 * (y >= 16) + (x >= 8) for y in range(32) for x in range(16)]
expected = [rgb[c] for c in pixels]
wire = sixel(16, 32, palette, pixels)
with image_test(sys.argv[1]) as test:
client = test.attach()
test.emit(wire)
assert len(client.images()) == 1
check_image(client.images()[0], 16, 32, expected)
for _ in range(3):
test.redraw()
assert len(client.images()) == 1
check_image(client.images()[0], 16, 32, expected)
# Keep the stored cell footprint when terminal cell pixels change.
for cw, ch in [(16, 32), (12, 24), (12, 16)]:
test.resize(client, 40, 16, cw=cw, ch=ch)
w, h = cw * 2, ch * 2
scaled = [expected[(y * 32 // h) * 16 + x * 16 // w]
for y in range(h) for x in range(w)]
assert len(client.images()) == 1
check_image(client.images()[0], w, h, scaled)
test.resize(client, 40, 16)
check_image(client.images()[0], 16, 32, expected)
# Removing one grid cell crops the original source, retaining its colours.
test.emit(b'\033[HX')
images = client.images()
assert len(images) == 2, [im[:2] for im in images]
check_image(images[0], 8, 16, [rgb[1]] * (8 * 16))
check_image(images[1], 16, 16,
[rgb[2 + (x >= 8)] for y in range(16) for x in range(16)])
test.emit(b'\033[2J\033[H')
assert not client.images()
test.redraw()
assert not client.images()
# A partial last cell keeps its actual pixel size instead of stretching.
test.emit(sixel(26, 26, [(100, 100, 100)], [0] * (26 * 26)))
assert len(client.images()) == 1
check_image(client.images()[0], 26, 26, [rgb[3]] * (26 * 26))
# Transparent edges and holes must not acquire coloured pixels.
pixels = [None if x == 0 or y == 0 or x == 7 or y == 15 else 0
for y in range(16) for x in range(8)]
test.emit(b'\033[2J\033[H' + sixel(8, 16, palette[:1], pixels))
assert len(client.images()) == 1
check_image(client.images()[0], 8, 16,
[None if c is None else rgb[0] for c in pixels])
# A skewed histogram still splits into black, grey and white entries.
pixels = [0] * 10 + [1] * 10 + [2] * 80
test.emit(b'\033[2J\033[H' +
sixel(100, 1, [(0, 0, 0), (50, 50, 50), (100, 100, 100)], pixels))
assert len(client.images()) == 1
check_image(client.images()[0], 100, 1,
[(0, 0, 0)] * 10 + [(128, 128, 128)] * 10 + [rgb[3]] * 80)
# The right edge of a pane crops the source, rather than rescaling it.
test.emit(b'\033[2J\033[1;40H' + wire)
assert len(client.images()) == 1
check_image(client.images()[0], 8, 32,
[rgb[2 * (y >= 16)] for y in range(32) for x in range(8)])
# Different clients independently use the same image at their own cell size.
with image_test(sys.argv[1]) as test:
large = test.attach()
test.emit(wire)
small = test.attach(cw=4, ch=8)
fallback = test.attach(graphical=False)
test.redraw()
assert len(large.images()) == 1
check_image(large.images()[0], 16, 32, expected)
assert len(small.images()) == 1
check_image(small.images()[0], 8, 16,
[expected[y * 2 * 16 + x * 2]
for y in range(16) for x in range(8)])
assert not fallback.images()
assert b'\xe2\x96\x84' in fallback.data, 'missing simultaneous fallback'
PY