diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d8e8c9..fc16463 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/Cargo.lock b/Cargo.lock index 26dd061..2d99ba9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index 411cdbc..e85ee31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ exclude = [ resolver = "2" [workspace.package] -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.4" authors = ["Chris Tsang "] edition = "2024" license = "MIT OR Apache-2.0" diff --git a/README.md b/README.md index 2543fa5..07f4244 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/crates/vtracer-bench/src/lib.rs b/crates/vtracer-bench/src/lib.rs index 767e494..98e37e4 100644 --- a/crates/vtracer-bench/src/lib.rs +++ b/crates/vtracer-bench/src/lib.rs @@ -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> = - (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> = (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) { +pub fn fidelity( + orig_rgb: &[u8], + cand_rgb: &[u8], + w: usize, + h: usize, + thresh: f64, +) -> (FidelityReport, Vec) { 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::().sqrt() + sizes + .iter() + .map(|&a| (a as f64) * (a as f64)) + .sum::() + .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] diff --git a/crates/vtracer-bench/src/main.rs b/crates/vtracer-bench/src/main.rs index cf947c1..391afbf 100644 --- a/crates/vtracer-bench/src/main.rs +++ b/crates/vtracer-bench/src/main.rs @@ -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 = 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 diff --git a/crates/vtracer-cli/Cargo.toml b/crates/vtracer-cli/Cargo.toml index d52b6eb..ef5baf8 100644 --- a/crates/vtracer-cli/Cargo.toml +++ b/crates/vtracer-cli/Cargo.toml @@ -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 = [ diff --git a/crates/vtracer-py/Cargo.toml b/crates/vtracer-py/Cargo.toml index 66dd04a..97aa807 100644 --- a/crates/vtracer-py/Cargo.toml +++ b/crates/vtracer-py/Cargo.toml @@ -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 "] 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", diff --git a/crates/vtracer-py/README.md b/crates/vtracer-py/README.md index 40b1ebc..fcd897c 100644 --- a/crates/vtracer-py/README.md +++ b/crates/vtracer-py/README.md @@ -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 diff --git a/nodejs/Cargo.toml b/nodejs/Cargo.toml index e800be4..139d226 100644 --- a/nodejs/Cargo.toml +++ b/nodejs/Cargo.toml @@ -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 "] 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" diff --git a/nodejs/package.json b/nodejs/package.json index 912d1b3..78a0e20 100644 --- a/nodejs/package.json +++ b/nodejs/package.json @@ -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",