Generate practice templates for Chinese characters (hanzi) for Supernote A5 X2 Manta e-ink tablet.
  • Python 98.2%
  • Shell 1.8%
Find a file
Fredrik Randsborg Bølstad c324fb15fe s/--force/--overwrite
2025-12-02 21:30:16 +08:00
hanzi_data initial commit 2025-12-02 14:01:23 +08:00
input multi-character template: support input file w/ multiple sections 2025-12-02 21:23:02 +08:00
lib add pdf output format 2025-12-02 21:23:02 +08:00
output s/templates/output 2025-12-02 18:19:08 +08:00
tests sanitize output filenames 2025-12-02 21:23:02 +08:00
.gitignore s/templates/output 2025-12-02 18:19:08 +08:00
.pre-commit-config.yaml initial commit 2025-12-02 14:01:23 +08:00
DEVELOPMENT.md remove pyenv references, update documentation 2025-12-02 16:31:05 +08:00
hanzi_generator.py s/--force/--overwrite 2025-12-02 21:30:16 +08:00
pyproject.toml remove pyenv references, update documentation 2025-12-02 16:31:05 +08:00
README.md s/--force/--overwrite 2025-12-02 21:30:16 +08:00
requirements-dev.txt remove pyenv references, update documentation 2025-12-02 16:31:05 +08:00
requirements.txt remove pyenv references, update documentation 2025-12-02 16:31:05 +08:00
setup.sh remove pyenv references, update documentation 2025-12-02 16:31:05 +08:00

Hanzi Template Generator

Generate practice templates for Chinese characters (hanzi) for Supernote A5 X2 Manta e-ink tablet.

Features

  • 1920×2560 px output - Perfect for Supernote A5 X2 Manta
  • Tiled layout - 4×6 grid (24 cells) for practice
  • Greyed-out tracing cells - First 3 cells show the character in grey for tracing practice
  • Empty practice cells - Remaining cells with dotted cross-hairs for reference
  • Character information - Header shows character, pinyin, and definition
  • Multiple formats - PNG, JPG, JPEG, WEBP support
  • Batch processing - Process single characters or files
  • Offline operation - Uses Make Me a Hanzi dataset (included)

Installation

Prerequisites

  • Python 3.9 or higher
  • uv (recommended) or pip

Run the setup script which handles everything automatically:

./setup.sh

This will:

  • Check for a compatible Python version on your system
  • Prefer uv if available (falls back to classic venv + pip)
  • Create a virtual environment
  • Install all dependencies
  • Download data files if needed

Manual setup with uv

  1. Clone or download this repository

  2. Create and sync a virtual environment:

UV_PYTHON=python3 uv sync --group dev
  1. Activate the environment:
source .venv/bin/activate
  1. (Optional) Ensure Make Me a Hanzi data files are present:
ls hanzi_data/dictionary.txt hanzi_data/graphics.txt

If they are missing, the setup.sh script will download them for you, or you can download them manually as shown later.

Setup with pip (alternative)

  1. Clone or download this repository

  2. Create a virtual environment (recommended):

# Use python3 or python, whichever is available and is 3.9+
python3 -m venv .venv
source .venv/bin/activate
  1. Install dependencies:
pip install -e .
  1. Download the Make Me a Hanzi data files (same as above)

Usage

Single Character

Generate a template for a single character:

# Using the script directly
python hanzi_generator.py 中

# Or using the installed entry point (after pip install -e .)
hanzi-generator 中

This creates a template file under the output/progressive/ directory by default.

Batch Processing

Create a text file with one character per line (see input/characters.txt for example):

python hanzi_generator.py --file input/characters.txt

Options

# Specify output root directory (per-template subdirs are created automatically)
python hanzi_generator.py 中 --output my_output/

# Change output format
python hanzi_generator.py 中 --format JPG

# Overwrite existing files (skip duplicate check)
python hanzi_generator.py 中 --overwrite

# Specify desired number of columns (canonical layout for that count)
python hanzi_generator.py 中 --columns 7

# Specify explicit cell size (solver will fit as many cells as possible)
python hanzi_generator.py 中 --cell-size 240

# Adjust page padding (left/right/bottom minimum padding)
python hanzi_generator.py 中 --page-padding 30

# Use multi-character template (multiple characters per page, one row per character)
python hanzi_generator.py --file input/characters.txt --template multi-character

# Or pass multiple characters directly on the CLI (no spaces) for multi-character template
python hanzi_generator.py 中国人 --template multi-character

# Add a header title for the page(s)
python hanzi_generator.py 中国人 --template multi-character --title "Chapter 1: groceries"

# Specify custom data directory
python hanzi_generator.py 中 --data-dir /path/to/hanzi_data/

Output Format

Each generated page is a 1920×2560 px image with:

  • Header section: Character (rendered from SVG stroke data), pinyin, and definition
  • Grid layout: Practice cells arranged in a grid
    • Progressive template: stroke-by-stroke grid, where the first cell shows stroke 1, the second shows strokes 12, etc. After all strokes are shown, remaining cells are empty with cross-hairs for reference.
    • Multi-character template: one row per character, with a filled reference cell, tracing cells, and practice cells for each character.
    • All cells have black borders for clear separation

Output files are organized by template type:

  • Progressive template:
    • Default root: output/
    • Files: output/progressive/<character>_<pinyin>.webp (or the chosen format)
  • Multi-character template:
    • Default root: output/
    • Files: output/multi-character/<chars>_<pinyin>_multi.webp
      • If the characters span multiple pages, filenames become:
        • ..._multi_p1.webp, ..._multi_p2.webp, etc.
        • The _pN suffix is only added when there is more than one page.

Input File Format

Create a text file with one character per line:

中
国
人
好

Lines starting with # are treated as comments and ignored.

Development

See DEVELOPMENT.md for development setup, code quality tools, and guidelines.

Data Source

This project uses the Make Me a Hanzi dataset, which provides:

  • Stroke order data for ~9,000+ Chinese characters
  • SVG path data for each stroke
  • Dictionary information (pinyin, definitions, etymology)

Features

  • Customizable grid size
  • SVG-based character rendering (no fonts needed)
  • Multiple templates
  • Helper gridlines
  • Progressive stroke order (first cell = stroke 1, second = strokes 1-2, etc.)

License

This project uses data from Make Me a Hanzi, which is licensed under the Arphic Public License.

Project Structure

At a high level, the repository is structured as:

  • hanzi_generator.py main CLI script
  • pyproject.toml project configuration and dependencies
  • setup.sh helper script for creating a virtual environment and installing deps
  • hanzi_data/ Make Me a Hanzi data files (dictionary and stroke graphics)
  • output/ generated practice sheets (subdirectories per template type)
  • input/ example input files with characters
  • lib/ library code for:
    • loading Hanzi data
    • layout solving and template generation
    • SVG rendering for characters and strokes