Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

plotline

Turn images into drawings for pen plotters.

CI License: MIT Python 3.11+ Status: early

Open it in your browser  ·  Command line  ·  Design brief

plotline converts raster images into vector line art, such as stippling, single continuous lines, dashes and sketched strokes. It comes with a live preview that shows the algorithm at work, so you can see what a setting does before you commit ink to paper.

A still life of three balls and a cube
The image
The still life drawn with the grid style
grid: dots on a regular grid
The still life drawn with the hatch style
hatch: crossing parallel lines
The still life drawn with the waves style
waves: rippling lines, one stroke each
The still life drawn with the spiral style
spiral: one rippling spiral
The plotline logo drawn with the ink style
ink: line art, here the logo

plotline drew every picture above with a 0.3 mm pen, from images it renders in code.

Features

  • Eighteen styles, from dots on a grid to one continuous spiral. The table below describes each one.
  • Live preview. The browser GUI shows the drawing being built. It runs the engine inside the page as WebAssembly, so your image is never uploaded.
  • Suggestions. The engine measures a new image and suggests changes: line art, levels, invert, noise, page orientation and colour. You apply each one with a click. The tone stage's Levels can also be Auto, which sets black and white from the image.
  • Short pen travel. Every run orders its paths to keep the pen's travel short, and the line styles lift the pen far less often than grid.
  • Plotter-ready output. An SVG in millimetres holds one layer per pen that draws, each labelled with the name of its pen. A run can also write the paths as JSON, and a PNG preview that draws each mark at its real pen width. For a pen-fitted 3D printer, the GUI writes one G-code file per pen.
  • Several pens. Pen use shares a drawing between your pens: light to dark in list order, or each pen by its colour, so cyan, magenta, yellow and black pens can draw a colour image. By default the first pen draws alone.
  • Real pens. A bank of common fineliners, technical pens, gel pens, ballpoints and markers gives each pen its maker's line width, and a list of common inks gives it a colour.
  • Presets. A small JSON file holds the style, page, pens, settings and machine of a run, so you can keep a look and share it.
  • One engine. The engine is written in Rust and compiled twice: to a native extension for the Python package, and to WebAssembly for the browser. The Python package and the command line are thin layers over it.
Style What it draws
grid A dot on a regular grid wherever the image is dark enough.
hatch Straight parallel lines over the dark areas, in three levels that cross over darker tones.
waves Parallel lines that ripple more where the image is darker, one pen stroke per line.
spiral One spiral from the centre out that ripples the same way.
ink Line art, lettering and inked drawings. It outlines every ink shape and fills it with rings, and draws strokes thinner than the pen once down the middle, so the drawing keeps its own shapes and weights.
stipple Points that spread evenly while staying dense in dark areas (weighted Voronoi relaxation), each drawn as a dot sized by the ink under it.
line The same points joined into one unbroken line that does not cross itself.
dashes A short stroke at each point, along the image's edges.
tree The points joined by the shortest tree.
mesh A triangle mesh over the points.
cells The outlines of the points' Voronoi cells.
sketch Straight strokes chained from dark to dark, like a quick pencil sketch.
halftone Dots on a regular grid, each sized by the ink, like a printed halftone.
dither Dots placed by error diffusion.
circles Circles packed without overlap, larger and closer where the image is darker.
contours Level lines of the image, like a topographic map.
flow Evenly spaced lines that follow the image's edges, closer together where it is darker.
hilbert A space-filling curve that folds tighter where the image is darker, broken where it leaves the image.

stipple, line, dashes, tree, mesh and cells share one placement of points, so switching between them at their default settings reuses the points. A style switch resets the settings to the new style's defaults.

In the browser

Open jonathanrjoyner.github.io/plotline. There is nothing to install.

  1. Drop or paste a PNG, JPEG or WebP image, or click Sample image.
  2. Pick a style, change its settings and click Run to watch it draw.
  3. Set up your pens in the Pens dialog, and choose how they share the drawing under Pen use. The page remembers your setup between visits.
  4. Click Export SVG in the toolbar, ready for a pen plotter's own software.

For a new image the Suggestions panel, at the top of the right column, lists what would suit it, each with an Apply button. Nothing changes until you click.

For G-code, enter your machine in the Settings dialog: the drawable area, pen heights, feeds, and start and end G-code. The export panel then writes one G-code file per pen. The preset carries the machine, so save a preset to keep it. A short tour of the page opens on your first visit, and Tour in the toolbar opens it again.

Command line

There is no release yet, so work from a clone of this repository. Building the Python extension needs a Rust toolchain: install one with rustup. With uv installed as well, run this in the clone, where uv sync builds the extension and installs the package:

uv sync
uv run plotline --help

Then draw an image of your own:

uv run plotline run grid your-photo.jpg --out drawing.svg --preview preview.png

This writes drawing.svg and preview.png, and prints a one-line summary with the path count and an estimated plot time.

To Use
Set the page and margin, in mm --width 210 --height 297 --margin 15
Choose the pen, by ink name or #rrggbb colour --pen 'Fine:0.3:blue'
Share the drawing between pens given with --pen more than once; by default only the first draws --set split.mode=light_to_dark or by_colour
Change a setting --set points.spacing_mm=3
List a style's settings plotline describe grid
Save the run's look as a preset --save-preset my-look.json
Start a later run from a preset --preset my-look.json
See an image's statistics and suggested changes as JSON plotline analyse your-photo.jpg
Open the live preview locally plotline gui

plotline gui serves the browser GUI from your machine. Building it needs Node, wasm-pack and the wasm32-unknown-unknown Rust target: run npm run wasm, npm ci and npm run build in web/.

With an AI assistant

plotline mcp serves plotline to an AI assistant over the Model Context Protocol, on stdio. From a clone, uv sync installs the MCP extra; once there is a release, pip install "plotline[mcp]" will. Give an MCP client the server as {"command": "plotline", "args": ["mcp"]}, where command is the plotline on the client's PATH or the full path to it (for a clone, the one in its .venv). The assistant can load an image, ask analyse_image what would suit it, run styles, look at previews, also zoomed in on a part of the page, and export the result.

Roadmap

plotline is early software. The goals, architecture, decisions and everything still planned are in the design brief.

License

MIT

Metadata

Release files for plotline 0.1.0.dev0

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

Source distribution (sdist)

Source distribution for plotline 0.1.0.dev0
File Size Uploaded
plotline-0.1.0.dev0.tar.gz 972.1 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for plotline 0.1.0.dev0
File
plotline-0.1.0.dev0-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
plotline-0.1.0.dev0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 abi3 Linux glibc 2.17+ x86-64 Details
plotline-0.1.0.dev0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.11 abi3 Linux glibc 2.17+ ARM64 Details
plotline-0.1.0.dev0-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl CPython 3.11 abi3 macOS 11.0+ ARM64, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64 Details

Total release size: 10.6 MB

Release files / plotline-0.1.0.dev0.tar.gz

Download URL plotline-0.1.0.dev0.tar.gz
Size 972.1 kB
Tags Source
SHA-256 checksum
How to use checksums
d9d19c532eeeb1ba794ed7731dda127cc42552a8a31fc4d29fa51697737e11f6
BLAKE2b-256 checksum
How to use checksums
c68b365641052f147c15e60e1d98aa6e336cce4727d7e12cc0c7341e9ddd4019
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 16, 2026.

Transparency log

Release files / plotline-0.1.0.dev0-cp311-abi3-win_amd64.whl

Download URL plotline-0.1.0.dev0-cp311-abi3-win_amd64.whl
Size 2.1 MB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
22df47c78c8579cd1ba0a448ba7d068a44478f112b4e3a35199597cac01600e2
BLAKE2b-256 checksum
How to use checksums
c674c9382f7eee54da650e6d810b230bbd35ef2649fa4e1a236e4ff01cf2d9bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 16, 2026.

Transparency log

Release files / plotline-0.1.0.dev0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL plotline-0.1.0.dev0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.2 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
58a59b95a612ef0f4a3053c12ae209e8f0f07a6666f037d404e315245eee84fe
BLAKE2b-256 checksum
How to use checksums
f7f66d740226695fa0a30dd8e2560f49da0a36bd87f8af860e8607192d31c848
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 16, 2026.

Transparency log

Release files / plotline-0.1.0.dev0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL plotline-0.1.0.dev0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 2.1 MB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
a066a4f186fbe59323891cd659b739cd3af10e0b9533b1aa2cce60fc6fc5e7f8
BLAKE2b-256 checksum
How to use checksums
70b87d16ba926dcd296a33879a1c6998e1afbf3d376db6ba65b6510a2fa71aa9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 16, 2026.

Transparency log

Release files / plotline-0.1.0.dev0-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl

Download URL plotline-0.1.0.dev0-cp311-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Size 3.3 MB
Tags CPython 3.11 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
625db4483be3c65f2f67d0fdf482b927fd45947299df071b9274cd39768ae1f7
BLAKE2b-256 checksum
How to use checksums
5a38ae4bdce07493bf2b012dc0b266243d7bfac04d1d81a157a1ba9bd2852573
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 16, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

5 release files

0.1.0

5 release files

This release

0.1.0.dev0 This release

5 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