Files
hand-writter/README.md
T
second_constantine 9e81d7a3e0 handwrite.py: рукописный рендер кириллицы синими чернилами
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/.
2026-08-22 15:12:01 +03:00

171 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# handwrite.py
Python-скрипт, превращающий текст в картинку рукописного текста с **поддержкой
кириллицы** (полный русский алфавит, включая `Ё`, `щ`, `ъ`, `э`, `ю`, `я`).
Чернила — **синие**, с имитацией письма ручкой.
## Возможности
- 🖋️ **Синие чернила «как рукой»**: имитация письма ручкой — дрейф «давления»
(коррелированные тёмные/светлые участки), полупрозрачные чернила, неровный
край мазка
- ✅ Полная поддержка кириллицы (автоподбор рукописного шрифта с проверкой
наличия всех глифов; приоритет — `Marker Felt`)
- 📐 Корректное выравнивание: обычные буквы (`а`, `о`, `н`, `б`, `й`) на одной
базовой линии, буквы с нижними выносными (`р`, `у`, `д`, `ц`, `щ`) — с
хвостами ниже, точки/запятые — внизу строки, спецсимволы (`$ ~ % @ # & …`) —
по дизайну шрифта
- 📝 Перенос по словам + сохранение `\n` из входного файла/STDIN
- 📓 «Тетрадная» линейная бумага (`--lined`)
- 🎨 Настройка цвета чернил/бумаги/линий, размера шрифта, полей
- 📥 Ввод: аргументом, из файла (`-i`, с переносами строк), через STDIN
- 🔒 Воспроизводимый результат через `--seed`
## Установка
```bash
pip install -r requirements.txt # нужна только Pillow
```
или через обёртку (создаст venv):
```bash
./run.sh init
```
## Быстрый старт
```bash
# текст аргументом
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` | случайный | Зерно ГПСЧ для воспроизводимости. |
## Примеры использования
```bash
# крупный текст на тёплой бумаге
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` передаются после `--` (или просто в конце):
```bash
./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`.
## Подбор шрифта
Скрипт автоматически ищет рукописный шрифт с **полным покрытием кириллицы**:
1. Проверяет приоритетные системные шрифты (`Marker Felt`, затем `Snell Roundhand`).
2. Сканирует системные каталоги, отбирая «рукописные» имена и проверяя все
глифы кириллицы.
3. В крайнем случае берёт любой шрифт с поддержкой кириллицы.
Проверка глифов — без сторонних библиотек (только 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`.