Skip to main content

terminalCanvas

terminalCanvas is a Python library intended for creating graphics and developing visual-rich applications inside the terminal.

WARNING: This library is mainly developed and tested on Windows, with all the quirks of the Windows command prompt in mind. Support for Linux terminals is extremely limited.

Voxelate, a voxel-based Minecraft-wannabe game

Installation & Requirements

The terminalCanvas module currently requires Python of version 3.10 and up, although I've only tested on Python 3.11.

If this goes on PyPI at some point, install the module by running:

py -m pip install terminalCanvas

Otherwise, install it using Git:

py -m pip install git+https://github.com/RandomMaerks/terminalCanvas.git

The module uses Pillow for image processing, as well as NumPy for image-to-array conversion and other array-related operations. They should automatically install along with the main installation.

How it works

Because most monospaced fonts are quite narrow (width:height ratio is about 1:2), we can use the half-box character ▀ to represent one squarish pixel, along with the other empty half to represent another pixel below it.

Additionally, some terminal support changing colours independently for a character (called the foreground) and its own background using ANSI escape sequences, so we're able to fully simulate two whole pixels whose colours can be independently changed.

To create an entire canvas, we just need to fill up every space in the terminal with this character. Since one single character is able to represent two pixels, the total number of characters used should be width * (height // 2), where width and height are the possible number of lines and columns respectively to write text for any given window size.

Basic usage

The information below is only showing the very basics. For more info, please consult the wiki (doesn't exist yet lol).

● 2D & 3D rendering

Start by importing the main module. For convenience, set a short alias for the module, tc for example.

import terminalCanvas as tc

Then, create a new TCanvas object:

canvas = tc.TCanvas()

Upon creating the object, the "width" and "height" of the terminal that would run the script will automatically be detected. You can get these data by calling canvas.width or canvas.height, as well as the precalculated canvas.wCenter and canvas.hCenter.

Some properties of the canvas can be changed. For example, to change the background colour:

canvas.background((125, 170, 245))

The background() method requires a tuple with three items that represents the RGB values.

To resize the canvas, use:

canvas.resize()

This will replace the old canvas.width and canvas.height with the new values corresponding to the reoslution of the terminal window. This is especially important if you want to resize the terminal window during runtime.

To create a graphical object such as a line, you can call the Line class:

line = tc.Line(0, 0, canvas.width, canvas.height, color=(255, 0, 0))

This will create an instance of the Line class which includes the line's pixel data, its attributes, and additional setter methods to modify them. Other objects include Point, Point3D, Line3D, Rectangle, Triangle, Triangle3D, Ellipse, Text, Image, and Sprite. Their attributes do not need to be set right from the start; you can simply create an instance of any object with absolutely no arguments.

Anyway, we've created an object, but it's not on the canvas yet. To actually draw the line, use the draw() method:

canvas.draw(line)

This will put all the pixels from the object into the main canvas.

Now, to show the canvas and see what you've drawn, use:

canvas.show()

This will print everything in our canvas to the terminal.

An example of the line being drawn on the canvas

However, canvas.show() only shows the canvas once. You can put it in a loop to keep it running, along with keyPressed() to stop the loop using keyboard input:

while True:
    if canvas.keyPressed("ESC"):
        break

    canvas.clear()

    # all the drawing stuff

    canvas.show()

The clear() method allows the canvas to be completely clean before redrawing anything for the next frame. Without calling this method, the very first frame will be the only frame to be shown.

Lastly, you should put canvas.end() after everything to properly erase everything and restore the cursor.

The whole thing should be something like this:

import terminalCanvas as tc

canvas = tc.TCanvas()
canvas.background((125, 170, 245))

line = tc.Line(
    0, 0,
    canvas.width, canvas.height,
    color=(255, 0, 0)
)

while True:
    if canvas.keyPressed("ESC"):
        break

    canvas.clear()
    canvas.draw(line)
    canvas.show()

canvas.end()

● User interface

terminalCanvas also has a canvas dedicated to "user interface", although it is very limited. You can use it by calling TCanvasUI instead of TCanvas:

canvas = tc.TCanvasUI()

TCanvasUI fundamentally changes what a "pixel" is on the canvas and how each pixel is represented. In TCanvas, each pixel represents one color, takes up half of a character's bounding box, and the glyph used in this character space is specifically the half-box character ▀. In TCanvasUI, however, each pixel represents one character, and the glyph is either a letter from a textbox or part of a rectangular frame.

By default, the background color of TCanvasUI will be entirely black, as opposed to TCanvas being white. You can still change it using background().

There are two custom graphical objects for TCanvasUI: RectangleUI and TextUI.

You can use it like the other objects:

tc.RectangleUI(
    0, 0,
    canvas.width - 1, canvas.height - 1,
    color=(255, 0, 0),
    mode="frame",
)

While non-UI objects are usable in TCanvasUI, they will not be displayed in the same manner as in TCanvas.

TCanvasUI also has all the essential methods like draw() and show().

Credits & honourable mentions

Massive thanks to ConnerWill for his ANSI escape sequence cheatsheet. Without this cheatsheet, I wouldn't have been able to make this module possible (and, honestly, I wouldn't have known that this entire thing was possible).

Another huge thanks to Gabriel Gambetta for writing the book Computer Graphics from Scratch. All my rasterisation work closely follow his guidance.

I'd also like to mention Mr. Shiffman, Daniel Shiffman from The Coding Train for inspring me to do programming with all his fascinating coding challenges.

Some honourable mentions:

  • p5.js, literally where this whole idea comes from
  • The pyglet module

Other credits:

Release files for terminalCanvas 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for terminalCanvas 0.4.0
File Size Uploaded
terminalcanvas-0.4.0.tar.gz 77.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for terminalCanvas 0.4.0
File Interpreter ABI Platform
terminalcanvas-0.4.0-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 158.2 kB

Release files / terminalcanvas-0.4.0.tar.gz

Download URL terminalcanvas-0.4.0.tar.gz
Size 77.8 kB
Tags Source
SHA-256 checksum
How to use checksums
7dcfeaf9152e885844997440ad1cf8ca7fcffef51c103cff44bcee279eabfb25
BLAKE2b-256 checksum
How to use checksums
1b615b1405d52944b5f5ce588966e5ef2b238969fd485e35bb52b46ab713ac47
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / terminalcanvas-0.4.0-py2.py3-none-any.whl

Download URL terminalcanvas-0.4.0-py2.py3-none-any.whl
Size 80.4 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
38184cab9564d5328b1588d1afd0cbd856166180c03eb3bdc4a5eecde7d5c2e1
BLAKE2b-256 checksum
How to use checksums
a4a88d2b3a0d5fa6c701bddf576f52257b270e2ddc89011875e3dfbe08fb6fa9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release history Release notifications | RSS feed

0.5.0

2 release files

This release

0.4.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page