├── sixel.sh ├── egret.jpg ├── snake.jpg ├── sixel-result.jpg ├── test-passed-part1.jpg ├── test-passed-part2.jpg ├── minimal-sixel.six ├── jw_star-forming_region_carina_nircam.jpg ├── experiments-screenshots ├── 87f9a824b2d4d037.png ├── Screenshot 4 sixkcd.bash.png ├── Screenshot 5 sixkcd.bash.png ├── Screenshot 2 mandelbrot-bitmap.awk.png ├── Screenshot 3 mandelbrot-bitmap.awk.png ├── Screenshot from 2020-09-05 23-03-33.png ├── Screenshot from 2020-09-06 10-03-03.png ├── Screenshot from 2020-09-06 11-56-07.png ├── Screenshot from 2020-09-06 13-32-58.png ├── Screenshot from 2020-09-06 16-53-04.png ├── Screenshot from 2020-09-06 20-25-22.png └── Screenshot from 2020-09-08 01-51-27.png ├── jw_star-forming_region_carina_nircam_xterm.jpg ├── font-vt100.sh ├── 3-sixels.six ├── font-ansi-blocks.txt ├── 256-colors.sh ├── font-ansi-box.txt ├── font-dec.txt ├── toggle-solarized-dark.sh ├── toggle-solarized-light.sh ├── population.awk ├── 256-colors.pl ├── 16-colors.sh ├── horigraph.awk ├── ansi-vte52.sh ├── sixel.py ├── population-bitmap.awk ├── 24-bit-color.sh ├── bifur-bitmap.awk ├── README.md ├── AnsiTestPattern.txt ├── sixkcd.bash ├── detect-font-geometry.py ├── mandelbrot-bitmap.awk ├── text-test.sixel ├── Experiments.md └── font-test-all.txt /sixel.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | export TERM=tmux-sixel 3 | cat snake.six 4 | -------------------------------------------------------------------------------- /egret.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/egret.jpg -------------------------------------------------------------------------------- /snake.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/snake.jpg -------------------------------------------------------------------------------- /sixel-result.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/sixel-result.jpg -------------------------------------------------------------------------------- /test-passed-part1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/test-passed-part1.jpg -------------------------------------------------------------------------------- /test-passed-part2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/test-passed-part2.jpg -------------------------------------------------------------------------------- /minimal-sixel.six: -------------------------------------------------------------------------------- 1 | Pq 2 | #0;2;0;0;0#1;2;100;100;0#2;2;0;100;0 3 | #1~~@@vv@@~~@@~~$ 4 | #2??}}GG}}??}}??- 5 | #1!14@ 6 |  7 | -------------------------------------------------------------------------------- /jw_star-forming_region_carina_nircam.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/jw_star-forming_region_carina_nircam.jpg -------------------------------------------------------------------------------- /experiments-screenshots/87f9a824b2d4d037.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/87f9a824b2d4d037.png -------------------------------------------------------------------------------- /jw_star-forming_region_carina_nircam_xterm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/jw_star-forming_region_carina_nircam_xterm.jpg -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot 4 sixkcd.bash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot 4 sixkcd.bash.png -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot 5 sixkcd.bash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot 5 sixkcd.bash.png -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot 2 mandelbrot-bitmap.awk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot 2 mandelbrot-bitmap.awk.png -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot 3 mandelbrot-bitmap.awk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot 3 mandelbrot-bitmap.awk.png -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot from 2020-09-05 23-03-33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot from 2020-09-05 23-03-33.png -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot from 2020-09-06 10-03-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot from 2020-09-06 10-03-03.png -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot from 2020-09-06 11-56-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot from 2020-09-06 11-56-07.png -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot from 2020-09-06 13-32-58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot from 2020-09-06 13-32-58.png -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot from 2020-09-06 16-53-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot from 2020-09-06 16-53-04.png -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot from 2020-09-06 20-25-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot from 2020-09-06 20-25-22.png -------------------------------------------------------------------------------- /experiments-screenshots/Screenshot from 2020-09-08 01-51-27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csdvrx/sixel-testsuite/HEAD/experiments-screenshots/Screenshot from 2020-09-08 01-51-27.png -------------------------------------------------------------------------------- /font-vt100.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "You should see basic thin lines used for drawing boxes" 3 | echo 4 | for i in 6a 6b 6c 6d 6e 71 74 75 76 77 78; do 5 | printf "0x$i \x$i \x1b(0\x$i\x1b(B\n" 6 | done 7 | -------------------------------------------------------------------------------- /3-sixels.six: -------------------------------------------------------------------------------- 1 | Pq"1;1;93;14#0;2;60;0;0#1;2;0;66;0#2;2;56;60;0#3;2;47;38;97#4;2;72;0;69#5;2;0;66;72#6;2;72;72;72#7;2;0;0;0#0!11~#1!12~#2!12~#3!12~#4!12~#5!12~#6!12~#7!10~-#0!11~#1!12~#2!12~#3!12~#4!12~#5!12~#6!12~#7!10~-#0!11B#1!12B#2!12B#3!12B#4!12B#5!12B#6!12B#7!10B\ -------------------------------------------------------------------------------- /font-ansi-blocks.txt: -------------------------------------------------------------------------------- 1 | 0 1 2 3 4 5 6 7 8 9 A B C D E F 2 | U+258x ▀ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▉ ▊ ▋ ▌ ▍ ▎ ▏ 3 | U+259x ▐ ░ ▒ ▓ ▔ ▕ ▖ ▗ ▘ ▙ ▚ ▛ ▜ ▝ ▞ ▟ 4 | 5 | There should be no stripes (no lines between blocks) in the bear below 6 | https://github.com/mintty/mintty/issues/376 7 | _ _ 8 | ▗▛▀▜▄ ▃▃▃,,. ~°°°┐ 9 | ▐▌▗███████%#X0, # 10 | ▀███▛▜███@K°%M#%° 11 | ▟███ o▟██▙o #5M% 12 | ██#██▛▗▄▄▖▜██#0K 13 | ▕██M%█▏▝▜▛▘▕█████▏ 14 | ▜████▙━▘▝━▟████▛ 15 | ▝▀▀▜██████▛▀▀▘ 16 | -------------------------------------------------------------------------------- /256-colors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This program is free software. It comes without any warranty, to 4 | # the extent permitted by applicable law. You can redistribute it 5 | # and/or modify it under the terms of the Do What The Fuck You Want 6 | # To Public License, Version 2, as published by Sam Hocevar. See 7 | # http://sam.zoy.org/wtfpl/COPYING for more details. 8 | 9 | for fgbg in 38 48 ; do # Foreground / Background 10 | for color in {0..255} ; do # Colors 11 | # Display the color 12 | printf "\e[${fgbg};5;%sm %3s \e[0m" $color $color 13 | # Display 6 colors per lines 14 | if [ $((($color + 1) % 6)) == 4 ] ; then 15 | echo # New line 16 | fi 17 | done 18 | echo # New line 19 | done 20 | 21 | exit 0 22 | -------------------------------------------------------------------------------- /font-ansi-box.txt: -------------------------------------------------------------------------------- 1 | 0 1 2 3 4 5 6 7 8 9 A B C D E F 2 | U+250x ─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏ 3 | U+251x ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟ 4 | U+252x ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯ 5 | U+253x ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿ 6 | U+254x ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏ 7 | U+255x ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟ 8 | U+256x ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯ 9 | U+257x ╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿ 10 | 11 | There should be 4 small rectangles above a big rectangle with text in the top part. 12 | 13 | ┌─┬┐ ╔═╦╗ ╓─╥╖ ╒═╤╕ 14 | │ ││ ║ ║║ ║ ║║ │ ││ 15 | ├─┼┤ ╠═╬╣ ╟─╫╢ ╞═╪╡ 16 | └─┴┘ ╚═╩╝ ╙─╨╜ ╘═╧╛ 17 | ┌───────────────────┐ 18 | │ ╔═══╗ Some Text │▒ 19 | │ ╚═╦═╝ in the box │▒ 20 | ╞═╤══╩══╤═══════════╡▒ 21 | │ ├──┬──┤ │▒ 22 | │ └──┴──┘ │▒ 23 | └───────────────────┘▒ 24 | ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ 25 | -------------------------------------------------------------------------------- /font-dec.txt: -------------------------------------------------------------------------------- 1 | DEC VT220 drawing in unicode 2 | 3 | U+25C6 Diamond ◆ 4 | U+2592 Checkerboard ▒ 5 | U+2409 Horizontal tab ␉ 6 | U+240C Form feed ␌ 7 | U+240D Carrier return ␍ 8 | U+240A Linefeed ␊ 9 | U+2424 Newline ␤ 10 | U+240B Vertical tab ␋ 11 | U+2518 Lower-right corner ┘ 12 | U+2510 Upper-right corner ┐ 13 | U+250C Upper-left corner ┌ 14 | U+2514 Lower-left corner └ 15 | U+253C Crossing Lines ┼ 16 | U+23BA Horizontal line 1 ⎺ 17 | U+23BB Horizontal line 3 ⎻ 18 | U+2500 Horizontal line 5 ─ 19 | U+23BC Horizontal line 7 ⎼ 20 | U+23BD Horizontal line 9 ⎽ 21 | U+251C Left "T" ├ 22 | U+2524 Right "T" ┤ 23 | U+2534 Bottom "T" ┴ 24 | U+252C Top "T" ┬ 25 | U+2502 Vertical bar │ 26 | -------------------------------------------------------------------------------- /toggle-solarized-dark.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # With 24 bit colors support, dynamically change your current palette to solarized-dark 4 | echo "attempting toggle of solarized-dark" 5 | echo -ne '\eP\e]10;#839496\a' # Foreground -> base0 6 | echo -ne '\eP\e]11;#002B36\a' # Background -> base03 7 | echo -ne '\eP\e]12;#DC322F\a' # Cursor -> red 8 | echo -ne '\eP\e]4;0;#073642\a' # black -> Base02 9 | echo -ne '\eP\e]4;8;#002B36\a' # bold black -> Base03 10 | echo -ne '\eP\e]4;1;#DC322F\a' # red -> red 11 | echo -ne '\eP\e]4;9;#CB4B16\a' # bold red -> orange 12 | echo -ne '\eP\e]4;2;#859900\a' # green -> green 13 | echo -ne '\eP\e]4;10;#586E75\a' # bold green -> base01 * 14 | echo -ne '\eP\e]4;3;#B58900\a' # yellow -> yellow 15 | echo -ne '\eP\e]4;11;#657B83\a' # bold yellow -> base00 * 16 | echo -ne '\eP\e]4;4;#268BD2\a' # blue -> blue 17 | echo -ne '\eP\e]4;12;#839496\a' # bold blue -> base0 * 18 | echo -ne '\eP\e]4;5;#D33682\a' # magenta -> magenta 19 | echo -ne '\eP\e]4;13;#6C71C4\a' # bold magenta -> violet 20 | echo -ne '\eP\e]4;6;#2AA198\a' # cyan -> cyan 21 | echo -ne '\eP\e]4;14;#93A1A1\a' # bold cyan -> base1 * 22 | echo -ne '\eP\e]4;7;#EEE8D5\a' # white -> Base2 23 | echo -ne '\eP\e]4;15;#FDF6E3\a' # bold white -> Base3 24 | -------------------------------------------------------------------------------- /toggle-solarized-light.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # With 24 bit colors support, dynamically change your current palette to solarized-light 4 | echo "attempting toggle of solarized-light" 5 | echo -ne '\eP\e]10;#657B83\a' # Foreground -> base00 6 | echo -ne '\eP\e]11;#FDF6E3\a' # Background -> base3 7 | echo -ne '\eP\e]12;#DC322F\a' # Cursor -> red 8 | echo -ne '\eP\e]4;0;#073642\a' # black -> Base02 9 | echo -ne '\eP\e]4;8;#002B36\a' # bold black -> Base03 10 | echo -ne '\eP\e]4;1;#DC322F\a' # red -> red 11 | echo -ne '\eP\e]4;9;#CB4B16\a' # bold red -> orange 12 | echo -ne '\eP\e]4;2;#859900\a' # green -> green 13 | echo -ne '\eP\e]4;10;#586E75\a' # bold green -> base01 * 14 | echo -ne '\eP\e]4;3;#B58900\a' # yellow -> yellow 15 | echo -ne '\eP\e]4;11;#657B83\a' # bold yellow -> base00 * 16 | echo -ne '\eP\e]4;4;#268BD2\a' # blue -> blue 17 | echo -ne '\eP\e]4;12;#839496\a' # bold blue -> base0 * 18 | echo -ne '\eP\e]4;5;#D33682\a' # magenta -> magenta 19 | echo -ne '\eP\e]4;13;#6C71C4\a' # bold magenta -> violet 20 | echo -ne '\eP\e]4;6;#2AA198\a' # cyan -> cyan 21 | echo -ne '\eP\e]4;14;#93A1A1\a' # bold cyan -> base1 * 22 | echo -ne '\eP\e]4;7;#EEE8D5\a' # white -> Base2 23 | echo -ne '\eP\e]4;15;#FDF6E3\a' # bold white -> Base3 24 | -------------------------------------------------------------------------------- /population.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk 2 | 3 | # Copyright (C) 2020 by Coffee (@Coffee@toot.cafe) 4 | 5 | # you may redistribute and/or modify this file under the terms of 6 | # the GNU Affero General Public License, version 3 or later. The full 7 | # text of this license can be found in the file called LICENSE, which 8 | # should have been distributed along with this file. If not, try the 9 | # following sources: 10 | 11 | # https://gitlab.com/Matrixcoffee/sixel-experiments/blob/master/LICENSE 12 | # https://spdx.org/licenses/AGPL-3.0-or-later.html 13 | # https://www.gnu.org/licenses/ 14 | 15 | # SPDX-License-Identifier: AGPL-3.0-or-later 16 | 17 | function add_sixel(row, x, y , c, nc) 18 | { 19 | c = substr(row, x + 1, 1) 20 | if (c == "") c = "?" 21 | nc = index(SIXELS, c) - 1 22 | nc += 2^y 23 | return substr(row, 1, x) substr(SIXELS, nc + 1, 1) substr(row, x + 2) 24 | } 25 | 26 | BEGIN { 27 | SIXELS = "?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" 28 | 29 | population = 1 30 | row = "" 31 | if (r == "") r = 1.1 32 | y = 0 33 | print "\033Pq#0;2;0;100;0" 34 | for (i = 0; i < 300; i++) { 35 | population += population * r * (1 - population / 500) 36 | for (x = 0; x < population; x++) { 37 | row = add_sixel(row, x, y, 1) 38 | } 39 | y++ 40 | if (y > 5) { 41 | printf "#0%s$-\n", row 42 | y = 0 43 | row = "" 44 | } 45 | } 46 | printf "\033\\" 47 | } 48 | -------------------------------------------------------------------------------- /256-colors.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # Author: Todd Larason 3 | # $XFree86: xc/programs/xterm/vttests/256colors2.pl,v 1.2 2002/03/26 01:46:43 dickey Exp $ 4 | 5 | # use the resources for colors 0-15 - usually more-or-less a 6 | # reproduction of the standard ANSI colors, but possibly more 7 | # pleasing shades 8 | 9 | # colors 16-231 are a 6x6x6 color cube 10 | for ($red = 0; $red < 6; $red++) { 11 | for ($green = 0; $green < 6; $green++) { 12 | for ($blue = 0; $blue < 6; $blue++) { 13 | printf("\x1b]4;%d;rgb:%2.2x/%2.2x/%2.2x\x1b\\", 14 | 16 + ($red * 36) + ($green * 6) + $blue, 15 | ($red ? ($red * 40 + 55) : 0), 16 | ($green ? ($green * 40 + 55) : 0), 17 | ($blue ? ($blue * 40 + 55) : 0)); 18 | } 19 | } 20 | } 21 | 22 | # colors 232-255 are a grayscale ramp, intentionally leaving out 23 | # black and white 24 | for ($gray = 0; $gray < 24; $gray++) { 25 | $level = ($gray * 10) + 8; 26 | printf("\x1b]4;%d;rgb:%2.2x/%2.2x/%2.2x\x1b\\", 27 | 232 + $gray, $level, $level, $level); 28 | } 29 | 30 | 31 | # display the colors 32 | 33 | # first the system ones: 34 | print "System colors:\n"; 35 | for ($color = 0; $color < 8; $color++) { 36 | print "\x1b[48;5;${color}m "; 37 | } 38 | print "\x1b[0m\n"; 39 | for ($color = 8; $color < 16; $color++) { 40 | print "\x1b[48;5;${color}m "; 41 | } 42 | print "\x1b[0m\n\n"; 43 | 44 | # now the color cube 45 | print "Color cube, 6x6x6:\n"; 46 | for ($green = 0; $green < 6; $green++) { 47 | for ($red = 0; $red < 6; $red++) { 48 | for ($blue = 0; $blue < 6; $blue++) { 49 | $color = 16 + ($red * 36) + ($green * 6) + $blue; 50 | print "\x1b[48;5;${color}m "; 51 | } 52 | print "\x1b[0m "; 53 | } 54 | print "\n"; 55 | } 56 | 57 | 58 | # now the grayscale ramp 59 | print "Grayscale ramp:\n"; 60 | for ($color = 232; $color < 256; $color++) { 61 | print "\x1b[48;5;${color}m "; 62 | } 63 | print "\x1b[0m\n"; 64 | -------------------------------------------------------------------------------- /16-colors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Bright toggle=2 separate color matrices of 8x8, showing" 4 | echo "foreground/background colors, bg as rows, fg as columns" 5 | echo 6 | echo "Normal:" 7 | for bg in 0 1 2 3 4 5 6 7 ; do 8 | echo -ne "\e[4$bg" 9 | echo -n "m" 10 | case $bg in 11 | 0) echo -n "black ";; 12 | 1) echo -n " red ";; 13 | 2) echo -n " green ";; 14 | 3) echo -n "yellow ";; 15 | 4) echo -n " blue ";; 16 | 5) echo -n "magenta";; 17 | 6) echo -n " cyan ";; 18 | 7) echo -n " white ";; 19 | esac 20 | for fg in 0 1 2 3 4 5 6 7 ; do 21 | echo -ne "\e[3$fg" 22 | echo -n "m" 23 | case $fg in 24 | 0) echo -n "black ";; 25 | 1) echo -n " red ";; 26 | 2) echo -n " green ";; 27 | 3) echo -n "yellow ";; 28 | 4) echo -n " blue ";; 29 | 5) echo -n "magenta";; 30 | 6) echo -n " cyan ";; 31 | 7) echo -n " white ";; 32 | esac 33 | # reset 34 | echo -ne "\e[39m" 35 | done 36 | # reset and newline 37 | echo -e "\e[49m" 38 | done 39 | 40 | echo 41 | echo "Brightness on:" 42 | for bg in 0 1 2 3 4 5 6 7 ; do 43 | echo -ne "\e[10$bg" 44 | echo -n "m" 45 | case $bg in 46 | 0) echo -n "black ";; 47 | 1) echo -n " red ";; 48 | 2) echo -n " green ";; 49 | 3) echo -n "yellow ";; 50 | 4) echo -n " blue ";; 51 | 5) echo -n "magenta";; 52 | 6) echo -n " cyan ";; 53 | 7) echo -n " white ";; 54 | esac 55 | for fg in 0 1 2 3 4 5 6 7 ; do 56 | echo -ne "\e[9$fg" 57 | echo -n "m" 58 | case $fg in 59 | 0) echo -n "black ";; 60 | 1) echo -n " red ";; 61 | 2) echo -n " green ";; 62 | 3) echo -n "yellow ";; 63 | 4) echo -n " blue ";; 64 | 5) echo -n "magenta";; 65 | 6) echo -n " cyan ";; 66 | 7) echo -n " white ";; 67 | esac 68 | # reset 69 | echo -ne "\e[39m" 70 | done 71 | # reset and newline 72 | echo -e "\e[49m" 73 | done 74 | echo 75 | echo 76 | -------------------------------------------------------------------------------- /horigraph.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk 2 | 3 | # Copyright (C) 2020 by Coffee (@Coffee@toot.cafe) 4 | 5 | # you may redistribute and/or modify this file under the terms of 6 | # the GNU Affero General Public License, version 3 or later. The full 7 | # text of this license can be found in the file called LICENSE, which 8 | # should have been distributed along with this file. If not, try the 9 | # following sources: 10 | 11 | # https://gitlab.com/Matrixcoffee/sixel-experiments/blob/master/LICENSE 12 | # https://spdx.org/licenses/AGPL-3.0-or-later.html 13 | # https://www.gnu.org/licenses/ 14 | 15 | # SPDX-License-Identifier: AGPL-3.0-or-later 16 | 17 | function sixel_multigraph(Data , x, y, yy, maxy, width, color, colors, sixel, bit, value) 18 | { 19 | maxy = Data["height"] - 1 20 | width = Data["width"] 21 | colors = Data["colors"] 22 | for (y = maxy + 5 - maxy % 6; y >= 5; y -= 6) { 23 | for (color = 0; color < colors; color++) { 24 | printf "#%d", color 25 | for (x = 0; x < width; x++) { 26 | sixel = 0 27 | value = Data[color, x] 28 | bit = 1 29 | for (yy = 0; yy < 6; yy++) { 30 | if (value > y - yy) sixel += bit 31 | bit *= 2 32 | } 33 | printf "%c", sixel + 63 34 | } 35 | print "$" 36 | } 37 | print "-" 38 | } 39 | } 40 | 41 | function simulate_population(Graph, color, r, iterations, maxy , y) 42 | { 43 | population = 1 44 | for (i = 0; i < iterations; i++) { 45 | population += population * r * (1 - population / 300) 46 | y = int(population + 0.5) 47 | if (y > maxy) maxy = y 48 | Graph[color, i] = y 49 | } 50 | 51 | return maxy 52 | } 53 | 54 | BEGIN { 55 | if (r1 == "") r1 = 2.1 56 | if (r2 == "") r2 = 0.04 57 | maxy = 0 58 | Graph["width"] = 300 59 | 60 | maxy = simulate_population(Graph, 0, r1, 300, maxy) 61 | maxy = simulate_population(Graph, 1, r2, 300, maxy) 62 | 63 | Graph["height"] = maxy + 1 64 | Graph["colors"] = 2 65 | 66 | print "\033Pq" 67 | print "#0;2;0;100;0" 68 | print "#1;2;0;0;100" 69 | sixel_multigraph(Graph) 70 | printf "\033\\" 71 | } 72 | -------------------------------------------------------------------------------- /ansi-vte52.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo -e '\e[1mbold\e[22m' 4 | echo -e '\e[2mdim\e[22m' 5 | echo -e '\e[3mitalic\e[23m' 6 | echo -e '\e[4munderline\e[24m' 7 | echo -e '\e[4:1mthis is also underline (new in 0.52)\e[4:0m' 8 | echo -e '\e[21mdouble underline (new in 0.52)\e[24m' 9 | echo -e '\e[4:2mthis is also double underline (new in 0.52)\e[4:0m' 10 | echo -e '\e[4:3mcurly underline (new in 0.52)\e[4:0m' 11 | echo -e '\e[5mblink (new in 0.52)\e[25m' 12 | echo -e '\e[7mreverse\e[27m' 13 | echo -e '\e[8minvisible\e[28m <- invisible (but copy-pasteable)' 14 | echo -e '\e[9mstrikethrough\e[29m' 15 | echo -e '\e[53moverline (new in 0.52)\e[55m' 16 | 17 | echo -e '\e[31mred\e[39m' 18 | echo -e '\e[91mbright red\e[39m' 19 | echo -e '\e[38:5:42m256-color, de jure standard (ITU-T T.416)\e[39m' 20 | echo -e '\e[38;5;42m256-color, de facto standard (commonly used)\e[39m' 21 | echo -e '\e[38:2::240:143:104mtruecolor, de jure standard (ITU-T T.416) (new in 0.52)\e[39m' 22 | echo -e '\e[38:2:240:143:104mtruecolor, rarely used incorrect format (might be removed at some point)\e[39m' 23 | echo -e '\e[38;2;240;143;104mtruecolor, de facto standard (commonly used)\e[39m' 24 | 25 | echo -e '\e[46mcyan background\e[49m' 26 | echo -e '\e[106mbright cyan background\e[49m' 27 | echo -e '\e[48:5:42m256-color background, de jure standard (ITU-T T.416)\e[49m' 28 | echo -e '\e[48;5;42m256-color background, de facto standard (commonly used)\e[49m' 29 | echo -e '\e[48:2::240:143:104mtruecolor background, de jure standard (ITU-T T.416) (new in 0.52)\e[49m' 30 | echo -e '\e[48:2:240:143:104mtruecolor background, rarely used incorrect format (might be removed at some point)\e[49m' 31 | echo -e '\e[48;2;240;143;104mtruecolor background, de facto standard (commonly used)\e[49m' 32 | 33 | echo -e '\e[21m\e[58:5:42m256-color underline (new in 0.52)\e[59m\e[24m' 34 | echo -e '\e[21m\e[58;5;42m256-color underline (new in 0.52)\e[59m\e[24m' 35 | echo -e '\e[4:3m\e[58:2::240:143:104mtruecolor underline (new in 0.52) (*)\e[59m\e[4:0m' 36 | echo -e '\e[4:3m\e[58:2:240:143:104mtruecolor underline (new in 0.52) (might be removed at some point) (*)\e[59m\e[4:0m' 37 | echo -e '\e[4:3m\e[58;2;240;143;104mtruecolor underline (new in 0.52) (*)\e[59m\e[4:0m' 38 | -------------------------------------------------------------------------------- /sixel.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | class SixelGraphic: 4 | class Color: 5 | def __init__(self, r, g, b): 6 | self.r = self._v(r) 7 | self.g = self._v(g) 8 | self.b = self._v(b) 9 | 10 | @staticmethod 11 | def _v(v): 12 | v = int(v) 13 | if v < 0: v = 0 14 | if v > 100: v = 100 15 | return v 16 | 17 | def as_sixel(self, n): 18 | return "#{};2;{};{};{}".format(n, self.r, self.g, self.b) 19 | 20 | def __eq__(self, other): 21 | if not isinstance(other, self.__class__): 22 | return false 23 | 24 | return self.r == other.r and self.g == other.g and self.b == other.b 25 | 26 | def __init__(self, fh=sys.stdout): 27 | self.fh = fh 28 | self.grid = [] 29 | self.colors = [] 30 | 31 | def __enter__(self): 32 | self.emitln("\033Pq") 33 | return self 34 | 35 | def __exit__(self, *args): 36 | self.emitln("\033\\") 37 | return False 38 | 39 | def set_pixel(self, x, y, color): 40 | y_index, y_offset = divmod(y, 6) 41 | 42 | #print("x: {}, y: {}, y_index: {}, y_offset: {}".format(x, y, y_index, y_offset)) 43 | 44 | while len(self.grid) <= y_index: 45 | self.grid.append([]) 46 | 47 | while len(self.grid[y_index]) <= color: 48 | self.grid[y_index].append(bytearray()) 49 | 50 | while len(self.grid[y_index][color]) <= x: 51 | self.grid[y_index][color].append(63) 52 | 53 | self.grid[y_index][color][x] = \ 54 | ((self.grid[y_index][color][x] - 63) | 2 ** y_offset) + 63 55 | 56 | def set_pixel_rgb(self, x, y, r, g, b): 57 | c = self.Color(r, g, b) 58 | for n, tc in enumerate(self.colors): 59 | if tc == c: 60 | return self.set_pixel(x, y, n) 61 | 62 | self.colors.append(c) 63 | return self.set_pixel(x, y, len(self.colors) - 1) 64 | 65 | def display(self): 66 | for n, c in enumerate(self.colors): 67 | self.emitln(c.as_sixel(n)) 68 | 69 | for a in self.grid: 70 | for c, line in enumerate(a): 71 | self.emit("#{}".format(c)) 72 | self.emit(line.decode()) 73 | self.emitln("$") 74 | self.emitln("-") 75 | 76 | def emit(self, txt): 77 | print(txt, file=self.fh, end="") 78 | 79 | def emitln(self, txt): 80 | print(txt, file=self.fh) 81 | 82 | 83 | if __name__ == '__main__': 84 | x = SixelGraphic() 85 | 86 | for n in range(33): 87 | x.set_pixel_rgb(n, n, 100, 0, 0) 88 | x.set_pixel_rgb(n + 3, n, 0, 100, 0) 89 | x.set_pixel_rgb(33 - n, n, 0, 0, 100) 90 | 91 | with x: 92 | x.display() 93 | -------------------------------------------------------------------------------- /population-bitmap.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk 2 | 3 | # Copyright (C) 2020 by Coffee (@Coffee@toot.cafe) 4 | 5 | # you may redistribute and/or modify this file under the terms of 6 | # the GNU Affero General Public License, version 3 or later. The full 7 | # text of this license can be found in the file called LICENSE, which 8 | # should have been distributed along with this file. If not, try the 9 | # following sources: 10 | 11 | # https://gitlab.com/Matrixcoffee/sixel-experiments/blob/master/LICENSE 12 | # https://spdx.org/licenses/AGPL-3.0-or-later.html 13 | # https://www.gnu.org/licenses/ 14 | 15 | # SPDX-License-Identifier: AGPL-3.0-or-later 16 | 17 | function draw_image(Image, maxx, maxy, maxcolor, borg, color, s, x, y, sixel, bit, pixel) 18 | { 19 | maxx = -1 20 | maxy = -1 21 | maxcolor = -1 22 | 23 | # Determine dimensions 24 | for (borg in Image) { 25 | color = Image[borg] 26 | s = index(borg, SUBSEP) 27 | x = int(substr(borg, 1, s - 1)) 28 | y = int(substr(borg, s + 1)) 29 | if (maxx < x) maxx = x 30 | if (maxy < y) maxy = y 31 | if (color != "" && maxcolor < color) maxcolor = color 32 | } 33 | 34 | # Sixelize 35 | for (y = maxy + 6 - maxy % 6; y >= 5; y -= 6) { 36 | for (color = 0; color <= maxcolor; color++) { 37 | printf "#%d", color 38 | for (x = 0; x <= maxx; x++) { 39 | sixel = 0 40 | bit = 1 41 | for (yy = 0; yy < 6; yy++) { 42 | pixel = Image[x, y - yy] 43 | if (pixel != "" && pixel == color) sixel += bit 44 | bit *= 2 45 | } 46 | printf "%c", sixel + 63 47 | } 48 | print "$" 49 | } 50 | print "-" 51 | } 52 | } 53 | 54 | function sgn(x) 55 | { 56 | if (x < 0) return -1 57 | if (x > 0) return 1 58 | return 0 59 | } 60 | 61 | function simulate_population(Image, color, r, iterations , population, i, y, prev_y) 62 | { 63 | population = 1 64 | prev_y = 1 65 | for (i = 0; i < iterations; i++) { 66 | population += population * r * (1 - population / 300) 67 | if (population < 0) population = 0 68 | y = int(population + 0.5) 69 | do { 70 | prev_y += sgn(y - prev_y) 71 | Image[i, prev_y] = color 72 | } while (prev_y != y) 73 | } 74 | } 75 | 76 | function run_program(Args, nargs) 77 | { 78 | for (color = 0; color < nargs - 1; color++) 79 | simulate_population(Figure, color, Args[color + 1], 750) 80 | 81 | print "\033Pq" 82 | print "#0;2;50;50;50" 83 | #print "#1;2;0;100;0" 84 | 85 | draw_image(Figure) 86 | 87 | printf "\033\\" 88 | } 89 | 90 | BEGIN { 91 | Defaultratios[1] = 2.4 92 | Defaultratios[2] = 0.04 93 | 94 | if (ARGC > 1) run_program(ARGV, ARGC) 95 | else run_program(Defaultratios, 3) 96 | } 97 | -------------------------------------------------------------------------------- /24-bit-color.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "You should see 4 lines of continuous colors, without bands or breaks except if it reaches the right side of the screen" 4 | # This file echoes four gradients with 24-bit color codes 5 | # to the terminal to demonstrate their functionality. 6 | # The foreground escape sequence is ^[38;2;;;m 7 | # The background escape sequence is ^[48;2;;;m 8 | # range from 0 to 255 inclusive. 9 | # The escape sequence ^[0m returns output to default 10 | 11 | SEPARATOR=':' 12 | 13 | setBackgroundColor() 14 | { 15 | echo -en "\x1b[48${SEPARATOR}2${SEPARATOR}$1${SEPARATOR}$2${SEPARATOR}$3""m" 16 | } 17 | 18 | resetOutput() 19 | { 20 | echo -e "\x1b[0m" 21 | } 22 | 23 | resetOutputFinal() 24 | { 25 | echo -en "\x1b[0m" 26 | } 27 | 28 | # Gives a color $1/255 % along HSV 29 | # Who knows what happens when $1 is outside 0-255 30 | # Echoes "$red $green $blue" where 31 | # $red $green and $blue are integers 32 | # ranging between 0 and 255 inclusive 33 | rainbowColor() 34 | { 35 | let h=$1/43 36 | let f=$1-43*$h 37 | let t=$f*255/43 38 | let q=255-t 39 | 40 | if [ $h -eq 0 ] 41 | then 42 | echo "255 $t 0" 43 | elif [ $h -eq 1 ] 44 | then 45 | echo "$q 255 0" 46 | elif [ $h -eq 2 ] 47 | then 48 | echo "0 255 $t" 49 | elif [ $h -eq 3 ] 50 | then 51 | echo "0 $q 255" 52 | elif [ $h -eq 4 ] 53 | then 54 | echo "$t 0 255" 55 | elif [ $h -eq 5 ] 56 | then 57 | echo "255 0 $q" 58 | else 59 | # execution should never reach here 60 | echo "0 0 0" 61 | fi 62 | } 63 | 64 | for i in `seq 0 127`; do 65 | setBackgroundColor $i 0 0 66 | echo -en " " 67 | done 68 | resetOutput 69 | for i in `seq 255 128`; do 70 | setBackgroundColor $i 0 0 71 | echo -en " " 72 | done 73 | resetOutput 74 | 75 | for i in `seq 0 127`; do 76 | setBackgroundColor 0 $i 0 77 | echo -n " " 78 | done 79 | resetOutput 80 | for i in `seq 255 128`; do 81 | setBackgroundColor 0 $i 0 82 | echo -n " " 83 | done 84 | resetOutput 85 | 86 | for i in `seq 0 127`; do 87 | setBackgroundColor 0 0 $i 88 | echo -n " " 89 | done 90 | resetOutput 91 | for i in `seq 255 128`; do 92 | setBackgroundColor 0 0 $i 93 | echo -n " " 94 | done 95 | resetOutput 96 | 97 | for i in `seq 0 127`; do 98 | setBackgroundColor `rainbowColor $i` 99 | echo -n " " 100 | done 101 | resetOutput 102 | for i in `seq 255 128`; do 103 | setBackgroundColor `rainbowColor $i` 104 | echo -n " " 105 | done 106 | resetOutputFinal 107 | -------------------------------------------------------------------------------- /bifur-bitmap.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk 2 | 3 | # Copyright (C) 2020 by Coffee (@Coffee@toot.cafe) 4 | 5 | # you may redistribute and/or modify this file under the terms of 6 | # the GNU Affero General Public License, version 3 or later. The full 7 | # text of this license can be found in the file called LICENSE, which 8 | # should have been distributed along with this file. If not, try the 9 | # following sources: 10 | 11 | # https://gitlab.com/Matrixcoffee/sixel-experiments/blob/master/LICENSE 12 | # https://spdx.org/licenses/AGPL-3.0-or-later.html 13 | # https://www.gnu.org/licenses/ 14 | 15 | # SPDX-License-Identifier: AGPL-3.0-or-later 16 | 17 | function draw_image(Image, maxx, maxy, maxcolor, borg, color, s, x, y, sixel, bit, pixel) 18 | { 19 | maxx = -1 20 | maxy = -1 21 | maxcolor = -1 22 | 23 | # Determine dimensions 24 | for (borg in Image) { 25 | color = Image[borg] 26 | s = index(borg, SUBSEP) 27 | x = int(substr(borg, 1, s - 1)) 28 | y = int(substr(borg, s + 1)) 29 | if (maxx < x) maxx = x 30 | if (maxy < y) maxy = y 31 | if (color != "" && maxcolor < color) maxcolor = color 32 | } 33 | 34 | # Sixelize 35 | for (y = maxy + 6 - maxy % 6; y >= 5; y -= 6) { 36 | for (color = 0; color <= maxcolor; color++) { 37 | printf "#%d", color 38 | for (x = 0; x <= maxx; x++) { 39 | sixel = 0 40 | bit = 1 41 | for (yy = 0; yy < 6; yy++) { 42 | pixel = Image[x, y - yy] 43 | if (pixel != "" && pixel == color) sixel += bit 44 | bit *= 2 45 | } 46 | printf "%c", sixel + 63 47 | } 48 | print "$" 49 | } 50 | print "-" 51 | } 52 | } 53 | 54 | function sgn(x) 55 | { 56 | if (x < 0) return -1 57 | if (x > 0) return 1 58 | return 0 59 | } 60 | 61 | function run_population(Image, color, x, r, height , p, i) 62 | { 63 | p = 0.5 64 | for (i = 0; i < 500; i++) p = r * p * (1 - p) 65 | for (i = 0; i < 500; i++) { 66 | p = r * p * (1 - p) 67 | Image[x, int(0.5 * p * height)] = color 68 | } 69 | } 70 | 71 | function bifurcate(Image, color, rmax, width, height, rmin , x, r) 72 | { 73 | if (rmin == "") rmin = 1 74 | 75 | for (x = 0; x < width; x++) { 76 | r = rmin + (rmax - rmin) * (x / width) 77 | run_population(Image, color, x, r, height) 78 | } 79 | } 80 | 81 | function run_program(Args, nargs) 82 | { 83 | bifurcate(Figure, 3, 4, 450, 600) 84 | 85 | print "\033Pq" 86 | print "#0;2;50;50;50" 87 | #print "#1;2;0;100;0" 88 | 89 | draw_image(Figure) 90 | 91 | printf "\033\\" 92 | } 93 | 94 | BEGIN { 95 | Defaultratios[1] = 2.4 96 | Defaultratios[2] = 0.04 97 | 98 | if (ARGC > 1) run_program(ARGV, ARGC) 99 | else run_program(Defaultratios, 3) 100 | } 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > sixel-tmux : a terminal multiplexer that properly display graphics because it does not eat escape sequences 2 | 3 | ## Usage 4 | 5 | To check what your terminal supports: 6 | 7 | For the colors: 8 | 1. start by 16-colors.sh 9 | 2. then try 256-colors.pl 10 | 3. see if you are lucky and can use a 24 bits palette with 24-bit-color.sh 11 | 4. if it works, try to switch the 16 colors palette between Solarized dark and light with toggle-solarized-dark.sh and toggle-solarized-light.sh 12 | 13 | In the final test, after displaying the 4 continous color lines without bands 14 | or sudden breaks, your screen should switch to a black background then back to 15 | a clear yellowish background. 16 | 17 | For the fonts: 18 | 1. start with `cat font-ansi-blocks.txt` to see block drawing characters and a test bear 19 | 2. run `font-vt100.sh` to see the basic box drawing characters 20 | 2. `cat font-ansi-box.txt` to see the full set of box drawing characters 21 | 3. `cat font-dec.txt` to check DEC VT220 extra characters 22 | 4. `cat font-test-all.txt` to check unicode support and overall support of the drawing characters 23 | 24 | In the final test, boxes should be properly aligned, and lines should intersect cleanly. 25 | 26 | If the font test fails, you may need to change your font as it may not support every character. 27 | 28 | Alternatively, when using mlterm you can tell it to extend your preferred font with one or more other fonts, for example: 29 | ISO8859_1 = Iosevka SS04 18 30 | ISO8859_15 = Iosevka SS04 18 31 | ISO10646_UCS2_1 =Iosevka SS04 18 32 | ISO10646_UCS2_1_BOLD = Iosevka SS04 18 33 | U+2500-25ff=Segoe UI Symbol 34 | U+25C6 = Tera Special # Diamond ◆ 35 | U+2409 = Tera Special # Horizontal tab ␉ 36 | U+240C = Tera Special # Form feed ␌ 37 | U+240D = Tera Special # Carrier return ␍ 38 | U+240A = Tera Special # Linefeed ␊ 39 | U+2424 = Tera Special # Newline ␤ 40 | U+240B = Tera Special # Vertical tab ␋ 41 | U+23BA = Tera Special # Horizontal line 1 ⎺ 42 | U+23BB = Tera Special # Horizontal line 3 ⎻ 43 | U+2500 = Tera Special # Horizontal line 5 ─ 44 | U+23BC = Tera Special # Horizontal line 7 ⎼ 45 | U+23BD = Tera Special # Horizontal line 9 ⎽ 46 | 47 | ### Test passed 48 | 49 | You should get something like: 50 | 51 | ![mintty displaying VTE52 font attributes](https://raw.githubusercontent.com/csdvrx/sixel-testsuite/master/test-passed-part1.jpg) 52 | 53 | 54 | ![mintty displaying ANSI and sixels](https://raw.githubusercontent.com/csdvrx/sixel-testsuite/master/test-passed-part2.jpg) 55 | 56 | Create your own image: 57 | 58 | Requirements: [libsixel](https://github.com/saitoha/libsixel) 59 | 60 | ```sh 61 | $ img2sixel -7 jw_star-forming_region_carina_nircam.jpg \ 62 | -o jw_star-forming_region_carina_nircam.six 63 | $ cat jw_star-forming_region_carina_nircam.six 64 | ``` 65 | 66 | ![xterm displaying sixels](jw_star-forming_region_carina_nircam_xterm.jpg) 67 | 68 | [Image source](https://www.nasa.gov/image-feature/goddard/2022/nasa-s-webb-reveals-cosmic-cliffs-glittering-landscape-of-star-birth). 69 | 70 | ### Test failed 71 | 72 | If the ANSI test fail, you may need a correct terminfo. 73 | 74 | Here is an example assuming you use sixel-tmux 75 | 1. install sixel-tmux.terminfo: `tic sixel-tmux.terminfo; tic -o ~/.terminfo sixel-tmux.terminfo` 76 | 2. start sixel-tmux: `sixel-tmux` 77 | 3. select sixel-tmux: `export TERM=sixel-tmux` 78 | 4. verify sixel-tmux is used: `tput smglr|base64` should return GzcbWz82OWgbWyVpJXAxJWQ7JXAyJWRzGzg= 79 | 80 | -------------------------------------------------------------------------------- /AnsiTestPattern.txt: -------------------------------------------------------------------------------- 1 | ▐██▌ ▐███▌ ▐███▌ ▐███▌ ▐███▌ ▐███▌ ▐███▌ ▐███▌ ▐███▌ ▐██▌ 2 | ▐▀▀┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼▀▀▌ 3 | ▐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ▌ 4 | ▐▄▄┼───┼───┴───┼───┼───┼───┼▄▄▄▄███████████▄▄▄▄┼───┼───┼───┼───┴───┼───┼▄▄▌ 5 | ▐██│ │ │ │ │▄▄███▌ Majerus.net ▐███▄▄│ │ │ │ │██▌ 6 | ▐▀▀┼───┤ ├───┼─▄▄██████▌ ▌ │██████▄▄─┼───┤ ├───┼▀▀▌ 7 | ▐ │ │ │ ▄█████████▌ Black ▌ White │█████████▄ │ │ │ ▌ 8 | ▐▄▄┼───┤ ┌───┼─▄▌ ███ ▐██▌ 0·8 ▌ 7·15 ▐██▌ ███ ▐▄─┼───┐ ├───┼▄▄▌ 9 | ▐██│ │ │ │░█▌ ███ ▐██▌ ▌ ▐██▌ ███ ▐█░│ │ │ │██▌ 10 | ▐▀▀┼───┤ ├───░█████▌ ▐███████▌ ▐███████▌ ░───┤ ├───┼▀▀▌ 11 | ▐ │ │ │ ▐Yellow▌ Cyan ▌ Green ▌Magenta▌ Red ▌ Blue ▌ │ │ │ ▌ 12 | ▐▄▄┼───┤ ├──▐ 3·11 ▌ 6·14 ▌ 2·10▌ │ ▐5·13 ▐ 1·9 ▐ 4·12 ▌──┤ ├───┼▄▄▌ 13 | ▐██│ │ │ ███████▌ ▐█████▌ │ ▐█████▌ ▐███████ │ │ │██▌ 14 | ▐▀▀┼───┤ ├── │ │ │ │ │ │ │ │ │ │ │ │ │ ──┤ ├───┼▀▀▌ 15 | ▐ │ │ │ ─┼───┼───┼───┼───┼───┼─┼─┼───┼───┼───┼───┼───┼─ │ │ │ ▌ 16 | ▐▄▄┼───┤ ├── │ │ │ │ │ │ │ │ │ │ │ │ │ ──┤ ├───┼▄▄▌ 17 | ▐██│ │ │ █████████▀▄▀▄▀▄▀▄▀▌▌▌│ │ ▌▌■ ■ ■ ■ ■/\/\/\/\  │ │ │██▌ 18 | ▐▀▀┼───┤ ├──▐████████▀▄▀▄▀▄▀▄▀▐▐▐▐ │ │▐ ■ ■ ■ ■ \/\/\/\/ ▐──┤ ├───┼▀▀▌ 19 | ▐ │ │ │ ▐████████▀▄▀▄▀▄▀▄▀▌▌▌▌▌▌▌▌▌■ ■ ■ ■ ■/\/\/\/\ ▐ │ │ │ ▌ 20 | ▐▄▄┼───┤ ├───░███████▀▄▀▄▀▄▀▄▀▐▐▐▐▐▐▐▐▐ ■ ■ ■ ■ \/\/\/\/ ▒───┤ ├───┼▄▄▌ 21 | ▐██│ │ │ │░████▓▓▓▒▒▒░░░  ░░░▒▒▒▓▓▓███▓▓▓▒▒▒░░░ ▒│ │ │ │██▌ 22 | ▐▀▀┼───┤ └───┼─▀███▓▓▓▒▒▒░░░  ░░░▒▒▒▓▓▓███▓▓▓▒▒▒░░░ ▄─┼───┘ ├───┼▀▀▌ 23 | ▐ │ │ │ ▀███████ ║ ANSI/VT ███████▀ │]8;id=tp4b;http://www.majerus.net/▐■▐■▐ ]8;;│ │ ▌ 24 | ▐▄▄┼───┤ ├───┼─▀▀████ ║ test pattern ████▀▀─┼───┤]8;id=tp4b;http://www.majerus.net/ ▐■▐■▐ ]8;;├───┼▄▄▌ 25 | ▐██│ │ │ │ │▀▀█████████▌ ▐█████████▀▀│ │ │]8;id=tp4b;http://www.majerus.net/Majerus]8;;│ │██▌ 26 | ▐▀▀┼───┼───┬───┼───┼───┼───┼▀▀▀▀███▌ ▐███▀▀▀▀┼───┼───┼───┼───┬───┼───┼▀▀▌ 27 | ▐ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ▌ 28 | ▐▄▄┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼▄▄▌ 29 | ▐██▌ ▐███▌ ▐███▌ ▐███▌ ▐███▌ ▐███▌ ▐███▌ ▐███▌ ▐███▌ ▐██▌ -------------------------------------------------------------------------------- /sixkcd.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Display an xkcd comic using sixel graphics. Show the comic if 4 | # given, or the latest comic by default. 5 | # 6 | # Press any key to show the alt text and exit. 7 | 8 | # Dependencies: 9 | # - img2sixel ("apt-get install libsixel-bin") 10 | # - python 3.x ("apt-get install python3") 11 | # - curl or wget ("apt-get install curl") 12 | # - torsocks (optional, make requests through tor) 13 | 14 | # [ User Parameters ] ######################################################### 15 | 16 | xkcdnumber="$1" 17 | 18 | # [ Global Configuration ] #################################################### 19 | 20 | TORIFY=( torsocks -i ) 21 | type -p "${TORIFY[0]}" > /dev/null || TORIFY=() 22 | 23 | # [ Functions ] ############################################################### 24 | 25 | # Print a message to standard error and exit with a non-zero status code 26 | 27 | error: () 28 | { 29 | echo Error: "$*" 1>&2 30 | exit 127 31 | } 32 | 33 | # Word Wrap (stdin -> stdout) with auto terminal width detection 34 | # 35 | # Prefer "par" if detected, otherwise fall back via "fmt" to "cat". 36 | 37 | wordwrap () 38 | { 39 | local width="$1" 40 | local defaultwidth="${2:-"80"}" 41 | local ww 42 | 43 | [ "$width" ] || tty <&1 > /dev/null || width="$defaultwidth" 44 | [ "$width" ] || width="$COLUMNS" 45 | [ "$width" ] || width="$( tput cols <&1 )" 46 | [ "$width" ] || width="$defaultwidth" 47 | 48 | ww=( cat ) 49 | [ -x /usr/bin/fmt ] && ww=( /usr/bin/fmt -w "$width" ) 50 | [ -x /usr/bin/par ] && ww=( /usr/bin/par "$width" ) 51 | 52 | "${ww[@]}" 53 | } 54 | 55 | # Fetch URL and output contents to stdout 56 | 57 | fetch_url () 58 | { 59 | local url="$1" 60 | 61 | if type -p curl > /dev/null; then 62 | "${TORIFY[@]}" curl -sSL "$url" 63 | elif type -p wget > /dev/null; then 64 | "${TORIFY[@]}" wget --no-verbose --retry-on-host-error -O - -- "$url" 65 | fi 66 | } 67 | 68 | # Fetch xkcd metadata by its comic number, or latest if omitted. 69 | # Writes to stdout. 70 | 71 | fetch_xkcd () 72 | { 73 | local xkcdnumber="$1" 74 | local url 75 | 76 | if [ "$xkcdnumber" ]; then 77 | url="https://xkcd.com/"$xkcdnumber"/info.0.json" 78 | else 79 | url="https://xkcd.com/info.0.json" 80 | fi 81 | 82 | fetch_url "$url" 83 | } 84 | 85 | # Read xkcd json from stdin, output selected values on stdout: 86 | # Line 1: xkcd number 87 | # Line 2: safe_title 88 | # Line 3: URL of comic image 89 | # Line 4: year 90 | # Line 5: month 91 | # Line 6: day 92 | # Line 7+: "Alt" text 93 | 94 | decode_xkcd () 95 | { 96 | python3 -c 'if __name__ == "__main__": 97 | import json 98 | import sys 99 | j = json.load(sys.stdin) 100 | for k in "num safe_title img year month day alt".split(): 101 | print(j[k])' 102 | } 103 | 104 | # [ Main ] #################################################################### 105 | 106 | # Display xkcd number ASAP if known, but don't advance the line, so we 107 | # can overwrite it with json data when that arrives. Doing it this way 108 | # allows us to have a single code path, regardless of whether we already 109 | # know the xkcd number. 110 | 111 | echo -n "$xkcdnumber " 112 | 113 | # Download and extract 114 | 115 | xkcd_data="$( fetch_xkcd "$xkcdnumber" | decode_xkcd )" \ 116 | || error: Download failed 117 | 118 | xkcd_number="$( echo "$xkcd_data" | awk 'NR==1' )" 119 | xkcd_safe_title="$( echo "$xkcd_data" | awk 'NR==2' )" 120 | xkcd_imgurl="$( echo "$xkcd_data" | awk 'NR==3' )" 121 | xkcd_year="$( echo "$xkcd_data" | awk 'NR==4' )" 122 | xkcd_month="$( echo "$xkcd_data" | awk 'NR==5' )" 123 | xkcd_day="$( echo "$xkcd_data" | awk 'NR==6' )" 124 | xkcd_alt="$( echo "$xkcd_data" | awk 'NR>6' )" 125 | 126 | # Display (before image) 127 | 128 | printf '\r%s (%04d-%02d-%02d)\n' "$xkcd_number" "$xkcd_year" "$xkcd_month" "$xkcd_day" 129 | echo 130 | echo "$xkcd_safe_title" | wordwrap 131 | echo 132 | 133 | # Download image 134 | 135 | xkcd_siximg="$( fetch_url "$xkcd_imgurl" | img2sixel )" \ 136 | || error: Image download failed 137 | 138 | # Display (image, alt text) 139 | 140 | echo "$xkcd_siximg" 141 | read -rsn 1 142 | echo "$xkcd_alt" | wordwrap 143 | echo 144 | -------------------------------------------------------------------------------- /detect-font-geometry.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 by Coffee (@Coffee@toot.cafe) 2 | 3 | # you may redistribute and/or modify this file under the terms of 4 | # the GNU Affero General Public License, version 3 or later. The full 5 | # text of this license can be found in the file called LICENSE, which 6 | # should have been distributed along with this file. If not, try the 7 | # following sources: 8 | 9 | # https://gitlab.com/Matrixcoffee/sixel-experiments/blob/master/LICENSE 10 | # https://spdx.org/licenses/AGPL-3.0-or-later.html 11 | # https://www.gnu.org/licenses/ 12 | 13 | # SPDX-License-Identifier: AGPL-3.0-or-later 14 | 15 | import collections 16 | import os 17 | import re 18 | import sys 19 | import termios 20 | import time 21 | 22 | Dimensions = collections.namedtuple("Dimensions", "width height") 23 | 24 | class RawTerminal: 25 | def __enter__(self): 26 | self.saved_attrs = termios.tcgetattr(0) 27 | self.saved_blocking = os.get_blocking(0) 28 | 29 | attrs = termios.tcgetattr(0) 30 | attrs[3] &= ~termios.ICANON 31 | attrs[3] &= ~termios.ECHO 32 | termios.tcsetattr(0, termios.TCSADRAIN, attrs) 33 | os.set_blocking(0, False) 34 | 35 | return self 36 | 37 | def __exit__(self, exc_type, exc_value, traceback): 38 | termios.tcsetattr(0, termios.TCSADRAIN, self.saved_attrs) 39 | os.set_blocking(0, self.saved_blocking) 40 | 41 | @staticmethod 42 | def _interrogate(question, stopseq, answerpattern, timeout=5): 43 | sys.stdout.write(question) 44 | sys.stdout.flush() 45 | 46 | r = "" 47 | c = "" 48 | noinput = 0 49 | capture = False 50 | 51 | while True: 52 | c = sys.stdin.read(1) 53 | if c == "": 54 | time.sleep(.1) 55 | noinput += 1 56 | if noinput > timeout: return 57 | continue 58 | noinput = 0 59 | if not capture: 60 | if c != "\033": continue 61 | capture = True 62 | 63 | r = r + c 64 | if r.endswith(stopseq): break 65 | if len(r) >= 65535: return 66 | 67 | if isinstance(answerpattern, str): 68 | return re.search(answerpattern, r) 69 | else: 70 | return answerpattern.search(r) 71 | 72 | def _has_swapped_size_bug(self): 73 | # gnome-terminal responds with width;height when 74 | # interrogated with the [14t sequence. The correct 75 | # order is height;width, as per the spec and as correctly 76 | # implemented in both xterm and mlterm. 77 | 78 | # This method detects when a libvte-based terminal 79 | # (such as gnome-terminal) is in use, and offers its 80 | # best guess as to whether the bug is present. 81 | 82 | # That is to say, we currently assume all libvte-based 83 | # terminals have the bug. 84 | 85 | # Reference for detection: 86 | # https://gitlab.gnome.org/GNOME/vte/-/issues/235 87 | 88 | m = self.get_DA3() 89 | if not m: return False 90 | if m.group(1) != "7E565445": return False # Hex "~VTE" 91 | 92 | return True 93 | 94 | #m = self.get_DA2() 95 | #if not m: return True # Can't get version - assume bug is present 96 | #if m.group(2) < 1000000: return True 97 | 98 | def get_size_pixels(self): 99 | m = self._interrogate("\033[14t", "t", "^\033\\[4;([0-9]+);([0-9]+)t$") 100 | if m: 101 | if self._has_swapped_size_bug(): 102 | # Broken libvte terminal emulator 103 | return Dimensions(int(m.group(1)), int(m.group(2))) 104 | else: 105 | return Dimensions(int(m.group(2)), int(m.group(1))) 106 | 107 | def get_size_characters(self): 108 | m = self._interrogate("\033[18t", "t", "^\033\\[8;([0-9]+);([0-9]+)t$") 109 | if m: return Dimensions(int(m.group(2)), int(m.group(1))) 110 | 111 | def get_character_cell_size(self): 112 | m = self._interrogate("\033[16t", "t", "^\033\\[6;([0-9]+);([0-9]+)t$") 113 | if m: return Dimensions(int(m.group(2)), int(m.group(1))) 114 | 115 | # Well, that didn't work. Let's try the indirect route, 116 | # and divide canvas size in pixels by canvas size in 117 | # characters. 118 | 119 | d_pixels = self.get_size_pixels() 120 | if not d_pixels: return 121 | d_chars = self.get_size_characters() 122 | if not d_chars: return 123 | 124 | w = d_pixels.width / d_chars.width 125 | h = d_pixels.height / d_chars.height 126 | 127 | if w == int(w) and h == int(h): return Dimensions(int(w), int(h)) 128 | 129 | def get_DA2(self): 130 | return self._interrogate("\033[>c", "c", "^\033\\[>([0-9]*);([0-9]*);([0-9]*)c$") 131 | 132 | def get_DA3(self): 133 | return self._interrogate("\033[=c", "\033\\", "^\033P!\\|([0-9A-F]{8})\033\\\\$") 134 | 135 | def show_value(text, format, obj): 136 | fmo = "(not detected)" 137 | if obj: fmo=format.format(obj) 138 | print(text.format(fmo)) 139 | 140 | if __name__ == '__main__': 141 | with RawTerminal() as terminal: 142 | show_value("Your terminal size in pixels [WxH]: {}", 143 | "{0.width}x{0.height}", terminal.get_size_pixels()) 144 | show_value("Your terminal size in characters [WxH]: {}", 145 | "{0.width}x{0.height}", terminal.get_size_characters()) 146 | show_value("Your character cell size in pixels [WxH]: {}", 147 | "{0.width}x{0.height}", terminal.get_character_cell_size()) 148 | -------------------------------------------------------------------------------- /mandelbrot-bitmap.awk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/awk 2 | 3 | # Copyright (C) 2020 by Coffee (@Coffee@toot.cafe) 4 | 5 | # you may redistribute and/or modify this file under the terms of 6 | # the GNU Affero General Public License, version 3 or later. The full 7 | # text of this license can be found in the file called LICENSE, which 8 | # should have been distributed along with this file. If not, try the 9 | # following sources: 10 | 11 | # https://gitlab.com/Matrixcoffee/sixel-experiments/blob/master/LICENSE 12 | # https://spdx.org/licenses/AGPL-3.0-or-later.html 13 | # https://www.gnu.org/licenses/ 14 | 15 | # SPDX-License-Identifier: AGPL-3.0-or-later 16 | 17 | function draw_image(Image, maxx, maxy, maxcolor, borg, color, s, x, y, yy, sixel, bit, pixel) 18 | { 19 | maxx = -1 20 | maxy = -1 21 | maxcolor = -1 22 | 23 | # Determine dimensions 24 | for (borg in Image) { 25 | color = Image[borg] 26 | s = index(borg, SUBSEP) 27 | x = int(substr(borg, 1, s - 1)) 28 | y = int(substr(borg, s + 1)) 29 | if (maxx < x) maxx = x 30 | if (maxy < y) maxy = y 31 | if (color != "" && maxcolor < color) maxcolor = color 32 | } 33 | 34 | # Sixelize 35 | for (y = maxy + 6 - maxy % 6; y >= 5; y -= 6) { 36 | for (color = 0; color <= maxcolor; color++) { 37 | printf "#%d", color 38 | for (x = 0; x <= maxx; x++) { 39 | sixel = 0 40 | bit = 1 41 | for (yy = 0; yy < 6; yy++) { 42 | pixel = Image[x, y - yy] 43 | if (pixel != "" && pixel == color) sixel += bit 44 | bit *= 2 45 | } 46 | printf "%c", sixel + 63 47 | } 48 | print "$" 49 | } 50 | print "-" 51 | } 52 | } 53 | 54 | function real(c) 55 | { 56 | return substr(c, 1, index(c, SUBSEP) - 1) + 0 57 | } 58 | 59 | function imag(c) 60 | { 61 | return substr(c, index(c, SUBSEP) + 1) + 0 62 | } 63 | 64 | function complex(x, y) 65 | { 66 | return x SUBSEP y 67 | } 68 | 69 | function add_complex(c1, c2) 70 | { 71 | return complex(real(c1) + real(c2), imag(c1) + imag(c2)) 72 | } 73 | 74 | function mul_complex(c1, c2 , x1, y1, x2, y2) 75 | { 76 | x1 = real(c1) 77 | y1 = imag(c1) 78 | x2 = real(c2) 79 | y2 = imag(c2) 80 | 81 | return complex(x1*x2 - y1*y2, x1*y2 + y1*x2) 82 | } 83 | 84 | function sprint_complex(c) 85 | { 86 | return "(" real(c) ", " imag(c) ")" 87 | } 88 | 89 | function isnan(n) 90 | { 91 | # Tests true for "inf", "-inf", "nan", "-nan" 92 | return n == 1/0 || n == -1/0 93 | } 94 | 95 | function mandel(c, z) 96 | { 97 | return add_complex(mul_complex(z, z), c) 98 | } 99 | 100 | function iterate_mandel(x, y, iterations , c, z, i) 101 | { 102 | c = complex(x, y) 103 | z = complex(0, 0) 104 | 105 | for (i = 0; i < iterations; i++) { 106 | z = mandel(c, z) 107 | if (isnan(real(z))) return i 108 | if (isnan(imag(z))) return i 109 | } 110 | 111 | return 0 112 | } 113 | 114 | function generate_mandel(Image, ncolors, x1, y1, x2, y2, width, height, 115 | ite, maxite, x, y, mx, my) 116 | { 117 | maxite = 1 118 | 119 | print "Generating..." 120 | for (x = 0; x < width; x++) { 121 | printf "%3.1f%%\n\033[A", 100 * x / width 122 | mx = x1 + (x2 - x1) * x / width 123 | for (y = 0; y < height; y++) { 124 | my = y1 + (y2 - y1) * y / height 125 | ite = iterate_mandel(mx, my, 100) 126 | Image[x, y] = ite 127 | if (ite > maxite) maxite = ite 128 | } 129 | } 130 | printf "\r \r" 131 | 132 | # Adjust colors 133 | print "Adjusting..." 134 | for (c in Image) { 135 | Image[c] = int(Image[c] * (ncolors - 1) / maxite) 136 | } 137 | } 138 | 139 | function zoom(Box, quadrant , x, y) 140 | { 141 | x = (quadrant == 2 || quadrant == 4) 142 | y = (quadrant == 1 || quadrant == 2) 143 | if (x) Box["x1"] = (Box["x1"] + Box["x2"]) / 2 144 | else Box["x2"] = (Box["x1"] + Box["x2"]) / 2 145 | if (y) Box["y1"] = (Box["y1"] + Box["y2"]) / 2 146 | else Box["y2"] = (Box["y1"] + Box["y2"]) / 2 147 | } 148 | 149 | function draw_mandel(Viewbox, width, height, ncolors , c, rc) 150 | { 151 | generate_mandel(Mandel, ncolors, Viewbox["x1"], Viewbox["y1"], Viewbox["x2"], Viewbox["y2"], width, height) 152 | 153 | print "Drawing..." 154 | print "\033Pq" 155 | 156 | print "#0;2;0;0;0" 157 | for (c = 1; c < 16; c++) { 158 | rc = 15 - c 159 | printf "#%d;2;%d;%d;%d\n", c, int(100 * c / 16), int(sqrt(1000 * sin(c * 3 / 16))), int(100 * sin(c * 3 / 16)) 160 | } 161 | 162 | draw_image(Mandel) 163 | 164 | printf "\033\\" 165 | } 166 | 167 | function show_help() 168 | { 169 | print " 1 | 2" 170 | print "---+---" 171 | print " 3 | 4" 172 | print 173 | print "Please type a quadrant to zoom in on, and press [Enter]." 174 | print 175 | print "Type q [Enter] to quit." 176 | } 177 | 178 | BEGIN { 179 | width = 700 180 | height = 700 181 | ncolors = 16 182 | Viewbox["x1"] = -2.2 183 | Viewbox["y1"] = -1.5 184 | Viewbox["x2"] = 0.8 185 | Viewbox["y2"] = 1.5 186 | draw_mandel(Viewbox, width, height, ncolors) 187 | show_help() 188 | } 189 | 190 | /^[1-4]$/ { 191 | zoom(Viewbox, $0) 192 | draw_mandel(Viewbox, width, height, ncolors) 193 | print "Quadrant? [1-4]" 194 | } 195 | 196 | /^[QqXx]|[Ee][Xx][Ii][Tt]/ { 197 | exit 0 198 | } 199 | 200 | /^[?Hh]/ { 201 | show_help() 202 | } 203 | -------------------------------------------------------------------------------- /text-test.sixel: -------------------------------------------------------------------------------- 1 | 2 | Alignment depends on font size, so this may not display correctly. The 3 | (future) solution is to detect or ask for the size of the font used. 4 | 5 | aaaaaaaaaaaaaa 6 | aaa aaa 7 | aaa aaa 8 | aaa aaa 9 | aaa aaa 10 | aaa aaa 11 | aaaaaaaaaaaaaa 12 |  Pq"1;1;64;64#0;2;97;97;97#1;2;97;94;94#2;2;97;88;82#3;2;97;85;75#4;2;97;97;94#5;2;97;75;66#6;2;91;53;41#7;2;97;66;56#8;2;97;75;63#9;2;88;47;31#10;2;97;82;75#11;2;97;78;69#12;2;88;50;35#13;2;85;41;28#14;2;94;69;60#15;2;97;91;85#16;2;91;56;41#17;2;82;38;25#18;2;88;53;44#19;2;97;91;88#20;2;85;44;35#21;2;85;44;28#22;2;85;47;35#23;2;97;85;78#24;2;94;66;53#25;2;97;94;88#26;2;94;60;47#27;2;94;75;66#28;2;91;56;44#29;2;97;94;91#30;2;88;50;38#31;2;91;50;38#32;2;82;38;22#33;2;82;35;22#34;2;75;31;19#35;2;78;35;25#36;2;94;69;56#37;2;78;35;22#38;2;75;35;22#39;2;94;72;63#40;2;82;44;31#41;2;82;41;28#42;2;94;78;72#43;2;75;28;19#44;2;72;31;22#45;2;85;50;38#46;2;91;63;50#47;2;94;75;69#48;2;91;60;47#49;2;82;35;19#50;2;75;28;16#51;2;72;28;16#52;2;72;28;19#53;2;69;28;16#54;2;69;25;19#55;2;66;25;16#56;2;88;50;31#57;2;91;56;47#58;2;69;31;22#59;2;69;25;16#60;2;69;28;19#61;2;72;31;25#62;2;78;28;16#63;2;63;22;16#64;2;66;22;16#65;2;78;41;25#66;2;60;19;16#67;2;69;28;22#68;2;63;22;13#69;2;66;25;13#70;2;66;22;13#71;2;94;72;60#72;2;60;22;13#73;2;56;22;16 13 | #0!29~^NFBBBr!28~$ #4!29?_!4?_C$#1!30?OGC??G$#11!30?_#8O#9OO#3C$#12!31?_#5G#2C#7G$#13!32?_#6G#10O$#14!33?_- 14 | #0!21~^NFN!4~!4?}!30~$#1!21?_??_#15!4?@??G#19@$#23!22?O!6?O#13C_#2O$#7!22?_#11O!5?K#21GO#3C$#4!23?GO#10!4?A#9Q#17B#14A$#24!23?_#25!5?_#16@#20C#18@$#26!30?_#22G#27_- 15 | #0!21~o???F^~~~G???@B!28~$#1!21?G!4?_???C!4?C$#15!21?E???O!4?A#24C??C#10G$#19!21?@#2O?C!5?_??@#19A#14O$#31!22?AOO!6?A#13W?G#39_$#4!22?_??G!4?O#8W#30@#26A#35O$#6!22?CA#20_#36_#5!4?@#16_#32E#33C#38_$#28!22?@@#25A#37!7?_#34w$#7!22?G#21G!7?@$#14!23?_G$#22!23?C#29@- 16 | #0!21~^F!4?@???_oow{!28~$#4!21?_#14_??O!7?CA#3@$!22?OB#22@@#1oA@!4?G?A$#25!22?G#26G!6?@#23O#25??C$#13!23?_S#41E???_??C#40?@$#8!23?C#31_G#42E???_?G$#9!23?O#20A#15_HC#17O!4?A$#32!24?G#11??GA#44OG$#27!27?O#37_C?@$#36!27?_#21G#10@#34EEB@$#28!28?C#12A#45OG$#43!29?G- 17 | #0!16~!5^K???FNG???F!10N^^^!19~$#4!16?_!4?O#11C??O!8?OO#10O!6?_$#25!17?_!4?G#9C!5?C!9?_#16_#1O#14_$#19!18?_#3_!4?O#32_!8?___#3O#21_#29?O#24_$#27!20?_??G???PO???OO$#1!21?BO??G?C#37_???_$#24!21?_A#13B!6?O!6?_$#46!22?@!8?O$#26!22?_#15O!6?A#34_$#31!23?_#5G#49?_??_#19@G!7?O!4?_$#14!24?D#8?O#2AG!9?O$#21!24?_#33??_!5?_$#47!24?A#7???C#16W#42C$#12!28?A#22A#43_$#17!28?@#30@#48G- 18 | #0!13~B@#34w?AGGAA?EC_?__???@?@???O?@@@!8?o#15C#1o$!13?S#36_?@#38K!4?@???_#17!4?_!7?O#26_O!6?C#51GO#29A#27G$#4!13?_#3A#35C??A??@!7?__#41?_#40_#22__#53G?CAAA#12G!6?_#2A#38G#46O$#25!13?G#18G#2@#52Oooo{KA?GQ]^ZNV^!4]UUA@G?E??GWO??G$#46!14?C#31A#44K?CE?_[WO#54G???OG#6!5?_#55GGKCC#31O#32OK!5?_$#57!14?O#17?A???@#58O#61___#46!12?_#36__!6?A#0!5@BN!10~$#60!16?_#28@#22@#13@#43???@#51AD@?C!4?@?!4@#30?O#9_!7?CC$#50!24?@#37!16?G?D???G?O$#62!42?_#59__o__#33_#3A$#54!43?A#43AC??W$#56!43?G#18@#13AC#24C???C_$#50!44?O#11@#25@#19AA- 19 | #0!14~w_#52BGBr?O__o!4G!8?C!6?ODB@#3G??C#27@$#10!14?@G!9?A!4?@#3@???A#27A#15@!9?G!4?A$#4!14?C#36C!7?A!4?@?C#0A#34G???C!7?_#18O#21C??@#25G#31A$#19!14?A#13@G!4?@?C#11A#53_O#19A!5?@B@@!9?O#0!4ow{!11~$#31!15?A!6?@#18@#20C#9C#55_oOO??O???G??CMWP`J#36_#4_#12C#50@AA#37@$#25!15?O#57O!8?@@#26C!5?C#30C#21C#66?OO#16@#32@#53!4?A#41??C#13C#49@$#34!16?C!4?C#16A#28?@#6?C#46@C#51GGG!7?A!7?AA#23G#57C$#47!16?_#60F??o!4?O#15A#64?__oo?O?G??C?O_m]C#65G$#44!17?O{CEGWWG#25???A#1A??AA#48???A#11@!7?G$#41!17?_#58?GG_#37C#24!6?C??C#59GG!6?@$#38!20?@#21A#5!7?@#4A#14C#63__oooggw_E$#2!32?@#13!5?A- 20 | #0!11~^!4NMG#44@ACG@#53OoB#63!5?AKKmm~~Nn[#34_?C#10G@!7?_$#2!11?_!4?O??O#58BF?A#54G#55KHBE_`pa!8?RN@#14COO!5?_$#1!12?O!6?_#46?_#60G?@#64Ou{x^]KPoO!5?BK#50O??_#0F!6N^^!9~$#36!12?_#19O??@#11A#15G?_#67?ELE#59_#66!7?B@@??oO#59_??A#17@#1K!6?O$#22!13?_#17_!4?CGO_#68!12?O#13!6?_#31O#36O#19A!4?O#25O??_$#3!14?O???_#52@??O_#32!19?_#45A#4?G#8O#3O#9_#30_#46_$#10!15?O#41_?A#48GO#40!22?G#49_#62?_#33_#21_#15O$#37!15?_#25?S#4O$#28!17?@#24C$#57!17?_- 21 | #0!9~xo_#53AHG??_!8?@#8_#9?C!8?GC?@#43?@#70???A#52__?@?A#4_O$!9?E#23G!8?@A#19@??C???G!4?O#31C?O???A#66oww{[W#53?@??O#38OG#14@#0_!8~$#2!10?@?_#24_!8?@???c#57C#21??C???_???A?@#32A@#34!7?_?@#2_#23O#3A$#14!10?E#18@O#37O!8?O#15G?O???G???GG#63@?@_?OG?CAae[??EM#24_#21@#40A#10C$#3!11?O#34H??_!8?@#11C??___!5?G#24GC#50G??A#13!8?_??C#15G$#6!11?G#60C#69E?@@#45?@A!8?C#2?G?G??G#59_?O??C!5?@??O??C#46G#25@$#38!11?E#64??EMM]W!9?@???@@@?@??O??C??@?_]EG?E#28O$#52!14?O?_@A?Oo_??@?AA!6?A#17?A#72?__#69!11?G$#59!14?@O??_w_#10C#14G!9?_???C#37O#12?A#69G$#13!14?_#55?O?C!8?@?BBBAAA??_@!4?A@?@??X@$#51!19?CG??_#33_#0G?!4O#13CC#20C#10O#49_!4?C$#4!20?@A??G!6?O#26?_#7?O#71?C#34?@$#22!20?C#20G#1CC??W!5?O#46??C$#25!22?A!4?G#5???_$#41!23?@?A#38A!9?A$#18!23?OA#12_#23!5?G$#27!23?AO- 22 | #0!13~}}{{!5w!7o!7_!8o!4w{{{}}!11~$#25!13?@?A!7?G#15G#23G#8?G!9?G#47G#55A?A!4?@#3?A#18@#36@#10@$#11!14?@!5?C!5?G#33@???@#64??AB??A?A#19G!7?A$#48!15?@#10A#1C!4?G!8?!4O!8?G???C??A$#21!16?@#14A???C!6?G#4OO!4?O#38CCC!8?@#20@$#37!17?@???A!5?C#53A!4?@!8?AA#14C??A$#51!18?@!5?@@!5?!4C#63?BB!4@?@@@$#18!18?A#52!5@??AA#32@@@#27!5?G#37??C!5?A$#19!18?C#9A!5?C#7???GG!4?G#10???G#2G!5?C$!19?C#13A!5?C#59??!5A@#13!5?C#22C!4?A$#34!22?!4A@?CCC?@??C#25!6?G!9?@$#24!22?C!8?!4G#6!7?C#46C#43A#11C$#16!23?C#30C#73!17?@- 23 | #0!64N 24 | \ 25 | 26 | -------------------------------------------------------------------------------- /Experiments.md: -------------------------------------------------------------------------------- 1 | # Sixel Experiments 2 | 3 | A collection of experiments with [sixel](https://en.wikipedia.org/wiki/Sixel) graphics. 4 | 5 | ## What is this? 6 | 7 | This is a collection of experiments with sixel graphics, imported from [coffee website](https://gitlab.com/Matrixcoffee/sixel-experiments) 8 | 9 | ## But Coffee, what on earth are sixel graphics? 10 | 11 | > 👉 Did you know: 12 | > 13 | > You can display actual bitmap images on the actual console in selected terminal emulators. 14 | > 15 | > [https://en.wikipedia.org/wiki/VT340](https://en.wikipedia.org/wiki/VT340) 16 | 17 | Observe: 18 | 19 | ![graphical "this is fine" meme in an xterm](experiments-screenshots/87f9a824b2d4d037.png) 20 | 21 | ## How can I display sixel graphics? 22 | 23 | ### First you need a sixel-capable terminal emulator 24 | 25 | [XTerm](https://invisible-island.net/xterm/) supports this, but needs a little nudging to enable: 26 | ``` 27 | $ xterm -xrm "XTerm*decTerminalID: vt340" -xrm "XTerm*numColorRegisters: 256" 28 | ``` 29 | But do you a favor and run the following: 30 | ``` 31 | $ echo "XTerm*decTerminalID: vt340" >> $HOME/.Xresources 32 | $ echo "XTerm*numColorRegisters: 256" >> $HOME/.Xresources 33 | $ echo "XTerm*disallowedWindowOps: 1,2,3,4,5,6,7,8,9,11,13,19,20,21,GetSelection,SetSelection,SetWinLines,SetXprop" >> $HOME/.Xresources 34 | $ xrdb $HOME/.Xresources 35 | ``` 36 | And all your XTerm sessions will have 256-color sixel graphics enabled by default. 37 | 38 | (The third line sets up some exceptions so we're allowed to query XTerm about its active screen size in pixels, from which we can then calculate the character cell size, which is kind of important to know when you want to align sixel graphics with text. Other terminal emulators already allow this by default.) 39 | 40 | The only _other_ sixel-capable X terminal emulator offered by _Debian Buster_ is [mlterm](http://mlterm.sourceforge.net). No special options are needed to enable sixel graphics. 41 | 42 | See the [libsixel home page](https://saitoha.github.io/libsixel/) for other _sixel-capable_ terminal emulators, including ones for the framebuffer console. 43 | 44 | ### Then you need some sixel graphics 45 | 46 | * Install `libsixel-bin` and use its `img2sixel` program to display most common image formats. 47 | * [ImageMagick](https://imagemagick.org/) (but **not** [GraphicsMagick](http://www.graphicsmagick.org/)!) can convert to and from sixel format. 48 | * All files in this repository ending in `.sixel` can simply be shown on the terminal with `cat`. 49 | * Working programs in this repository will emit sixel graphics, if you can figure them out. 50 | 51 | ## Status 52 | 53 | This repository is intended for experiments, and not to hold mature programs. Programs may be in various stages of completion, and various stages of documentation, including not at all. 54 | 55 | ## experiments-screenshots 56 | 57 | `population.awk`: 58 | 59 | ![Screenshot of population.awk](experiments-screenshots/Screenshot from 2020-09-05 23-03-33.png) 60 | 61 | `horigraph.awk`: 62 | 63 | ![Screenshot of horigraph.awk](experiments-screenshots/Screenshot from 2020-09-06 10-03-03.png) 64 | 65 | `population-bitmap.awk` (v1): 66 | 67 | ![Screenshot of population-bitmap.awk](experiments-screenshots/Screenshot from 2020-09-06 11-56-07.png) 68 | 69 | `population-bitmap.awk` (v2): 70 | 71 | ![Screenshot of population-bitmap.awk](experiments-screenshots/Screenshot from 2020-09-06 13-32-58.png) 72 | 73 | `bifur-bitmap.awk`: 74 | 75 | ![Screenshot of bifur-bitmap.awk](experiments-screenshots/Screenshot from 2020-09-06 16-53-04.png) 76 | 77 | `text-test.sixel`: 78 | 79 | ![Screenshot of text-test.sixel](experiments-screenshots/Screenshot from 2020-09-06 20-25-22.png) 80 | 81 | `mandelbrot-bitmap.awk` showing the full mandelbrot set: 82 | 83 | ![mandelbrot-bitmap.awk showing the full mandelbrot set](experiments-screenshots/Screenshot 3 mandelbrot-bitmap.awk.png) 84 | 85 | `mandelbrot-bitmap.awk` - usage - zooming in: 86 | 87 | ![mandelbrot-bitmap.awk - usage - zooming in](experiments-screenshots/Screenshot 2 mandelbrot-bitmap.awk.png) 88 | 89 | mandelbrot-bitmap.awk showing a zoomed-in view of the mandelbrot set: 90 | 91 | ![mandelbrot-bitmap.awk showing a zoomed-in view of the mandelbrot set](experiments-screenshots/Screenshot from 2020-09-08 01-51-27.png) 92 | 93 | sixkcd.bash black-on-white: 94 | 95 | ![Screenshot of sixkcd.bash showing xkcd comic 2154, black-on-white](experiments-screenshots/Screenshot 5 sixkcd.bash.png) 96 | 97 | sixkcd.bash white-on-black: 98 | 99 | ![Screenshot of sixkcd.bash showing xkcd comic 2154, white-on-black](experiments-screenshots/Screenshot 4 sixkcd.bash.png) 100 | 101 | ## Resources 102 | 103 | * [Sixel](https://en.wikipedia.org/wiki/Sixel) at Wikipedia 104 | * [Libsixel](https://saitoha.github.io/libsixel/) ([github](https://github.com/saitoha/libsixel)): Explanations, related projects, experiments-screenshots, examples. Its helper programs such as `img2sixel` are available from _Debian Buster_ package `libsixel-bin`. It also provides [Python](https://www.python.org) bindings, but sadly these aren't packaged for _Buster_. 105 | * [All About SIXELs](https://www.digiater.nl/openvms/decus/vax90b1/krypton-nasa/all-about-sixels.text) by Chris F. Chiesa. 106 | * [VT330/340 Programmer Reference Manual Volume 2 Chapter 14: Sixel Graphics](https://www.vt100.net/docs/vt3xx-gp/chapter14.html) 107 | * "[Jexer](https://jexer.sourceforge.io), a text windowing system that resembles Turbo Vision. The first and only text windowing system that supports mixed text and images to Xterm via sixel. Runs on Linux, Mac, and Windows. Written in Java. Feature complete." 108 | 109 | Supplemental resources: 110 | 111 | * [XTerm Control Sequences](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html) 112 | * [ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code) at Wikipedia 113 | * [POSIX.1-2017 Chapter 11: General Terminal Interface](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap11.html) 114 | 115 | ## Author 116 | 117 | [Coffee](https://gitlab.com/Matrixcoffee) 118 | 119 | ### Contact 120 | 121 | * Website: [https://open.source.coffee](https://open.source.coffee) 122 | * Mastodon: [@Coffee@toot.cafe](https://toot.cafe/@Coffee) 123 | 124 | ## License 125 | 126 | Copyright (C) 2020 by Coffee (@Coffee@toot.cafe) 127 | 128 | This program is free software: you can redistribute it and/or modify it under 129 | the terms of the GNU Affero General Public License as published by the Free 130 | Software Foundation, either version 3 of the License, or (at your option) any 131 | later version. 132 | 133 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 134 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 135 | PARTICULAR PURPOSE. See the GNU Affero General Public License for more 136 | details. 137 | 138 | The full text of this license can be found in the file called 139 | [LICENSE](https://gitlab.com/Matrixcoffee/sixel-experiments/blob/master/LICENSE). 140 | 141 | SPDX-License-Identifier: AGPL-3.0-or-later 142 | [[-> link](https://spdx.org/licenses/AGPL-3.0-or-later.html)] 143 | -------------------------------------------------------------------------------- /font-test-all.txt: -------------------------------------------------------------------------------- 1 | 2 | UTF-8 encoded sample plain-text file 3 | ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ 4 | 5 | Markus Kuhn [ˈmaʳkʊs kuːn] — 2002-07-25 CC BY 6 | 7 | 8 | The ASCII compatible UTF-8 encoding used in this plain-text file 9 | is defined in Unicode, ISO 10646-1, and RFC 2279. 10 | 11 | 12 | Using Unicode/UTF-8, you can write in emails and source code things such as 13 | 14 | Mathematics and sciences: 15 | 16 | ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ⎧⎡⎛┌─────┐⎞⎤⎫ 17 | ⎪⎢⎜│a²+b³ ⎟⎥⎪ 18 | ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β), ⎪⎢⎜│───── ⎟⎥⎪ 19 | ⎪⎢⎜⎷ c₈ ⎟⎥⎪ 20 | ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⎨⎢⎜ ⎟⎥⎬ 21 | ⎪⎢⎜ ∞ ⎟⎥⎪ 22 | ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (⟦A⟧ ⇔ ⟪B⟫), ⎪⎢⎜ ⎲ ⎟⎥⎪ 23 | ⎪⎢⎜ ⎳aⁱ-bⁱ⎟⎥⎪ 24 | 2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm ⎩⎣⎝i=1 ⎠⎦⎭ 25 | 26 | Linguistics and dictionaries: 27 | 28 | ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn 29 | Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ] 30 | 31 | APL: 32 | 33 | ((V⍳V)=⍳⍴V)/V←,V ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈ 34 | 35 | Nicer typography in plain text files: 36 | 37 | ╔══════════════════════════════════════════╗ 38 | ║ ║ 39 | ║ • ‘single’ and “double” quotes ║ 40 | ║ ║ 41 | ║ • Curly apostrophes: “We’ve been here” ║ 42 | ║ ║ 43 | ║ • Latin-1 apostrophe and accents: '´` ║ 44 | ║ ║ 45 | ║ • ‚deutsche‘ „Anführungszeichen“ ║ 46 | ║ ║ 47 | ║ • †, ‡, ‰, •, 3–4, —, −5/+5, ™, … ║ 48 | ║ ║ 49 | ║ • ASCII safety test: 1lI|, 0OD, 8B ║ 50 | ║ ╭─────────╮ ║ 51 | ║ • the euro symbol: │ 14.95 € │ ║ 52 | ║ ╰─────────╯ ║ 53 | ╚══════════════════════════════════════════╝ 54 | 55 | Combining characters: 56 | 57 | STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑ 58 | 59 | Greek (in Polytonic): 60 | 61 | The Greek anthem: 62 | 63 | Σὲ γνωρίζω ἀπὸ τὴν κόψη 64 | τοῦ σπαθιοῦ τὴν τρομερή, 65 | σὲ γνωρίζω ἀπὸ τὴν ὄψη 66 | ποὺ μὲ βία μετράει τὴ γῆ. 67 | 68 | ᾿Απ᾿ τὰ κόκκαλα βγαλμένη 69 | τῶν ῾Ελλήνων τὰ ἱερά 70 | καὶ σὰν πρῶτα ἀνδρειωμένη 71 | χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά! 72 | 73 | From a speech of Demosthenes in the 4th century BC: 74 | 75 | Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι, 76 | ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς 77 | λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ 78 | τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿ 79 | εἰς τοῦτο προήκοντα, ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ 80 | πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν 81 | οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι, 82 | οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν 83 | ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον 84 | τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι 85 | γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν 86 | προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους 87 | σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ 88 | τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ 89 | τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς 90 | τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον. 91 | 92 | Δημοσθένους, Γ´ ᾿Ολυνθιακὸς 93 | 94 | Georgian: 95 | 96 | From a Unicode conference invitation: 97 | 98 | გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო 99 | კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს, 100 | ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს 101 | ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი, 102 | ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება 103 | ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში, 104 | ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში. 105 | 106 | Russian: 107 | 108 | From a Unicode conference invitation: 109 | 110 | Зарегистрируйтесь сейчас на Десятую Международную Конференцию по 111 | Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии. 112 | Конференция соберет широкий круг экспертов по вопросам глобального 113 | Интернета и Unicode, локализации и интернационализации, воплощению и 114 | применению Unicode в различных операционных системах и программных 115 | приложениях, шрифтах, верстке и многоязычных компьютерных системах. 116 | 117 | Thai (UCS Level 2): 118 | 119 | Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese 120 | classic 'San Gua'): 121 | 122 | [----------------------------|------------------------] 123 | ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่ 124 | สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา 125 | ทรงนับถือขันทีเป็นที่พึ่ง บ้านเมืองจึงวิปริตเป็นนักหนา 126 | โฮจิ๋นเรียกทัพทั่วหัวเมืองมา หมายจะฆ่ามดชั่วตัวสำคัญ 127 | เหมือนขับไสไล่เสือจากเคหา รับหมาป่าเข้ามาเลยอาสัญ 128 | ฝ่ายอ้องอุ้นยุแยกให้แตกกัน ใช้สาวนั้นเป็นชนวนชื่นชวนใจ 129 | พลันลิฉุยกุยกีกลับก่อเหตุ ช่างอาเพศจริงหนาฟ้าร้องไห้ 130 | ต้องรบราฆ่าฟันจนบรรลัย ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ 131 | 132 | (The above is a two-column text. If combining characters are handled 133 | correctly, the lines of the second column should be aligned with the 134 | | character above.) 135 | 136 | Ethiopian: 137 | 138 | Proverbs in the Amharic language: 139 | 140 | ሰማይ አይታረስ ንጉሥ አይከሰስ። 141 | ብላ ካለኝ እንደአባቴ በቆመጠኝ። 142 | ጌጥ ያለቤቱ ቁምጥና ነው። 143 | ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው። 144 | የአፍ ወለምታ በቅቤ አይታሽም። 145 | አይጥ በበላ ዳዋ ተመታ። 146 | ሲተረጉሙ ይደረግሙ። 147 | ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል። 148 | ድር ቢያብር አንበሳ ያስር። 149 | ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም። 150 | እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም። 151 | የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ። 152 | ሥራ ከመፍታት ልጄን ላፋታት። 153 | ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል። 154 | የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ። 155 | ተንጋሎ ቢተፉ ተመልሶ ባፉ። 156 | ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው። 157 | እግርህን በፍራሽህ ልክ ዘርጋ። 158 | 159 | Runes: 160 | 161 | ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ 162 | 163 | (Old English, which transcribed into Latin reads 'He cwaeth that he 164 | bude thaem lande northweardum with tha Westsae.' and means 'He said 165 | that he lived in the northern land near the Western Sea.') 166 | 167 | Braille: 168 | 169 | ⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌ 170 | 171 | ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞ 172 | ⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎ 173 | ⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂ 174 | ⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙ 175 | ⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑ 176 | ⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲ 177 | 178 | ⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ 179 | 180 | ⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹ 181 | ⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞ 182 | ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕ 183 | ⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹ 184 | ⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎ 185 | ⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎ 186 | ⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳ 187 | ⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞ 188 | ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ 189 | 190 | (The first couple of paragraphs of "A Christmas Carol" by Dickens) 191 | 192 | Compact font selection example text: 193 | 194 | ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789 195 | abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ 196 | –—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд 197 | ∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა 198 | 199 | Greetings in various languages: 200 | 201 | Hello world, Καλημέρα κόσμε, コンニチハ 202 | 203 | Box drawing alignment tests: █ 204 | ▉ 205 | ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳ 206 | ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳ 207 | ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳ 208 | ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳ 209 | ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎ 210 | ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏ 211 | ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ ▗▄▖▛▀▜ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█ 212 | ▝▀▘▙▄▟ 213 | --------------------------------------------------------------------------------