Release 1.0.0-alpha.4
Rust / test (push) Has been cancelled
Rust / wasm-safety (core) (push) Has been cancelled
Rust / Node package (push) Has been cancelled

Bump every package version to 1.0.0-alpha.4 (PyPI 1.0.0a4) and promote the
CHANGELOG [Unreleased] section to 1.0.0-alpha.4. Refresh the tracked lockfile.
App download links are intentionally left at 1.0.0-alpha.3 (desktop app
release lands separately).
This commit is contained in:
Chris Tsang
2026-08-29 00:57:43 +01:00
parent 1ddc9ebbf7
commit 2500df76b5
11 changed files with 63 additions and 27 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
## 1.0.0-alpha.4 - 2026-08-29
### Changed
Generated
+3 -3
View File
@@ -984,7 +984,7 @@ dependencies = [
[[package]]
name = "vtracer"
version = "1.0.0-alpha.3"
version = "1.0.0-alpha.4"
dependencies = [
"flo_curves 0.8.0",
"image",
@@ -994,7 +994,7 @@ dependencies = [
[[package]]
name = "vtracer-bench"
version = "1.0.0-alpha.3"
version = "1.0.0-alpha.4"
dependencies = [
"dssim-core",
"image",
@@ -1004,7 +1004,7 @@ dependencies = [
[[package]]
name = "vtracer-cli"
version = "1.0.0-alpha.3"
version = "1.0.0-alpha.4"
dependencies = [
"clap",
"image",
+1 -1
View File
@@ -19,7 +19,7 @@ exclude = [
resolver = "2"
[workspace.package]
version = "1.0.0-alpha.3"
version = "1.0.0-alpha.4"
authors = ["Chris Tsang <chris.2y3@outlook.com>"]
edition = "2024"
license = "MIT OR Apache-2.0"
+4 -4
View File
@@ -155,7 +155,7 @@ VTracer 1.0 is a vectorization framework with pluggable stages: segmentation, cu
### Rust Library
```sh
cargo add vtracer@1.0.0-alpha.3
cargo add vtracer@1.0.0-alpha.4
```
```rust
@@ -185,12 +185,12 @@ let seg = pipeline.segment(&img)?; // the expensive part
let doc = pipeline.finish(&seg)?; // VectorDoc, ready to serialize
```
See [docs.rs/vtracer](https://docs.rs/vtracer/1.0.0-alpha.3/vtracer/) for the full API.
See [docs.rs/vtracer](https://docs.rs/vtracer/1.0.0-alpha.4/vtracer/) for the full API.
### Python Library
```sh
pip install vtracer==1.0.0a3
pip install vtracer==1.0.0a4
```
```python
@@ -222,7 +222,7 @@ See [`crates/vtracer-py`](crates/vtracer-py/README.md) for the full API.
[`@visioncortex/vtracer`](https://www.npmjs.com/package/@visioncortex/vtracer) is available for Node as a WebAssembly build (from the [`nodejs`](nodejs/README.md) package) — image decoding and vectorization both run in wasm, so there is **no native dependency**. Decodes PNG, JPEG, GIF, BMP, and WebP; for other formats, decode yourself and pass raw RGBA to `convertPixels`.
```sh
npm install @visioncortex/vtracer@1.0.0-alpha.3
npm install @visioncortex/vtracer@1.0.0-alpha.4
```
```js
+34 -7
View File
@@ -64,8 +64,13 @@ pub struct FidelityReport {
fn dssim_score(a_rgb: &[u8], b_rgb: &[u8], w: usize, h: usize) -> f64 {
let d = dssim_core::Dssim::new();
let to = |buf: &[u8]| {
let px: Vec<rgb::RGB<u8>> =
(0..w * h).map(|i| rgb::RGB { r: buf[i * 3], g: buf[i * 3 + 1], b: buf[i * 3 + 2] }).collect();
let px: Vec<rgb::RGB<u8>> = (0..w * h)
.map(|i| rgb::RGB {
r: buf[i * 3],
g: buf[i * 3 + 1],
b: buf[i * 3 + 2],
})
.collect();
d.create_image_rgb(&px, w, h).expect("dssim image")
};
let (val, _) = d.compare(&to(a_rgb), &to(b_rgb));
@@ -75,7 +80,13 @@ fn dssim_score(a_rgb: &[u8], b_rgb: &[u8], w: usize, h: usize) -> f64 {
/// Compare an original against a candidate reconstruction, both RGB8, w×h.
/// `thresh` is the RGB Euclidean bad-pixel gate (use [`DEFAULT_THRESH`]).
/// Returns the report plus the bad-pixel mask (255/0, one byte per pixel).
pub fn fidelity(orig_rgb: &[u8], cand_rgb: &[u8], w: usize, h: usize, thresh: f64) -> (FidelityReport, Vec<u8>) {
pub fn fidelity(
orig_rgb: &[u8],
cand_rgb: &[u8],
w: usize,
h: usize,
thresh: f64,
) -> (FidelityReport, Vec<u8>) {
assert_eq!(orig_rgb.len(), w * h * 3);
assert_eq!(cand_rgb.len(), w * h * 3);
@@ -108,7 +119,11 @@ pub fn fidelity(orig_rgb: &[u8], cand_rgb: &[u8], w: usize, h: usize, thresh: f6
// the signature of a slightly blurred/compressed source) vanish; genuine
// missing patches survive. The reported mask keeps the raw bad pixels.
let at = |m: &[u8], x: i64, y: i64| {
x >= 0 && y >= 0 && (x as usize) < w && (y as usize) < h && m[y as usize * w + x as usize] != 0
x >= 0
&& y >= 0
&& (x as usize) < w
&& (y as usize) < h
&& m[y as usize * w + x as usize] != 0
};
let mut eroded = vec![0u8; w * h];
for y in 0..h as i64 {
@@ -142,7 +157,11 @@ pub fn fidelity(orig_rgb: &[u8], cand_rgb: &[u8], w: usize, h: usize, thresh: f6
let patch_mass = if sizes.is_empty() {
0.0
} else {
sizes.iter().map(|&a| (a as f64) * (a as f64)).sum::<f64>().sqrt()
sizes
.iter()
.map(|&a| (a as f64) * (a as f64))
.sum::<f64>()
.sqrt()
};
let p_frac = patch_mass / (w * h) as f64;
@@ -212,7 +231,12 @@ mod tests {
assert!((rd.s_patch - 1.0).abs() < 1e-9);
// identical PSNR/RMSE by construction; the patch axis must separate them
assert!((rb.rmse - rd.rmse).abs() < 1e-9);
assert!(rb.s_patch < rd.s_patch * 0.25, "blob {} dust {}", rb.s_patch, rd.s_patch);
assert!(
rb.s_patch < rd.s_patch * 0.25,
"blob {} dust {}",
rb.s_patch,
rd.s_patch
);
assert!(rb.fidelity < rd.fidelity);
}
@@ -231,7 +255,10 @@ mod tests {
let (rf, _) = fidelity(&clean, &fil, 64, 64, DEFAULT_THRESH);
assert_eq!(rf.bad_px, 128);
assert_eq!(rf.clusters, 0);
assert!((rf.s_patch - 1.0).abs() < 1e-9, "filament must not count as a patch");
assert!(
(rf.s_patch - 1.0).abs() < 1e-9,
"filament must not count as a patch"
);
}
#[test]
+13 -4
View File
@@ -7,7 +7,7 @@
//! metrics, their [0,1] subscores, the composite fidelity, and a
//! machine-readable csv line.
use vtracer_bench::{fidelity, DEFAULT_THRESH};
use vtracer_bench::{DEFAULT_THRESH, fidelity};
fn main() {
let args: Vec<String> = std::env::args().collect();
@@ -49,11 +49,20 @@ fn main() {
let (r, mask) = fidelity(orig.as_raw(), &cand, w, h, thresh);
if let Some(out) = mask_out {
image::GrayImage::from_raw(w as u32, h as u32, mask).unwrap().save(&out).expect("save mask");
image::GrayImage::from_raw(w as u32, h as u32, mask)
.unwrap()
.save(&out)
.expect("save mask");
}
println!("psnr {:>8.2} dB (rmse {:.2}) -> {:.4}", r.psnr, r.rmse, r.s_psnr);
println!("ssim {:>8.5} (dssim {:.5}) -> {:.4}", r.s_ssim, r.dssim, r.s_ssim);
println!(
"psnr {:>8.2} dB (rmse {:.2}) -> {:.4}",
r.psnr, r.rmse, r.s_psnr
);
println!(
"ssim {:>8.5} (dssim {:.5}) -> {:.4}",
r.s_ssim, r.dssim, r.s_ssim
);
println!(
"patch {:>8.1} px rms ({} bad px, {} clusters, largest {}) -> {:.4}",
r.patch_mass, r.bad_px, r.clusters, r.largest, r.s_patch
+1 -1
View File
@@ -15,7 +15,7 @@ name = "vtracer"
path = "src/main.rs"
[dependencies]
vtracer = { version = "1.0.0-alpha.3", path = "../vtracer" }
vtracer = { version = "1.0.0-alpha.4", path = "../vtracer" }
visioncortex.workspace = true
# Decode-only: trimmed to real input formats (drops the AV1 encoder + OpenEXR).
image = { version = "0.25", default-features = false, features = [
+2 -2
View File
@@ -1,7 +1,7 @@
[package]
name = "vtracer-py"
description = "Python bindings for the vtracer vectorization framework."
version = "1.0.0-alpha.3"
version = "1.0.0-alpha.4"
authors = ["Chris Tsang <tyt2y7@gmail.com>"]
edition = "2024"
license = "MIT OR Apache-2.0"
@@ -19,7 +19,7 @@ name = "vtracer"
crate-type = ["cdylib"]
[dependencies]
vtracer = { version = "1.0.0-alpha.3", path = "../vtracer" }
vtracer = { version = "1.0.0-alpha.4", path = "../vtracer" }
# Decode-only: trimmed to real input formats (drops the AV1 encoder + OpenEXR).
image = { version = "0.25", default-features = false, features = [
"png", "jpeg", "gif", "bmp", "webp", "tiff", "ico", "pnm", "tga", "qoi",
+1 -1
View File
@@ -36,7 +36,7 @@ Technical descriptions of the [tracing algorithm](https://www.visioncortex.org/v
## Install
```sh
pip install vtracer==1.0.0a3
pip install vtracer==1.0.0a4
```
## Usage
+2 -2
View File
@@ -1,7 +1,7 @@
[package]
name = "vtracer-wasm"
description = "WebAssembly core for the vtracer Node.js package."
version = "1.0.0-alpha.3"
version = "1.0.0-alpha.4"
authors = ["Chris Tsang <tyt2y7@gmail.com>"]
edition = "2024"
license = "MIT OR Apache-2.0"
@@ -15,7 +15,7 @@ repository = "https://github.com/visioncortex/vtracer/"
crate-type = ["cdylib"]
[dependencies]
vtracer = { version = "1.0.0-alpha.3", path = "../crates/vtracer" }
vtracer = { version = "1.0.0-alpha.4", path = "../crates/vtracer" }
wasm-bindgen = "0.2"
serde = { version = "1", features = ["derive"] }
serde-wasm-bindgen = "0.6"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@visioncortex/vtracer",
"version": "1.0.0-alpha.3",
"version": "1.0.0-alpha.4",
"description": "Raster to vector graphics converter (SVG). WebAssembly build of the vtracer framework — no native dependencies.",
"main": "index.js",
"types": "index.d.ts",