Skip to content

Repository files navigation

Quran Image Generator

CI Release Assets

Warning: This project is under active development and has not been proofread against a printed Mushaf. Do not use the output for production or distribution without thorough verification.

A CLI tool that generates per-line and per-page PNG/WebP images of the Quran using QCF (Quran Complex Font) page fonts.

Black glyphs on transparent background — enabling dark/light theming via tint color in consuming apps.

Supports font versions V1 (1405H), V2 (1423H), and V4 (Tajweed with embedded colors).

Setup

bun install

Usage

Interactive

bun src/cli.ts

Prompts for version, mode, width, page range, format, and markers. Downloads assets from GitHub releases if missing.

CLI args

bun src/cli.ts [startPage] [endPage] [width] [mode] [v1|v2|v4] [no-markers] [webp] [bounds] [json] [quantize] [dark] [--ink <hex>] [--recolor <SRC=DST,...|file.json>]

Examples:

bun src/cli.ts 1 604 1440 line v2           # all pages, line mode, V2
bun src/cli.ts 1 10 1440 page v1 no-markers # pages 1-10, page mode, no markers
bun src/cli.ts 1 604 1440 line v4 webp      # V4 tajweed, WebP format

Dark theme & tajweed recolor (V4 only)

V4 tajweed colors live in the font's COLR/CPAL color tables, not in fillStyle, so they're recolored by patching CPAL palette 0 at font-registration time. Glyph geometry (glyf/hmtx) and alpha are left byte-identical — only color records change.

bun src/cli.ts 1 604 2160 line v4 dark                 # base ink → light default (#E8E0D4)
bun src/cli.ts 1 604 2160 line v4 --ink "#E8E0D4"      # custom base ink (implies dark)
  • dark / --ink <hex> — recolors the near-black base ink only; saturated tajweed rules are left as-is.
  • --recolor "RRGGBB=RRGGBB,..." — optional, generic remap of any palette entry to a new color. Each source is matched against palette 0 with a ±10/channel tolerance. No palette is baked in — supply your own. Combine with --ink/dark to make rule colors legible on a dark background:
# Lighten the base ink and remap two tajweed rule colors in one pass:
bun src/cli.ts 1 604 2160 line v4 --ink "#E8E0D4" \
  --recolor "F40000=F77B72,3F48E6=6BA6E6"

# Or supply the map as a JSON file of { "SRC": "DST" } hex pairs:
bun src/cli.ts 1 604 2160 line v4 --recolor recolor.json

Docker

docker compose build
docker compose run generator 1 604 1440 line v2

Prebuilt binary (recommended)

Each release ships self-contained binaries with assets embedded — no bun install, no font/layout download, no Cairo or unzip required. Only tar (in every Linux/macOS base) is used to unpack assets on first run.

Pick the variant for your platform from the latest release:

Variant Targets Use when
quran-gen-{platform} v1 + v2 + v4 You want every font version in one binary
quran-gen-v1-{platform} v1 only Smaller download, single version
quran-gen-v2-{platform} v2 only Smaller download, single version
quran-gen-v4-{platform} v4 only Smaller download, single version

Supported platforms: darwin-arm64 (Apple Silicon), linux-x64, linux-arm64.

# Apple Silicon (all versions)
curl -L https://github.com/NedaaDevs/quran-image-generator/releases/latest/download/quran-gen-darwin-arm64.tar.gz | tar xz
./quran-gen-darwin-arm64 1 604 1440 line v2

# Linux x64 (v2 only)
curl -L https://github.com/NedaaDevs/quran-image-generator/releases/latest/download/quran-gen-v2-linux-x64.tar.gz | tar xz
./quran-gen-v2-linux-x64 1 604 1440 line v2

The tarball contains the binary plus a pngquant sidecar; keep them next to each other.

Build from source

bun build src/cli.ts --compile --external canvas --outfile quran-gen
./quran-gen 1 604 1440 line v2

Markers mode

By default, images include ayah end markers (ornamental numbered circles) and surah header frames rendered with the page font. Use no-markers to omit decorative elements — useful for apps that overlay their own themed markers:

  • With markers — full preview with ornamental ayah markers and surah header frames baked into the image
  • Without markers — text only, plus version-matched surah names (no frame). Apps can overlay custom-themed markers using glyph positions from bounds.db

The surah frame template is exported separately to markers/surah-frame.png for apps to composite with their own styling.

Output structure

output/{version}/{width}/
  lines/{page}/001..015.png    # per-line images (15 per page)
  pages/001..604.png           # full page images
  markers/surah-frame.png      # ornamental frame template
  bounds.db                    # glyph bounding boxes (SQLite)

bounds.db schema

glyph_bounds

Column Type Description
page INTEGER Page number (1–604)
line INTEGER Line number (1–15)
position INTEGER Word position within the line
surah_number INTEGER Surah number (1–114)
ayah_number INTEGER Ayah number within the surah
x INTEGER Left edge (px)
y INTEGER Top edge (px)
width INTEGER Glyph width (px)
height INTEGER Glyph height (px)
is_marker INTEGER 1 = ayah end marker, 0 = word
word_index INTEGER Word number within its ayah (join key: surah:ayah:word)
tajweed_index TEXT V4 tajwid rule(s): CPAL palette slot index/indices, comma-joined for multi-rule words (e.g. 15,5), joinable to tajweed_palette. NULL for V1/V2, markers, and base-ink-only words.

The slot index is a stable rule key (it doesn't shift across font builds the way the raw RGB does); map it to a rule in your own legend. Use tajweed_palette only if you need the font's native color.

tajweed_palette

The font's canonical tajwid colors, written once (the palette is identical across all page fonts). Empty for V1/V2.

Column Type Description
idx INTEGER CPAL palette slot (matches a value in tajweed_index)
hex TEXT Canonical source color #RRGGBB, uppercase

The DB's PRAGMA user_version carries the schema version (currently 2); bump it on any schema change so clients can detect a stale download and re-fetch.

line_metadata

Column Type Description
page INTEGER Page number (1–604)
line INTEGER Line number (1–15)
type TEXT text, surah-header, or basmala
surah_number INTEGER Surah number (nullable)
surah_name TEXT Arabic surah name (nullable)

Apps can render marker-less images and overlay ayah markers at runtime by querying:

SELECT x, y, width, height, ayah_number
FROM glyph_bounds
WHERE page = ? AND is_marker = 1

Then render each marker at the given position using the ayah number.

Data

Assets are downloaded automatically via the interactive CLI, or manually from GitHub releases:

data/
  common/fonts/                # surah name fonts, surah header font
  {v1,v2,v4}/
    quran-layout.db            # page/line/word layout + surah metadata
    fonts/p1..p604.ttf         # per-page QCF fonts

Font versions

Version Edition Layout Notes
V1 1405H Madinah Mushaf 604 pages, 15 lines Uthman Taha calligraphy
V2 1423H Madinah Mushaf 604 pages, 15 lines Updated edition
V4 Tajweed Same as V1 Embedded colors for tajweed rules

Credits

Tarteel AI — Quranic Universal Library (QUL)

Special thanks to Tarteel AI for their Quranic Universal Library, which provides the essential data powering this tool:

  • QCF font files — per-page V1, V2, and V4 glyph fonts
  • Word-by-word glyph codes — mapping each Quranic word to its QCF codepoint
  • Mushaf layout data — page/line/word mapping for the 1405H and 1423H Madinah Mushaf editions
  • Surah name ligature fonts — version-matched calligraphic surah names

Other Credits

License

MIT

About

Generate per-line and per-page Quran images using QCF fonts — V1, V2, V4 Tajweed. Black on transparent for theming.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages