vpype plugin for watercolor plotting
Project description
vpype-watercolor
A vpype plugin for watercolor plotting. It adds water dipping and paint loading sequences before each colored layer for use with pen plotters.
Note: This project is experimental. It works for me, but there might still be bugs and missing features.
How It Works
For each path in the input SVG, the plugin:
- Draws a circle at the water tray (dip to wet brush)
- Draws circles at the matching paint tray (load paint) - stacked over each other as one continuous line
- Draws the path
Installation
Install uv and run the following command to install vpype-watercolor.
uv pip install vpype-watercolor
Usage
uv run vpype \
read --attr stroke examples/input.svg \
scaleto 15cm 15cm \
watercolor --layout examples/layout.svg --center --max-length 5cm --water-every 3 --paint-every 3 --color-map '{"#e30022": "#00A550"}' \
write plot.svg
The --attr stroke option is required to read colors from the input SVG into layer properties.
Options
Finding the right options for your brush and setup might need some experimentation.
-l, --layout FILE(required): Path to layout SVG defining tray positions--center: Center the artwork within the paper area--dip-radius LENGTH: Radius of dip circles (default: 4mm)--paint-circles INTEGER: Number of circles at paint tray (default: 4)--max-length LENGTH: Maximum line length before splitting (e.g., 5cm). Lines longer than this are split into equal parts, each getting its own dip sequence.--color-map JSON: Map SVG colors to layout colors, e.g.,'{"#ff0000": "#cc0000"}'. Useful when your SVG uses different colors than your physical paint trays.--color-filter COLOR: Only output paths matching this color (e.g.,'#ff0000'). Applied after color-map.--water-every INTEGER: Dip in water every N line segments (default: 3).--paint-every INTEGER: Dip in paint every N line segments (default: 3).--reverse-lines: Draw each line forward then backward before pen up.--translate X Y: Translate the artwork by X and Y (e.g.,--translate 10mm 5mm).
Layout
The layout SVG defines the physical positions of trays on your plotter.
This is the layout I use. You can use it as a starting point. The fill color of the paint trays define the paint color. Go to piebro.github.io/vpype-watercolor to interactively modify the layout and download it.
Debug Visualization
To create a debug SVG that shows the layout with the plot overlaid:
vpype-merge-debug examples/layout.svg plot.svg debug.svg
This merges the layout SVG (with background and filled rectangles) with the plot paths for visual verification.
Plot with AxiCLI
Install the AxiDraw API:
uv pip install https://cdn.evilmadscientist.com/dl/ad/public/AxiDraw_API.zip
Toggle the pen to adjust pen up/down positions:
axicli --mode toggle --pen_pos_down 20 --pen_pos_up 75
Generate a preview SVG to verify the plot before running:
uv run axicli plot.svg --model 2 -G4 --speed_pendown 15 --pen_pos_down 20 --pen_pos_up 75 --report_time -vg3 -o preview.svg
Run the plot and return to the align position when done:
uv run axicli plot.svg --model 2 -G4 --speed_pendown 15 --pen_pos_down 20 --pen_pos_up 75 && uv run axicli -m align
The -G4 flag is required to strictly preserve file order. Without it, AxiCLI may reorder paths to optimize travel distance, which breaks the water→paint→line sequence.
Plotting Pixel Art
The example above was created using this generative algorithm: github.com/piebro/substitution-system.
Install vpype-pixelart to convert pixel art images to plottable paths:
uv pip install vpype-pixelart
Extract all hex colors from a pixel art image for the color map, or just do it manually:
uv run --with pillow python -c "from PIL import Image; img = Image.open('examples/example_pixelart.png').convert('RGB'); print(' '.join(sorted(set(f'#{r:02x}{g:02x}{b:02x}' for r,g,b in img.get_flattened_data()))))"
Convert pixel art to watercolor plot:
uv run vpype pixelart --mode line --pen-width 1.5mm --overdraw 0.35 --upscale 4 examples/example_pixelart_2.png \
reverse --flip \
linesort --no-flip \
watercolor --layout examples/layout.svg --center --water-every 16 --paint-every 4 --color-map '{"#006992": "#e30022", "#eaf8bf": "#120a8f", "#eca400": "#e3a857"}' --translate -100mm 0mm \
write plot.svg
Resources
Development
To publish a new version to PyPI:
git tag v0.1.0
git push origin v0.1.0
Contributing
Contributions are welcome. Open an issue or PR if you want to report a bug or have a feature request.
License
All code in this project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vpype_watercolor-0.1.0.tar.gz.
File metadata
- Download URL: vpype_watercolor-0.1.0.tar.gz
- Upload date:
- Size: 304.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c884456cb7be9e46b3b14625dce7e5e070ee5f239857aa698bcff626612e011
|
|
| MD5 |
6f986980ebd5ca6a396f8633018e15ae
|
|
| BLAKE2b-256 |
ce7e23c5a65ed69dee62f2c4f060c7e2e4d631268f41c55730f0e2e1a712d2e0
|
File details
Details for the file vpype_watercolor-0.1.0-py3-none-any.whl.
File metadata
- Download URL: vpype_watercolor-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c0230b14e85e5f42814eb2c7b759358a6e2c729a1806e4e2ad43e48946151a6
|
|
| MD5 |
89201b4db60419830c92ac6eb1a489a0
|
|
| BLAKE2b-256 |
92f9a6057a757d589476a6409d372ba0025a2eb460468591948345ba4ebd1986
|