ASCII-арт в браузере и терминале
Идея проста: взять изображение, измерить яркость каждого пикселя и заменить его символом. Плотные символы вроде @ или # представляют тёмные области, а более светлые, такие как . или (пробел), представляют яркие области. Соберите достаточное количество таких замен в сетку — и вы получите узнаваемое изображение, полностью состоящее из текста.
Эта базовая идея лежит в основе как ASCII-арта в терминале, так и ASCII-арта в браузере, а современные реализации вышли далеко за пределы классической 7-битной ASCII.
Ключевые моменты
- ASCII-арт сопоставляет яркость пикселей с символами из отсортированной палитры, где плотные глифы вроде
@представляют тёмные области, а разреженные вроде.— светлые - Блочные элементы Unicode и паттерны Брайля обеспечивают значительно более высокое разрешение по сравнению с традиционными палитрами ASCII-символов
- Реализации в браузере опираются на пиксельные данные
<canvas>и моноширинный CSS, в то время как терминальные рендереры используют ANSI escape-последовательности для цвета - Возможности терминалов сильно различаются — от базовой 16-цветной ANSI до 24-битного true color, SIXEL и графического протокола Kitty
Как работает сопоставление пикселей и символов
Каждый ASCII-рендерер следует примерно одному и тому же конвейеру:
- Разбить исходное изображение или видеокадр на сетку ячеек
- Вычислить среднюю яркость (luminance) каждой ячейки
- Сопоставить это значение яркости с символом из отсортированной палитры
- Вывести полученную сетку символов с опциональным цветом
Базовая реализация на JavaScript выглядит так:
const palette = ' .:-=+*#%@';
function brightnessToChar(brightness) {
const index = Math.floor((brightness / 255) * (palette.length - 1));
return palette[index];
}
Здесь предполагается, что brightness — это значение от 0 (чёрный) до 255 (белый). Функция нормализует его до индекса в строке палитры, где более ранние символы представляют светлые тона, а более поздние — тёмные.
Качество результата сильно зависит от вашей палитры символов. Классическая ASCII даёт около 10–15 полезных уровней затенения. Современные реализации справляются лучше.
За пределами ASCII: текстовая графика с Unicode
Текстовая графика с Unicode открывает значительно более высокое разрешение. Вместо разреженной ASCII-палитры можно использовать:
- Блочные элементы (
█ ▓ ▒ ░) для четырёх уровней затенения на ячейку - Паттерны Брайля (
⣿ ⠿ ⠛), которые кодируют до 8 точек в одном символе, обеспечивая более высокое эффективное разрешение по сравнению с традиционными ASCII-палитрами - Символы рисования рамок для структурированных макетов и границ
Chafa, программа для просмотра изображений в терминале, использует блочные символы Unicode и символы Брайля для рендеринга изображений почти фотографического качества в терминале. Разница по сравнению с обычным ASCII разительна.
Discover how at OpenReplay.com.
ASCII-арт в браузере: подходы с Canvas и WebGL
JavaScript-рендеринг ASCII в браузере обычно использует элемент <canvas> в качестве источника изображения. Процесс:
- Нарисовать изображение или видеокадр на невидимом canvas
- Прочитать пиксельные данные с помощью
ctx.getImageData() - Разбить сетку пикселей на ячейки и сопоставить каждую с символом
- Отрендерить результат в элемент
<pre>или обратно на canvas с помощьюfillText()
Библиотеки вроде p5.js делают это простым, позволяя обрабатывать живые потоки с веб-камеры или видеокадры в реальном времени. Для более высокой производительности шейдеры WebGL могут обрабатывать выборку яркости и поиск символов на GPU, что важно при рендеринге полноценного видео с частотой 30 кадров в секунду.
Для статического отображения настройка HTML/CSS минимальна, но важна:
.ascii-art {
font-family: monospace;
white-space: pre;
line-height: 1;
letter-spacing: 0;
}
Без white-space: pre браузер схлопывает пробелы и разрушает макет. Без моноширинного шрифта символы имеют неравную ширину, и сетка разваливается. Установка letter-spacing: 0 предотвращает тонкие горизонтальные промежутки, которые некоторые браузеры добавляют по умолчанию.
ASCII-графика в терминале: ANSI-цвет и вариативность протоколов
В терминальных средах ASCII или Unicode-символы выводятся в стандартный вывод. Цвет добавляется через ANSI escape-последовательности. Современные терминалы поддерживают 24-битный (true color) вывод:
printf '\033[38;2;255;100;0m%s\033[0m\n' "orange text"
Это устанавливает цвет переднего плана в RGB(255, 100, 0) с помощью последовательности 38;2;R;G;B, затем сбрасывает форматирование с помощью \033[0m.
Инструменты вроде jp2a и ascii-image-converter используют этот подход для создания цветной терминальной ASCII-графики из файлов изображений.
Однако возможности терминалов значительно различаются. Некоторые терминалы поддерживают только базовую 16-цветную ANSI. Другие поддерживают 256-цветный режим, полный 24-битный true color, графику SIXEL или графический протокол Kitty, который может рендерить настоящие пиксельные изображения внутри терминала, а не символьные приближения. Обработка ширины Unicode также различается между терминалами, поэтому символы Брайля или широкие символы могут смещаться в зависимости от окружения.
Заключение
Пишете ли вы JavaScript ASCII-рендерер для браузера или передаёте данные изображения через терминальный инструмент, базовая логика идентична: пиксели становятся символами, яркость становится плотностью, а цвет становится escape-кодами или CSS. Браузер даёт вам точный контроль над шрифтами и макетом, в то время как терминал даёт скорость и композируемость. Выбор среды определяет инструментарий, но конвейер преобразования — выборка, измерение, сопоставление, рендеринг — остаётся неизменным.
Часто задаваемые вопросы
Большинство моноширинных символов выше, чем шире, поэтому каждая ячейка символа не является идеальным квадратом. Это вертикальное растяжение искажает изображение. Вы можете компенсировать это, настроив line-height в CSS, масштабировав исходное изображение до неквадратного соотношения сторон перед преобразованием или выбирая меньше строк относительно столбцов.
Упорядочьте символы по их визуальной плотности, от самого светлого к самому тёмному. Более длинная палитра даёт больше уровней затенения и более плавные градиенты. Протестируйте свою палитру, отрендерив градиентное изображение и проверив наличие видимых полос. Блочные элементы Unicode и паттерны Брайля обеспечивают более тонкую детализацию по сравнению со стандартными ASCII-символами.
Да. В браузере рисуйте каждый видеокадр на невидимом canvas, читайте пиксельные данные и сопоставляйте ячейки с символами на каждом кадре анимации. Для приемлемой производительности при 30 кадрах в секунду держите разрешение сетки символов умеренным или переносите вычисление яркости на WebGL-шейдер. Терминальные инструменты вроде Chafa также поддерживают видеовход.
Символы Брайля относятся к Unicode, и их отображаемая ширина зависит от эмулятора терминала и активного шрифта. Некоторые терминалы обрабатывают их как широкие символы, другие — как узкие. Если ваш вывод выглядит сломанным, протестируйте с другим терминалом или шрифтом. Инструменты вроде Chafa определяют возможности терминала и соответственно настраивают режим вывода.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.