ascii-art
Programmatic ASCII art generation for TUI applications. Build text banners, convert images, draw shapes, render tables and charts, animate sprites — all as plain text strings ready for terminal display.
Installation
pip install ascii-art
With optional integrations:
pip install ascii-art[rich] # Rich panels & text objects
pip install ascii-art[textual] # Textual Static widgets
pip install ascii-art[dev] # pytest, mypy, ruff
Quick Start
import ascii_art
# Figlet text banner
print(ascii_art.text_render("Hello!", font="slant"))
# Image to ASCII
print(ascii_art.image_render("photo.png", width=60))
# Draw shapes on a canvas
canvas = ascii_art.Canvas(40, 20)
ascii_art.circle(canvas, 20, 10, 8, char="*")
ascii_art.rectangle(canvas, 5, 3, 30, 14, char="#")
print(canvas.render())
# Border frame
print(ascii_art.frame("Important message", style=ascii_art.BorderStyle.ROUNDED, title="Notice"))
# Table
print(ascii_art.table(
[["Alice", "92"], ["Bob", "87"]],
headers=["Name", "Score"],
style=ascii_art.BorderStyle.DOUBLE,
))
# Sparkline chart
print(ascii_art.sparkline([1, 4, 2, 8, 5, 7, 3, 6]))
# Bar chart
print(ascii_art.bar_chart([30, 80, 45, 60], labels=["Q1", "Q2", "Q3", "Q4"], width=30))
# Scatter plot
print(ascii_art.scatter([(1, 2), (3, 7), (5, 4), (8, 9)], width=40, height=15))
Fluent Builder API
Every module provides a Builder class for method-chaining style configuration:
from ascii_art import TextBuilder, BorderBuilder, ShapesBuilder, ChartBuilder
# Text
output = TextBuilder().text("Welcome").font("big").width(100).render()
# Borders
box = BorderBuilder().text("Hello").style(BorderStyle.DOUBLE).title("Greeting").render()
# Shapes — compose multiple primitives
scene = (
ShapesBuilder()
.width(60).height(20).char("*")
.add_circle(30, 10, 8)
.add_rectangle(5, 3, 50, 14)
.add_line(0, 0, 59, 19)
.render()
)
# Charts
chart = ChartBuilder().chart_type("bar").data([10, 20, 30]).width(50).labels(["A", "B", "C"]).render()
Text Rendering
Renders text using pyfiglet fonts with alignment control.
from ascii_art import text_render, list_fonts, Alignment
# List available curated fonts
print(list_fonts())
# ['banner', 'big', 'block', 'bubble', 'digital', 'lean', 'slant', 'small', 'standard', ...]
# Centered text
print(text_render("Title", font="shadow", width=60, align=Alignment.CENTER))
Image Conversion
Converts images to ASCII art using luminance mapping with optional edge detection.
from ascii_art import image_render, DETAILED_CHAR_RAMP, BLOCK_CHAR_RAMP
# Basic conversion
print(image_render("landscape.jpg", width=100))
# Inverted with detailed character set
print(image_render("logo.png", width=60, charset=DETAILED_CHAR_RAMP, invert=True))
# Edge detection (Sobel filter)
print(image_render("diagram.png", width=80, edges=True))
# From a PIL Image object
from PIL import Image
img = Image.open("photo.jpg")
print(image_render(img, width=120))
Three built-in character ramps are available:
| Ramp | Characters | Use case |
|---|---|---|
DEFAULT_CHAR_RAMP |
.:-=+*#%@ |
General purpose |
DETAILED_CHAR_RAMP |
70 chars, fine gradation | High detail |
BLOCK_CHAR_RAMP |
░▒▓█ |
Block-style output |
Shape Drawing
Draw primitives on a Canvas — a 2D character grid. All drawing functions mutate the canvas in-place and return it for chaining.
from ascii_art import Canvas, line, rectangle, circle, ellipse, triangle, diamond, arrow
c = Canvas(60, 25)
rectangle(c, 0, 0, 59, 24, "#") # border
circle(c, 30, 12, 10, "o") # centered circle
line(c, 0, 0, 59, 24, ".") # diagonal
diamond(c, 30, 12, 5, "+") # diamond overlay
triangle(c, 10, 20, 30, 5, 50, 20) # triangle
arrow(c, 5, 12, 25, 12) # horizontal arrow
print(c.render())
Canvases support overlay for compositing:
bg = Canvas(40, 20)
fg = Canvas(10, 5)
circle(fg, 5, 2, 2, "*")
bg.overlay(fg, 15, 7) # paste fg onto bg at offset (15, 7)
Borders & Frames
from ascii_art import frame, divider, BorderStyle
# Six border styles: SINGLE, DOUBLE, ROUNDED, BOLD, ASCII, DASHED, SHADOW
print(frame("Content here", style=BorderStyle.ROUNDED, padding=2, title="Header"))
# Horizontal dividers
print(divider("Section", width=60, style=BorderStyle.DOUBLE))
# ═══════════════════════════ Section ══════════════════════════
Border Styles
SINGLE: ┌──┐ DOUBLE: ╔══╗ ROUNDED: ╭──╮
│ │ ║ ║ │ │
└──┘ ╚══╝ ╰──╯
BOLD: ┏━━┓ ASCII: +--+ DASHED: ┌╌╌┐
┃ ┃ | | ╎ ╎
┗━━┛ +--+ └╌╌┘
SHADOW: ┌──┐░
│ │░
└──┘░
░░░░
Tables
from ascii_art import table, Alignment, BorderStyle
data = [
["Alice", "Engineering", "92"],
["Bob", "Marketing", "87"],
["Carol", "Engineering", "95"],
]
print(table(
data,
headers=["Name", "Dept", "Score"],
style=BorderStyle.BOLD,
alignments=[Alignment.LEFT, Alignment.LEFT, Alignment.RIGHT],
))
Output:
┏━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━┓
┃ Name ┃ Dept ┃ Score ┃
┣━━━━━━━╋━━━━━━━━━━━━━╋━━━━━━━┫
┃ Alice ┃ Engineering ┃ 92 ┃
┃ Bob ┃ Marketing ┃ 87 ┃
┃ Carol ┃ Engineering ┃ 95 ┃
┗━━━━━━━┻━━━━━━━━━━━━━┻━━━━━━━┛
Charts
from ascii_art import sparkline, bar_chart, scatter
# Sparkline — single-line Unicode block chart
print(sparkline([1, 4, 2, 8, 5, 7, 3, 6]))
# ▁▅▂█▄▆▃▅
# Horizontal bar chart with labels
print(bar_chart([30, 80, 45, 60], labels=["Q1", "Q2", "Q3", "Q4"], width=30))
# Scatter plot
print(scatter([(1, 1), (2, 4), (3, 2), (5, 8), (7, 3)], width=40, height=15))
Sprites & Animation
from ascii_art import Sprite, Animation, SPRITES
# Use a built-in sprite
heart = Sprite(SPRITES["heart"])
print(heart.render())
# Transforms (all return new Sprite)
flipped = heart.flip_h()
big = heart.scale(2)
rotated = heart.rotate(90)
# Animation from frames
frames = [heart, heart.flip_h(), heart.flip_v()]
anim = Animation(frames)
for frame in anim:
print(frame.render())
print("---")
Built-in sprites: heart, star, arrow_right, smiley.
Framework Integrations
Rich
from ascii_art.integrations.rich_panel import to_text, to_panel
from rich.console import Console
console = Console()
art = ascii_art.text_render("Hello", font="slant")
console.print(to_panel(art, title="ASCII Art"))
Textual
from ascii_art.integrations.textual_widget import to_static
widget = to_static(ascii_art.text_render("Dashboard"))
# Use in a Textual app's compose() method
Curses
from ascii_art.integrations.curses_win import write_to_window
# Inside a curses application
write_to_window(stdscr, ascii_art.frame("Status: OK"), y=2, x=5)
CLI
# Text banners
ascii-art text "Hello World" --font slant --width 100 --align center
# Image conversion
ascii-art image photo.png --width 80 --invert
ascii-art image diagram.png --edges
# Shape drawing
ascii-art shape circle --width 40 --height 20 --char "o"
ascii-art shape rectangle --width 30 --height 15
ascii-art shape diamond --char "+"
# Border framing (text argument or stdin)
ascii-art border "important text" --style rounded --title "Notice"
echo "piped text" | ascii-art border --style double
# Table from CSV (argument or stdin)
ascii-art table "Name,Score\nAlice,92\nBob,87" --headers --style bold
cat data.csv | ascii-art table --headers
# Charts
ascii-art chart "1,4,2,8,5,7" --type bar --width 30
ascii-art chart "1,4,2,8,5,7" --type sparkline
Development
# Create virtual environment and install dev dependencies
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
# Run tests
pytest
# Run a single test
pytest tests/test_shapes.py::test_rectangle -v
# Performance benchmarks
pytest -m perf
# Type checking (strict mode)
mypy src/
# Lint
ruff check src/ tests/
# Build distribution
python -m build
Project Structure
src/ascii_art/
├── __init__.py # Public API re-exports
├── __main__.py # CLI entry point
├── _types.py # Enums, type aliases, character ramps
├── _builder.py # BaseBuilder ABC (fluent API pattern)
├── _cache.py # @cached decorator
├── text.py # Figlet text rendering
├── image.py # Image-to-ASCII conversion
├── shapes.py # Canvas + drawing primitives
├── borders.py # Frame/divider rendering
├── tables.py # ASCII table rendering
├── charts.py # Sparkline, bar chart, scatter plot
├── sprites.py # Sprite transforms & animation
└── integrations/ # Rich, Textual, curses adapters
Requirements
Metadata
Release files for tui-ascii-art 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tui_ascii_art-0.1.1.tar.gz | 30.9 kB | With provenance | Details for tui_ascii_art-0.1.1.tar.gz |
Release files / tui_ascii_art-0.1.1.tar.gz
| Download URL | tui_ascii_art-0.1.1.tar.gz |
|---|---|
| Size | 30.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4379c57cf1e2bf7c88d8b1097535311b47ce187ed68788adab5c29252cedf748
|
|
BLAKE2b-256 checksum How to use checksums |
f2a8d23fe110e9b4e3fb1f1e756791d6790e06aa6b0e24a539ace11a701abebc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 4, 2026.
Transparency logSecurity for tui-ascii-art 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 1 file in this release has been uploaded with provenance metadata.
Attestation for tui_ascii_art-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 4, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.