Pure-Python cross-platform parser for Vexy Lines .lines vector art files
Project description
vexy-lines-py
Parse Vexy Lines .lines vector art files in pure Python — no app, no macOS, no heavy dependencies.
Install
pip install vexy-lines-py
Python 3.11+. Runtime dependency: loguru only.
Quick start
from vexy_lines import parse, GroupInfo, LayerInfo
doc = parse("artwork.lines")
print(doc.caption, doc.dpi) # "My Art" 300
print(doc.props.width_mm, "x", doc.props.height_mm, "mm")
# Walk the layer tree
for node in doc.groups:
if isinstance(node, GroupInfo):
for child in node.children:
if isinstance(child, LayerInfo):
for fill in child.fills:
p = fill.params
print(p.fill_type, p.color, f"interval={p.interval}")
# "linear" "#1a2b3c" interval=2.5
for image_filter in fill.image_filters:
print(image_filter.name, image_filter.params)
# "brightness" {"value": 25.0}
# Embedded document source image (JPEG)
if doc.source_image_data:
open("source.jpg", "wb").write(doc.source_image_data)
# Every embedded source image: document first, then group sources
for source in doc.source_images:
print(source.index, source.scope, source.owner_path, source.width, source.height)
# Embedded preview image (PNG)
if doc.preview_image_data:
open("preview.png", "wb").write(doc.preview_image_data)
Convenience wrappers for image extraction:
from vexy_lines import extract_source_image, extract_source_images, extract_preview_image
extract_source_image("artwork.lines", "source.jpg")
extract_source_images("artwork.lines", "artwork-sources/")
extract_preview_image("artwork.lines", "preview.png")
API
Read-only parser. This package parses
.linesfiles but does not support creating or writing them. For creating and manipulating.linesdocuments, usevexy-lines-apywith the MCP API.
parse(path) -> LinesDocument
Parse a .lines file and return a fully populated LinesDocument.
FileNotFoundError— path does not existxml.etree.ElementTree.ParseError— file is not valid XML
parse_string(xml_text) -> LinesDocument
Parse a .lines XML string (in-memory) and return a LinesDocument. Useful when the XML content is already loaded or received from another source.
xml.etree.ElementTree.ParseError— string is not valid XML
extract_source_image(path, output) -> Path
Parse and save the document-level embedded JPEG source image to output. Raises ValueError if no source image is present.
extract_source_images(path, output_dir) -> list[Path]
Parse and save every canonical source image: the document source first, then source images attached to groups. Href references are ignored. Output files use stable names such as artwork-source-001-document.jpg and artwork-source-002-face.jpg.
extract_preview_image(path, output) -> Path
Parse and save the embedded PNG preview to output. Raises ValueError if no preview is present.
Editing .lines files
Three helpers edit a .lines file while preserving everything else (fill parameters, masks, mesh, document settings) byte-for-byte. Each writes to output_path (pass the same path as the input to edit in place).
replace_source_image(lines_path, new_image_path, output_path, *, target_size=None) -> Path
Swap the embedded JPEG source image, reusing a .lines file's fill style with new content. Requires pillow. Raises FileNotFoundError if an input is missing, ValueError if there is no <SourcePict>.
rename_objects(lines_path, output_path, renames) -> int
Rewrite the caption of groups, layers, and/or fills. renames maps object_id (from GroupInfo/LayerInfo/FillNode) to a new caption; returns the number actually changed (a caption already equal to its target is not counted). Only canonical definitions are touched — href reference elements have no object_id.
set_visibility(lines_path, output_path, visible) -> int
Set the visible="0"/"1" attribute (absent = visible) per object_id; returns the number changed. Toggling visibility live over the app's MCP API does not change what the app exports, but baking the attribute into a copy and re-opening it does — this is how the AI-rename feature renders one fill in isolation.
from vexy_lines import rename_objects, set_visibility
rename_objects("artwork.lines", "artwork.lines", {1: "Background", 10: "Sky lines"})
set_visibility("artwork.lines", "fill_10_only.lines", {10: True, 11: False, 12: False})
Both raise FileNotFoundError if lines_path is missing.
Types
| Type | Key attributes |
|---|---|
LinesDocument |
caption, version, dpi, props, groups, source_image_data, source_images, preview_image_data |
DocumentProps |
width_mm, height_mm, dpi, thickness_min/max, interval_min/max |
GroupInfo |
caption, object_id, expanded, `children: list[GroupInfo |
LayerInfo |
caption, object_id, visible, mask, fills: list[FillNode], grid_edges |
FillNode |
xml_tag, caption, params: FillParams, image_filters: list[ImageFilterEntry], object_id |
FillParams |
fill_type, color, interval, angle, thickness, smoothness, uplimit, downlimit, multiplier, dispersion, shear, raw |
ImageFilterEntry |
type_id, name, params, raw |
MaskInfo |
mask_type, invert, tolerance |
SourceImageInfo |
index, data, scope, caption, object_id, owner_caption, owner_path, width, height |
FillParams.raw holds every original XML attribute, including algorithm-specific keys not promoted to named fields.
FillNode.image_filters holds the ordered source-image filter chain saved inside a fill's <image_filters> child. Known filters are named brightness, contrast, blur, sharpen, levels, shadows_highlights, invert, remove_background, color, and gradient; unknown future filter IDs are preserved as unknown_<id> with their raw attributes.
Colors are normalised to #RRGGBB (opaque) or #RRGGBBAA. The raw Vexy Lines #AARRGGBB encoding is converted automatically.
Fill types
11 fill algorithms are recognised in FillParams.fill_type:
| Value | Algorithm | XML Tag |
|---|---|---|
linear |
Parallel straight lines | LinearStrokesTmpl |
wave |
Sine-wave strokes | SigmoidStrokesTmpl |
circular |
Concentric circles | CircleStrokesTmpl |
radial |
Lines radiating from a centre point | RadialStrokesTmpl |
spiral |
Archimedean spirals | SpiralStrokesTmpl |
scribble |
Random scribble-style strokes | ScribbleStrokesTmpl |
halftone |
Halftone dot/line patterns | HalftoneStrokesTmpl |
handmade |
Sketch-style handmade strokes | FreeCurveStrokesTmpl |
fractals |
Fractal / Peano space-filling strokes | PeanoStrokesTmpl |
trace |
Strokes following image contours | TracedAreaTmpl |
source_strokes |
Strokes derived from the source image | SourceStrokes |
FreeCurveStrokesTmpl with attribute type_conv="9" is resolved to trace at parse time (otherwise handmade).
The mapping from XML tags to these names is available as FILL_TAG_MAP. The full set of recognised tags is FILL_TAGS.
Full documentation
Read the docs for the complete API reference, file format specification, and more examples.
License
MIT
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 vexy_lines_py-1.0.36.tar.gz.
File metadata
- Download URL: vexy_lines_py-1.0.36.tar.gz
- Upload date:
- Size: 11.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f75ccbd9b841c22e0f41958413c923ed99b201836db4e45dae38194559af0ed7
|
|
| MD5 |
b8175b53be386f86aee42137a0658d8f
|
|
| BLAKE2b-256 |
cb60d2e37b1ace658af00f725cf5a549378d0eaefc2f0b01192c8a21d75d503d
|
File details
Details for the file vexy_lines_py-1.0.36-py3-none-any.whl.
File metadata
- Download URL: vexy_lines_py-1.0.36-py3-none-any.whl
- Upload date:
- Size: 24.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
15783a20711ffecc67641bb4b208dae74c769bcbc4de1081e2d29906bbd892dc
|
|
| MD5 |
7cdd31f244227e56233e14c0ed5fabdb
|
|
| BLAKE2b-256 |
42e31c3fcd09df67eb12be236a98d5786cf0ce5570fbbf6245219fb40de63ccc
|