Sixel Sixel Graphics
Draw a bitmap image in the text, six pixels high at a time, from a device control string.
DCS P1 ; P2 ; P3 q s…s ST
- Defaults
- P1 = 0, P2 = 0
- VT330/VT340
- §14.2.1 Device Control String
- xterm
- Sixel Graphics
A sixel is a column of six pixels, and a sixel image is a string of them. It is sent in a device control string whose final byte is q, with no intermediate byte. Each data character from ? to ~ is one sixel: its value less 63 gives six bits, the least significant at the top. The VT330/VT340 manual defines the format in its chapter 14, §14.2. The parameters are:
- P1, the pixel aspect ratio:
0,1,5and6(and the default) make each pixel twice as tall as it is wide,2five times,3and4three times, and7to9square. The raster attributes below override it. - P2, what a
0bit means: with0or2(the default), it is drawn in the background color; with1, it is left as it was, so the image is transparent there. - P3, the horizontal grid size, which the VT300 ignores.
Within the data, a few characters are controls rather than sixels (§14.3):
| Character | Function |
|---|---|
! Pn s | repeat the sixel s Pn times |
" Pan ; Pad ; Ph ; Pv | raster attributes: the aspect ratio as a fraction, and the image size |
# Pc | draw in color register Pc from now on |
# Pc ; Pu ; Px ; Py ; Pz | define color register Pc, in HLS (Pu = 1) or RGB (Pu = 2) |
$ | graphics carriage return: back to the left of the same sixel row |
- | graphics new line: down six pixels, to the left |
Where the image goes, and where the text cursor is left when it ends, depend on DECSDM, mode 80.
The VT330 and the VT340 have sixel graphics, and so did the VT240 before them; the VT510 does not. xterm has them too, but not as a default xterm. Sixel support is compiled in unless configure is given --disable-sixel-graphics (configure.in), and it is then turned on only when xterm is a graphics terminal, a 240, 241, 330, 340 or 382 (ptyx.h). That is the decGraphicsID resource if it names one of those, and decTerminalID otherwise (charproc.c). Both default to a VT420 (ptyx.h), so begin_sixel sets nothing up (charproc.c), the string is collected like any other, and at ST it is dropped (misc.c). Nothing is drawn and the cursor does not move, and that is what the cases expect, as the sources page explains. Started as xterm -ti vt340, the same xterm draws the image. The case runner sees characters, not pixels, so even there it could check only where the cursor ends up.
The answer to DA is how a program can tell: a terminal with sixel graphics includes 4 in it, and a default xterm does not.
Not in libghostty-vt
libghostty-vt has no sixel graphics. Its DCS handler in dcs.zig recognizes q only after + (XTGETTCAP) or $ (DECRQSS), and drops any other device control string, so a sixel image is dropped too. That is what a default xterm does, so both cases pass. Ghostty draws images with the kitty graphics protocol instead.
Support
| Terminal | Version | Support | Notes |
|---|---|---|---|
| VT220 | manual, 2nd ed., 1984 | No | the VT220 has no graphics |
| VT340 | manual, vol. 2, 2nd ed., 1988 | Yes | §14 Sixel Graphics |
| VT510 | manual, 1st ed., 1993 | No | the VT510 manual has no sixel graphics |
| xterm | patch 412, xterm-411a | No | consumed and ignored: compiled in, but on only as a VT240, VT330, VT340 or VT382, and a default xterm is a VT420 |
| libghostty-vt | 83edd49 | No | the string is dropped |
| Konsole | 26.11.70, a24c3d71 | Yes | draws them (Vt102Emulation.cpp), and answers DA with 62;1;4 (Vt102Emulation.cpp) |
| ConEmu | build 230724, its documentation | No | not in ConEmu’s list, which has no DCS; ANSI escape codes |
Validation
SIXEL-1: Nothing is drawn, and the cursor does not move
A
\eP0;0;8q"1;1;4;12\#1;2;100;0;0\#1~~~~-~~~~\e\\ # a red 4×12 image
B
|AB____|
|______|
cursor 1,3
reply none
SIXEL-2: Text before ST is part of the image
\ePq~~~~ # never terminated
ABC # sixels, like the rest
|______|
cursor 1,1