Canvas
The Canvas is the root object. It holds dimensions and an ordered list of layers.
Creation
Canvas(width=None, height=None)
| Parameter | Type | Description |
|---|---|---|
width |
int \| None |
Canvas width in pixels. Must be a positive integer. |
height |
int \| None |
Canvas height in pixels. Must be a positive integer. |
Width and height must be given together or both omitted. A canvas built without a size (Canvas()) is unsized: it accepts layer builders but cannot be rendered, diagnosed, or serialized until it gets a size — either directly or by being added to a sized Deck, which injects its default size. Check canvas.has_size to tell the difference.
Canvas.from_aspect_ratio(ratio, base_width)
Creates a canvas from an aspect ratio string and a base width. Height is calculated automatically.
wide = Canvas.from_aspect_ratio("16:9", base_width=1280) # 1280×720
square = Canvas.from_aspect_ratio("1:1", base_width=1080) # 1080×1080
vertical = Canvas.from_aspect_ratio("9:16", base_width=1080) # 1080×1920
| Parameter | Type | Description |
|---|---|---|
ratio |
str |
Aspect ratio string in "W:H" format, e.g. "16:9" |
base_width |
int |
Canvas width in pixels |
Layer builders
All builder methods mutate the canvas and return self, enabling method chaining.
| Method | Description |
|---|---|
.background(...) |
Add a full-canvas background layer |
.text(...) |
Add a text layer |
.image(...) |
Add an overlay image layer |
.shape(...) |
Add a shape layer |
.svg(...) |
Add an SVG layer, rasterized at render time |
.group(...) |
Add an auto-layout group of child layers |
.outline(...) |
Add a canvas border |
.chart(...) |
Add a deterministic bar or line chart layer from a typed chart spec |
.qr_code(...) |
Add a square QR code layer |
.custom(fn) |
Add a Pillow callback layer |
See the data visualization reference and the other individual reference pages for full parameter details.
.diagnose()
Checks the composition for layout and legibility issues without writing a file. Returns a list of Diagnostic findings (empty when clean):
Finding codes: off-canvas, tiny-text, text-overflow, text-clipped, missing-glyph,
low-contrast, layer-overlap, layer-hidden, and edge-crowding. See
Diagnostics & CLI for details and the quickthumb lint (or
quickthumb diagnose) equivalent.
Export methods
.render(path, format=None, quality=None, debug=False, animation=None)
Renders the canvas and writes the result to a file. The format is detected from the file extension; .svg, .pptx, and .pdf produce vector/document output, and .gif/.mp4/.webm produce an animation playing the canvas's layer animation effects (see Exporting to SVG, PPTX, PDF & video).
from quickthumb import GifOptions, VideoOptions
canvas.render("output.png")
canvas.render("output.jpg", format="JPEG", quality=85)
canvas.render("output.webp", format="WEBP", quality=90)
canvas.render("debug.png", debug=True) # raster output with public layer-id bboxes
canvas.render("output.svg")
canvas.render("output.pptx") # requires quickthumb[pptx]
canvas.render("output.pdf") # requires quickthumb[pdf]
canvas.render("output.gif") # animated; .mp4/.webm require the ffmpeg binary
canvas.render(
"preview.gif",
animation=GifOptions(fps=8, max_size=(540, 960), colors=128),
)
canvas.render("preview.mp4", animation=VideoOptions(fps=30))
| Parameter | Type | Default | Description |
|---|---|---|---|
path |
str |
— | Output file path |
format |
str \| None |
None |
Optional raster output format override: "PNG", "JPEG", or "WEBP" |
quality |
int \| None |
None |
Compression quality (1–95). Only valid for JPEG and WEBP. |
debug |
bool |
False |
Draw public layer-id bounding boxes on raster output for visual review. |
animation |
GifOptions \| VideoOptions \| None |
None |
Format-specific options: GifOptions for GIF, VideoOptions for MP4/WebM. |
Warning
Passing quality with format="PNG" raises RenderingError. Passing debug=True for document or animated output (.svg, .pptx, .pdf, .html, .gif, .mp4, or .webm) raises RenderingError.
GifOptions and VideoOptions are available from quickthumb. GifOptions
accepts fps, matte, loop, max_size=(width, height), and colors.
VideoOptions accepts fps, matte, soundtrack=AudioTrack(...), and loop_audio.
GIF sizing and palette controls are rejected for MP4/WebM output.
.to_svg(embed_fonts=False)
Returns the canvas as an SVG document string. Set embed_fonts=True to inline the used font files as @font-face data URLs.
.to_pptx()
Returns the canvas as PowerPoint file bytes — a single slide with editable text boxes and autoshapes. Requires the pptx extra.
.to_pdf()
Returns the canvas as PDF file bytes — a single page with native vector backgrounds, shapes, and selectable text when its font can be safely embedded and the text does not require complex shaping. Unsupported text is embedded as a pixel-exact image fragment. Requires the pdf extra.
.to_gif(...) / .to_mp4(...) / .to_webm(...)
Return the canvas as an animation that plays its layer animation effects in sequence, then holds the settled composition for hold seconds (see Animated GIF & video). A canvas with no animations yields a single-frame GIF. .to_mp4()/.to_webm() require the ffmpeg binary on PATH (or named by QUICKTHUMB_FFMPEG).
gif_bytes = canvas.to_gif(fps=20, hold=3.0, loop=0, matte="#000000")
mp4_bytes = canvas.to_mp4(fps=30, hold=2.0, soundtrack="music.mp3")
webm_bytes = canvas.to_webm(fps=30, hold=2.0)
.to_mp4()/.to_webm() also accept soundtrack (an audio file muxed into the video, trimmed to the video length) and loop_audio (an explicit override). AudioTrack(..., loop=True) repeats a shorter configured track; legacy string paths keep the previous default of looping. GIF cannot carry audio. See the Deck API for the full parameter table.
.to_base64(format="PNG", quality=None)
Returns the rendered image as a base64-encoded string.
| Parameter | Type | Default | Description |
|---|---|---|---|
format |
str |
"PNG" |
Output format: "PNG", "JPEG", or "WEBP" |
quality |
int \| None |
None |
Compression quality. Only valid for JPEG and WEBP. |
.to_data_url(format="PNG", quality=None)
Returns the rendered image as a data URL (data:<mime>;base64,...).
| Parameter | Type | Default | Description |
|---|---|---|---|
format |
str |
"PNG" |
Output format: "PNG", "JPEG", or "WEBP" |
quality |
int \| None |
None |
Compression quality. Only valid for JPEG and WEBP. |
.to_json()
Serializes the canvas to a JSON string.
Raises ValidationError if the canvas contains .custom(fn) layers (callbacks cannot be serialized).
Canvas.from_json(json_str)
Deserializes a canvas from a JSON string.
Note
from_json() expects a JSON string, not a Python dict. Use json.dumps(data) first if you have a dict.
.custom(fn)
Adds a callback that receives and returns a Pillow Image.
from PIL import ImageDraw
from quickthumb import Canvas
def draw_badge(image):
d = ImageDraw.Draw(image)
d.polygon([(70, 70), (240, 70), (155, 180)], fill="#FF3B30")
return image
canvas = Canvas(512, 512).custom(draw_badge)
| Rule | Detail |
|---|---|
fn must be callable |
Receives a PIL.Image.Image |
| Return value | May return the same image (mutated), a new image of the same size, or None |
| Errors | Exceptions from the callback are wrapped as RenderingError |
| Serialization | Custom layers are not JSON-serializable |