mirror of
https://github.com/visioncortex/vtracer.git
synced 2026-09-12 23:25:53 -07:00
c3f56a6339
Three refinements that make the watershed frontend a first-class citizen of both compositing modes and of interactive tuning: Stacked mode now stacks for real. Instead of one full-canvas background plus disjoint regions, the cut emits the merge tree itself: the root (whole canvas, mean color) first, then progressively finer ancestor regions, then the final regions on top — the same principle as the color clustering frontend, just with watershed-born clusters. Sub-pixel gaps between abutting regions therefore show their common ancestor's color rather than an unrelated backdrop, and overdraw stays seam-free. A painted-area budget (3x canvas) keeps pathological persistence chains from ballooning the stack; the root and final regions are always emitted so coverage never depends on it. Cutout is native. The watershed hierarchy already decided every merge, so the flattened partition reaches the mosaic untouched: merge_diff is 0 for watershed (the gradient-step re-merge still applies to the color path). Faces are exactly the cut regions. Re-cuts are cached. WatershedHierarchy is now public and split into build(img) — Kruskal, BPT, volume persistence; depends only on the image — and cut(detail, min_area), which is near-linear: region formation, graph-level small-basin absorption (region adjacencies, not pixel sweeps), then the merge tree. Session builds the hierarchy lazily on the first watershed render and re-cuts it on every watershed_detail or filter_speckle change: ~25 ms per re-cut vs ~40 ms rebuild on a 1400x775 photo, with the one-shot Frontend::segment path unchanged (build + cut), so Session output still equals the one-shot pipeline exactly. Tests: flatten-based stack invariants (solid bottom layer, full coverage, final regions topmost, exact region counts), hierarchy re-cut == one-shot, Session re-cut == one-shot across detail changes, and cutout keeping two regions one gradient step apart that the color path's merge would rejoin. Watershed goldens re-blessed for the new stack structure.
VTracer 1.0 Design Documents
VTracer is being rearchitected from a single hardcoded pipeline into a vectorization framework. These documents describe the target design.
| Document | Contents |
|---|---|
| architecture.md | Workspace layout, core IR, stage traits, pipeline driver, optimizer & SVG writer, CLI |
| mosaic.md | The seam-free cutout/mosaic mode: boundary-graph tracing and shared-edge curve fitting |
| bindings.md | Python (PyPI), wasm, and the new Node.js (npm) package |
| roadmap.md | Milestones and verification strategy |
Motivation
VTracer today (0.6.x) is a thin driver around the visioncortex crate: one pipeline (color clustering → per-cluster tracing → SVG string), a CLI, a pyo3 binding, and a web demo that duplicates the pipeline. The rewrite turns it into a framework with pluggable stages:
- Frontend — any algorithm that produces clusters/segmentation from a raster image
- Curve fitting backend — pluggable polyline→curve fitters (pixel, polygon, spline, future potrace-style)
- Color fitting — mapping cluster colors to final paints, including custom fixed palettes
- Optimizer — a pass pipeline that shrinks output (relative path syntax, shorthand commands, precision reduction)
- True mosaic cutout — a perfect, gapless tessellation with shared boundary geometry, replacing today's fake cutout (which re-clusters a re-rendered image and shows seams)
The project stays backend/CLI focused, and everything except image file I/O compiles to wasm32-unknown-unknown.
Decisions
visioncortexremains a dependency, wrapped behind traits. Development uses a path/[patch]dependency on the local checkout; API additions are committed to visioncortex directly and published as 0.8.x releases. Verified that everything the new design needs is already public: the fitting primitives (fit_points_with_bezier,find_corners,subdivide_keep_corners,reduce,PathSimplify::*) and cluster pixel access viaClustersView.- In-repo rewrite, clean break. New workspace layout, new API, version bump. Old CLI flags are kept only where they map naturally.
- Python binding stays (ported to the new API). The webapp GUI is dropped; a wasm library crate replaces it.
- New Node.js library published to npm, using the wasm build internally plus a native image reader (sharp).
Pipeline at a glance
┌───────────┐ ┌──────────────┐ ┌─────────────────────────────┐
raster ───▶ │ Frontend │ ─▶│ ColorFitter* │ ─▶│ Compositing │
image │ (segment) │ │ (palette, │ │ Stacked: closed outlines │
└───────────┘ │ quantize, │ │ Mosaic: boundary graph + │
│ merge) │ │ shared-edge fit │
└──────────────┘ └──────────────┬──────────────┘
│ CurveFitter
▼ (pixel/polygon/spline)
┌──────────────────────────────┐
SVG ◀──── │ VectorDoc ─ OptimizerPass* ─ │
│ SvgWriter │
└──────────────────────────────┘