9e81d7a3e022692bc1a00974f2e622639f95748f
CLI-утилита (Pillow) для превращения текста в картинку рукописного текста. Полная поддержка кириллицы, синие чернила с имитацией письма ручкой (дрейф давления, полупрозрачность, неровный край), корректное выравнивание (б/й/н на baseline, р/у/д с хвостами, точки внизу, спецсимволы), перенос по словам + сохранение переносов строк, тетрадная бумага, --list-fonts. run.sh: команды-обёртки (init/upd/render/lined/big/calm/plain/poetry/render-file/render-stdin/list-fonts/examples). Документация: README.md, AGENTS.md. Примеры в examples/.
handwrite.py
Python-скрипт, превращающий текст в картинку рукописного текста с поддержкой
кириллицы (полный русский алфавит, включая Ё, щ, ъ, э, ю, я).
Чернила — синие, с имитацией письма ручкой.
Возможности
- 🖋️ Синие чернила «как рукой»: имитация письма ручкой — дрейф «давления» (коррелированные тёмные/светлые участки), полупрозрачные чернила, неровный край мазка
- ✅ Полная поддержка кириллицы (автоподбор рукописного шрифта с проверкой
наличия всех глифов; приоритет —
Marker Felt) - 📐 Корректное выравнивание: обычные буквы (
а,о,н,б,й) на одной базовой линии, буквы с нижними выносными (р,у,д,ц,щ) — с хвостами ниже, точки/запятые — внизу строки, спецсимволы ($ ~ % @ # & …) — по дизайну шрифта - 📝 Перенос по словам + сохранение
\nиз входного файла/STDIN - 📓 «Тетрадная» линейная бумага (
--lined) - 🎨 Настройка цвета чернил/бумаги/линий, размера шрифта, полей
- 📥 Ввод: аргументом, из файла (
-i, с переносами строк), через STDIN - 🔒 Воспроизводимый результат через
--seed
Установка
pip install -r requirements.txt # нужна только Pillow
или через обёртку (создаст venv):
./run.sh init
Быстрый старт
# текст аргументом
python3 handwrite.py "Привет, мир!" -o hello.png
# тетрадная бумага
python3 handwrite.py "Привет, мир!" -o hello.png --lined
# из файла с переносами строк (каждая строка файла → строка на картинке)
python3 handwrite.py -i text.txt -o letter.png --lined
# через STDIN
echo "Мама мыла раму" | python3 handwrite.py -o out.png
Параметры
| Параметр | По умолчанию | Описание |
|---|---|---|
text |
— | Текст для рендера (позиционный). |
-i, --input |
— | Файл с текстом (UTF-8); переносы строк сохраняются. - = STDIN, иначе при отсутствии текста — STDIN. |
-o, --output |
handwriting.png |
Выходной PNG. |
--font |
авто | Путь к шрифту (path или path:index в .ttc). Иначе авто-подбор рукописного с кириллицей. |
--font-size |
44 |
Размер шрифта (pt). |
--line-spacing |
1.6 |
Множитель межстрочного интервала. |
--margin |
64 |
Поля вокруг текста (px). |
--chars-per-line |
48 |
Примерная ширина строки в символах для переноса. |
--ink |
#1a3b8c |
Цвет чернил (#RRGGBB). По умолчанию — синий. |
--paper |
#ffffff |
Цвет бумаги (#RRGGBB). |
--lined |
выкл. | Рисовать «тетрадные» линии. |
--lined-color |
#cfe8ff |
Цвет линий бумаги. |
--jitter |
1.0 |
Сила «рукописного» дрожания (0 — ровный текст). |
--no-rotate-lines |
выкл. | Отключить лёгкий поворот строк. |
--seed |
случайный | Зерно ГПСЧ для воспроизводимости. |
Примеры использования
# крупный текст на тёплой бумаге
python3 handwrite.py "Стихи на полях" -o poem.png --font-size 56 --paper "#fdf6e3" --lined
# «спокойный» почерк — меньше колебаний давления, фиксированный seed
python3 handwrite.py "Ровный аккуратный текст" -o neat.png --jitter 0.3 --seed 42
# полностью ровный текст (без дрожания и поворота)
python3 handwrite.py "Как печатный" -o plain.png --jitter 0 --no-rotate-lines
# другой синий оттенок чернил
python3 handwrite.py "Глубокий синий" -o deep.png --ink "#0f2d78"
# широкий формат (длинные строки)
python3 handwrite.py -i long_text.txt -o wide.png --chars-per-line 80 --margin 40
# другой рукописный шрифт (Snell Roundhand)
python3 handwrite.py "Текст" --font "/System/Library/Fonts/Supplemental/SnellRoundhand.ttc:0"
# многострочный файл через STDIN
cat text.txt | python3 handwrite.py -o out.png --lined
# тёмная бумага, светлые чернила (например, для презентации)
python3 handwrite.py "Белым по тёмному" -o dark.png --ink "#cfe8ff" --paper "#1a2238"
Команды run.sh
Удобные обёртки для типовых задач (вывод — в out/):
| Команда | Описание |
|---|---|
./run.sh init |
Создать venv и установить зависимости |
./run.sh upd |
Обновить зависимости |
./run.sh render "текст" |
Рендер текста → out/handwriting.png |
./run.sh lined "текст" |
Рендер на тетрадной бумаге → out/handwriting.png |
./run.sh big "текст" |
Крупный шрифт (64pt) на тёплой бумаге |
./run.sh calm "текст" |
«Спокойный» почерк (jitter 0.3, seed 42) |
./run.sh plain "текст" |
Ровный текст (без дрожания/поворота) |
./run.sh render-file file |
Рендер файла (с переносами строк) |
./run.sh poetry file |
Многострочный файл → тетрадь, крупный шрифт |
./run.sh render-stdin |
Чтение из STDIN (echo "..." | ./run.sh render-stdin) |
./run.sh list-fonts |
Показать доступные рукописные шрифты с кириллицей |
./run.sh examples |
Перегенерировать примеры в examples/ |
Доп. опции handwrite.py передаются после -- (или просто в конце):
./run.sh render "Текст" -- --jitter 0.4 --seed 7
./run.sh render-file text.txt --chars-per-line 60
./run.sh lined "Текст" -- --ink "#0f2d78"
Примеры
examples/
├── blue_pen.png # синий текст «от руки»
├── blue_pen_lined.png # синий текст на тетради
├── multiline.png # из файла с переносами строк
└── sample_input.txt # пример входного файла
Перегенерировать: ./run.sh examples.
Подбор шрифта
Скрипт автоматически ищет рукописный шрифт с полным покрытием кириллицы:
- Проверяет приоритетные системные шрифты (
Marker Felt, затемSnell Roundhand). - Сканирует системные каталоги, отбирая «рукописные» имена и проверяя все глифы кириллицы.
- В крайнем случае берёт любой шрифт с поддержкой кириллицы.
Проверка глифов — без сторонних библиотек (только Pillow): каждый символ
рендерится и сравнивается с формой notdef-глифа. Узкие буквы (например «г»)
неотличимы от notdef по ширине, поэтому сравнение делается по форме, а не по
ширине.
Требования
- Python 3.8+
- Pillow (
pip install pillow)
Файлы проекта
hand-writter/
├── handwrite.py # основной скрипт
├── requirements.txt # Pillow
├── run.sh # команды-обёртки
├── README.md # этот файл
├── AGENTS.md # руководство для агентов/разработчиков
└── examples/ # примеры вывода
Подробности о внутреннем устройстве и правилах изменения кода — в AGENTS.md.
Languages
Python
82.5%
Shell
17.5%