diff --git a/crates/vtracer-py/README.md b/crates/vtracer-py/README.md index 29216f6..49adf29 100644 --- a/crates/vtracer-py/README.md +++ b/crates/vtracer-py/README.md @@ -51,10 +51,11 @@ properties, plus the presets `Config.bw()`, `Config.poster()`, `Config.photo()`: | `length_threshold` | `4.0` | px | | `max_iterations` | `10` | | | `splice_threshold` | `45` | degrees | +| `simplify` | `None` | curve simplification tolerance in px (try 1–2.5) | | `path_precision` | `2` | output decimal places | | `palette` | `None` | list of `#rrggbb` strings | | `max_colors` | `None` | auto-quantize target | -| `optimize` | `1` | `0` off, `1` quantize+simplify, `2` + shorthands | +| `optimize` | `1` | `0` off, `1` quantize+cleanup, `2` + shorthands | | `binary_threshold` | `128` | bw: fixed cutoff, foreground below it | | `adaptive` | `False` | bw: Bradley–Roth adaptive thresholding | | `adaptive_window` | `0` | bw adaptive: window px (`0` = auto) | diff --git a/crates/vtracer-py/src/lib.rs b/crates/vtracer-py/src/lib.rs index cdba7c3..3ae5129 100644 --- a/crates/vtracer-py/src/lib.rs +++ b/crates/vtracer-py/src/lib.rs @@ -140,6 +140,7 @@ impl PyConfig { length_threshold = 4.0, max_iterations = 10, splice_threshold = 45, + simplify = None, path_precision = 2, palette = None, max_colors = None, @@ -162,6 +163,7 @@ impl PyConfig { length_threshold: f64, max_iterations: usize, splice_threshold: i32, + simplify: Option, path_precision: u32, palette: Option>, max_colors: Option, @@ -188,8 +190,7 @@ impl PyConfig { length_threshold, max_iterations, splice_threshold, - // Curve simplification is not surfaced in the Python API yet. - simplify: None, + simplify, path_precision: Some(path_precision), palette, max_colors, @@ -331,6 +332,15 @@ impl PyConfig { self.inner.splice_threshold = v; } + #[getter] + fn simplify(&self) -> Option { + self.inner.simplify + } + #[setter] + fn set_simplify(&mut self, v: Option) { + self.inner.simplify = v; + } + #[getter] fn path_precision(&self) -> Option { self.inner.path_precision diff --git a/crates/vtracer-py/vtracer.pyi b/crates/vtracer-py/vtracer.pyi index 5f2b7c6..ed62d53 100644 --- a/crates/vtracer-py/vtracer.pyi +++ b/crates/vtracer-py/vtracer.pyi @@ -18,6 +18,7 @@ class Config: length_threshold: float = 4.0, max_iterations: int = 10, splice_threshold: int = 45, + simplify: Optional[float] = None, # curve simplification tolerance in px (None = off) path_precision: int = 2, palette: Optional[list[str]] = None, # e.g. ["#112233", "#445566"] max_colors: Optional[int] = None, # auto-quantize target @@ -46,6 +47,7 @@ class Config: length_threshold: float max_iterations: int splice_threshold: int + simplify: Optional[float] path_precision: Optional[int] palette: list[str] max_colors: Optional[int] diff --git a/nodejs/README.md b/nodejs/README.md index 73373bd..df6490d 100644 --- a/nodejs/README.md +++ b/nodejs/README.md @@ -37,11 +37,14 @@ const svg2 = vtracer.convertPixels(rgba, width, height, { clustering: 'bw' }); ### `Options` (all optional, camelCase) `preset` (`"bw" | "poster" | "photo"`, applied first), `clustering` -(`"color" | "bw"`), `hierarchical` (`"stacked" | "cutout"` for the seam-free -mosaic), `mode` (`"pixel" | "polygon" | "spline"`), `filterSpeckle`, -`colorPrecision`, `layerDifference`, `cornerThreshold`, `lengthThreshold`, -`maxIterations`, `spliceThreshold`, `pathPrecision`, `palette` (list of -`#rrggbb`), `maxColors`, `optimize` (`0 | 1 | 2`). +(`"color-cluster" | "bw" | "watershed"`), `hierarchical` (`"stacked" | "cutout"` +for the seam-free mosaic), `mode` (`"pixel" | "polygon" | "spline"`), +`filterSpeckle`, `colorPrecision`, `layerDifference`, `cornerThreshold`, +`lengthThreshold`, `maxIterations`, `spliceThreshold`, `simplify` (curve +simplification tolerance in px, try 1–2.5), `pathPrecision`, `palette` (list of +`#rrggbb`), `maxColors`, `optimize` (`0 | 1 | 2`), `binaryThreshold` / +`adaptive` / `adaptiveWindow` / `adaptiveT` (binary mode), `watershedDetail` +(0..=255). ## Build from source diff --git a/nodejs/index.d.ts b/nodejs/index.d.ts index e60c178..da75884 100644 --- a/nodejs/index.d.ts +++ b/nodejs/index.d.ts @@ -13,6 +13,8 @@ export interface Options { lengthThreshold?: number; maxIterations?: number; spliceThreshold?: number; + /** Curve simplification tolerance in px (omit = off; try 1-2.5). */ + simplify?: number; pathPrecision?: number; /** Fixed palette: `#rrggbb` strings. */ palette?: string[]; diff --git a/nodejs/src/lib.rs b/nodejs/src/lib.rs index eccc4c9..ce80c80 100644 --- a/nodejs/src/lib.rs +++ b/nodejs/src/lib.rs @@ -26,6 +26,8 @@ struct Options { length_threshold: Option, max_iterations: Option, splice_threshold: Option, + /// Curve simplification tolerance in px (omit = off). + simplify: Option, path_precision: Option, palette: Option>, max_colors: Option, @@ -104,6 +106,9 @@ fn config_from(options: JsValue) -> Result { if let Some(v) = opts.splice_threshold { config.splice_threshold = v; } + if let Some(v) = opts.simplify { + config.simplify = Some(v); + } if let Some(v) = opts.path_precision { config.path_precision = Some(v); } diff --git a/nodejs/test.js b/nodejs/test.js index 0526203..15b6145 100644 --- a/nodejs/test.js +++ b/nodejs/test.js @@ -12,11 +12,19 @@ let svg = vtracer.convertBuffer(data); assert(svg.includes(' all black -svg = vtracer.convertBuffer(data, { colorMode: 'bw' }); +// options: bw clustering -> all black +svg = vtracer.convertBuffer(data, { clustering: 'bw' }); assert(svg.includes('fill="#000000"'), 'bw produces black'); console.log('convertBuffer bw:', (svg.match(/', simplified.length, 'bytes'); +} + // options: mosaic + polygon + palette svg = vtracer.convertBuffer(data, { hierarchical: 'cutout', mode: 'polygon', palette: ['#000000', '#ffffff'], optimize: 2 }); assert(svg.includes('