Графика в терминале

    Эта история началась, когда я узнал о существовании bpytop. Меня поразила детализация графиков и я начал разбираться как это сделано. Оказалось, что для вывода графиков использовались символы алфавита Брайля, представляющие из себя комбинацию из 8 точек: 2 точки в ширину и 4 точки в высоту. Поискав готовые решения, использующие этот подход, я нашел на реддите анонс такого проекта. В первом же комментарии анонса я прочитал:
    Это конечно круто, но почему люди просто не переоткроют для себя ReGIS (векторную графику в терминале) и sixel (пиксельную графику в терминале).
    До этого момента я ничего не знал про sixel. Копнув глубже я выяснил, что в теории sixel должен поддерживаться xterm-ом. Я запустил xterm на своей ubuntu 20.04 в режиме эмуляции vt340

    xterm -xrm "XTerm*decTerminalID: vt340" -xrm "XTerm*numColorRegisters: 256"

    выполнил вот такую команду (convert это команда из пакета imagemagick)

    clear && convert <(curl -s https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png) sixel:-

    и увидел вот это:

    image
    Вау, работает!

    Первым делом я проверил, что по sixel можно найти на хабре. Оказалось, что не много. Есть очень краткая статья 2010-го года без технических подробностей и упоминание в комментариях к статье о портировании Far на линукс. Давайте разберемся, как работает sixel и как с его помощью можно рисовать в совместимом терминале.

    Включение режима sixel осуществляется escape последовательностью DCSp1;p2;p3;q, где DCS это Device Control Sequence (может быть либо восьмибитным символом с десятичным значением 144, либо последовательностью двух семибитных символов «Escape», «P». Параметры p1, p2 и p3 необязательны.
    p1 Pixel Aspect Ratio (Vertical:Horizontal)
    Не указан 2:1 (default)
    0, 1 2:1
    2 5:1
    3, 4 3:1
    5, 6 2:1
    7, 8, 9 1:1

    Этот параметр является устаревшим. В современном коде его надо выставлять в 0 и использовать атрибут управления растром в sixel строке. Подробности можно посмотреть в документации.

    p2 может принимать 3 значения и определяет как терминал рисует фоновый цвет.
    p2 Что делает
    0 or 2 (default) Пикселы со значением 0 рисуются текущим фоновым цветом.
    1 Цвет пикселов со значением 0 не меняется.

    Параметр p3 управляет горизонтальным шагом сетки (расстоянием между соседними пикселями). Этот параметр игнорируется если у устройства вывода неизменяемый шаг сетки.

    В своих экспериментах в xterm-е я всегда входил в sixel режим при помощи последовательности 0x1bPq (0x1b — escape) не используя опциональные параметры.

    Выключение sixel режима осуществляется последовательностью ST (String Terminator). ST может быть либо восьмибитным символом с десятичным значением 156 либо последовательностью двух семибитных символов «Escape, backslash» (ESC \).

    После перевода устройства вывода в sixel режим нам нужно подать на него графические данные. Название sixel является производной от six pixels. В режиме sixel мы рисуем за раз столбик из 6-ти пикселов (младший бит является верхним). Отрисовка осуществляется выбранным цветом (об этом чуть позже). Значение одного сиксела может быть от 0 (все биты 0) до 63 (все биты 1). Это значение прибавляется к 63 (ascii ‘?’). Таким образом пустой сиксел представляется символом ‘?’, а сиксел у которого все биты выставлены в 1 символом ‘~’.

    Формат sixel предусматривает примитивную компрессию. Конструкция ‘!42~’ означает, что мы хотим вывести сиксел ‘~’ 42 раза. В официальной документации не упомянуты ограничения на значения счетчика. При этом известно, что vt240 при дампе графических данных не использует значения больше 255.

    При выводе sixel строки есть 2 способа управления курсором. Символ ‘$’ переводит курсор в начало той же строки. Это позволяет выводить пикселы разного цвета. Можно выбрать цвет, вывести набор сикселов, вернуться в начало той же строки, выбрать другой цвет, вывести другой набор сикселов. После того, как текущая строка прорисована как надо, можно воспользоваться символом ‘-’ и перевести курсор на следующую строку.

    Управление цветом осуществляется 2 этапа. Сперва нам надо определить цветовые регистры. Это можно сделать командой #NN;p1;p2;p3;p4. Здесь

    • NN номер регистра (от 0 до 255)
    • p1 — тип цветового пространства (1 — HLS или 2 — RGB)
    • p2, p3, p4 — значения hue, lightness, saturation для HLS или red, green, blue для RGB. Разрешенные значения параметров от 0 до 100 для всех, кроме hue, который может изменяться от 0 до 360.

    Теперь для переключения на определенный цвет нам надо использовать команду вида #NN.

    Вооруженные этой информацией мы можем написать код, который выведет нам вот такое изображение:

    image

    Для сравнения вот как будет выглядеть то же изображение выведенное кодом с использованием символов алфавита Брайля:

    image

    И то же изображение выведенное кодом с использованием простого ascii:

    image
    Реклама
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее

    Комментарии 41

      +1
      off По поводу ASCII, может хаброобщество знает ответ на исторический вопрос.
      Однажды я увидел очень старую распечатку на бумажной ленте. Даже не матричный принтер, а электрическая печатная машинка. Погуглил и неожиданно нашел с описанием.
      «ASCII JESUS SUPERSTAR (original print. Center for Computer Sciences, Dept. of Mathematics, Tartu University, pre-PC computer/ascii art wave in Soviet Union, late 1970s. 42x82 cm, framed)»
      Кто-нибудь знает историю происхождения этой картинки?
      Распечатка на ленте
      image
        +1
        очень старую распечатку на бумажной ленте

        Тогда уж вспомним про «кошечку».
          0
          Просто уточнение — это не «электрическая печатная машинка», это советский клон IBM'овского принтера.
            +1
            Я подумал о печатной машинке Консул, наподобие такого подключения к ЭВМ — www.youtube.com/watch?v=SSYvCvnd2zo
            +1
            О да, у меня в комнате такую родители повесили :-)
              +1
              Судя по названию, альтернативный постера мюзикла «Jesus Christ Superstart», созданный в частном порядке на матфаке Тартусского университета в конце 1970-ых.

              В то время был расцвет ASCII-art'а в СССР, разумеется, у тех, у кого был доступ к технике. Были и умельцы, которые с произвольной картинки делали ее ASCII-версию, потом эти «картинки» на перфолентах бродили по разным вычислительным центрам. В одном из фильмов так даже «фотографию» главной героини распечатывали.

              А еще конец семидесятых — период фанатства этой рок-оперой, особенно после ее релкамы в передаче Севы Новгородцева. Легально ее поставят в 1989 году в Рыбинске, а до этого — десять лет подполья. Причем некоторые умудрялись устраивать и полу-легальные коллективные прослушивания с винила или катушек в актовых залах. Видимо, сначала «лекция» о буржуазной музыке, которая использует религию для развращения умов молодежи, а потом — «демонстрация» того, чего советский человек должен был избегать. Примерно так же слушали «Emerson, Lake and Palmer», только под соусом «русская классическая музыка в современной обработке». Видимо, под такое полу-легальное коллективное прослушивание и сделали этот постер…
              0

              Только вот по моему вся эта красота все равно требует видеокарту, и отрисовать картинку на сервере (без графического стека) не получается. Или все таки можно?

                +8
                Видеокарта тут не нужна. Это фича эмулятора терминала. Если эмулятор поддерживает sixel то отобразит картинку. Ссылки по теме:
                en.wikipedia.org/wiki/VT320
                en.wikipedia.org/wiki/Sixel
                  +4

                  В linux так то вообще есть виртуальные фреймбуфферы и вы можете на сервере без видеокарты запускать GUI приложения.

                    0
                    О. Не знал. Тыкнете меня в ссылку для начача изучения. Спасибо
                    0
                    В свое время python + phantomjs были сильной связкой. Даже графические капчи можно было решать на сервере без графики как таковой
                  +3

                  проверил в iterm2 – работает без дополнительных настроек. правда если переключиться в mc по ⌃O, то при переключении обратно картинка заменяется на однотонный прямоугольник :) ещё картинку из iterm можно drag-and-drop-нуть в файндер – он сохраняет текстовый файл с escape-последовательностями, но что-то пропускает – повторно вывести её в терминал через cat уже не выходит…

                    0

                    c iterm2 идет imgcat, очень удобно:


                    $ imgcat picture.png
                      0
                      c iterm2 идет imgcat, очень удобно:

                      странно, но у меня нет. iTerm 3.4.4
                        0

                        iTerm -> Install Shell Integration

                          0
                          Спасибо, не знал. Жаль svg не понимает
                    +1
                    На macOS в Terminal.app не работает.
                      0
                      Там нет поддержки vt340. Надо поставить более нормальный терминал. Например, в том же iTerm2 работает.
                        0
                        а какой смысл в этих всех режимах эмуляции по типу vt340?
                          0
                          Они разные команды поддерживают для всяких плюшек помимо простого вывода текста. Там обычно есть поддержка ANSI и прочего. Что-то пришло из-за железа, что-то чисто для решения каких-то софтовых ограничений или особенностей связи.
                          У них корни идут в древние 70-80-ые годы, когда на них ещё динозавры сочиняли свои мемуары для потомков.
                      +2
                      Никогда-бы не подумал что текстовые терминалы умеют графику.
                      Это, походу, какая-то очень специфическая фича от старых терминалов типа VT3xx. Удивлён что её умеет xterm. Хотелось-бы получить файл который-бы можно было сделать cat и получить в консоли картинку =) Чтобы проверить какой эмулятор терминала поддерживает графику а какой нет.
                        +6

                        Если я правильно угадал, то вот в этой команде


                        convert <(curl -s https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png) sixel:-

                        конечный минус является указателем на stdout, и его можно заменить на имя файла.

                          +2
                          Это фича convert:
                          man convert
                          By default, the image format of `file' is determined by its magic number. To specify a particular image format, precede the filename with
                          an image format name and a colon (i.e. ps:image) or specify the image type as the filename suffix (i.e. image.ps). Specify 'file' as '-'
                          for standard input or output.


                          Т.е. можно sixel:filename можно filename.sixel.
                          +1
                          У меня почему-то не работает. Если перенаправить вывод в файл, то он создаётся, и весь код там есть. Но ни xterm, ни LXTerminal ничего не выводят, даже пустой строки.
                          Видимо, нужно что-то настроить или доустановить.
                          Upd. Разобрался. Вот здесь есть проект, посвящённый выводу видео FFmpeg напрямую в терминал через sixel, и там подробно рассказывается, что нужно сделать. Требуется поправить .Xresources и, если всё равно не поможет, пересобрать xterm с поддержкой sixel (опция --enable-sixel-graphics в ./configure).
                            0

                            я воспользовался онлайн конвертером, скачал, вызвал cat на получившемся файле
                            https://s121.convertio.me/p/DdnUpeF2kNmTYkk8hOZfSA/7139a098c74878e07ec4f9107a48913f/Lenna__test_image_.sixel

                            0
                            Взял на заметку, спасибо!)
                              0
                              PIU-PIU HD? ;)
                                0

                                археология сикеля

                                  0
                                  Посмотрим)
                                +3
                                впечатляет! вы меня удивили ) после стольких лет в терминале увидеть такое )
                                  +1
                                  виндовые ssh клиенты такое поддерживают?
                                  Сходу в putty ничего не вышло
                                    0
                                    В cygwin работает.
                                    0

                                    Сделайте лучше так, чтобы GUI-библиотеки могли прозрачно работать в текстовом 80x25.

                                      +1
                                      Правильно ли я понимаю, что теперь я могу делать чисто консольное приложение в терминале с отображением графики (если требуется взаимодействие только с клавиатурой)? Есть ли какой-то образец, чтобы посмотреть как это возможно?
                                        +3

                                        Что значит теперь? Автор же пишет, что эта фича появилась в VT340, который поступил в продажу где-то между 1987 и 1990 (не смог найти в интернете более точную информацию).

                                        0
                                        А нет бенчмарка на анимацию? Как быстро и часто можно обновлять экран с изображением?
                                          0
                                          Анимация точно возможна и стриминг видео тоже. Так что скорее всего 25 кадров в секунду достижимы. Думаю главным ограничительным фактором в данном случае будет размер области, требующей обновления. Вполне возможно, что 4k video сиксельная графика в реальном времени не потянет.
                                          0
                                          Похоже, кроме xterm из коробки не поддерживается нигде в линуксе. Так что правильнее было бы озаглавить статью «Графика в терминале VT320 или его эмуляторах».
                                            0
                                            Так, а Гуй с кнопками таким образом можно сорганизовать?
                                              0

                                              На "Апогее" можно похожим способом через ВГ75 графику выводить.

                                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                              Самое читаемое