AlansCodeLog / vectortracer

Wasm bindings to Visioncortex's VTracer library, a rust image vectorizer library.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Build Release

Wasm bindings to Visioncortex's VTracer library.

Features

  • Compatible with webworkers.
    • Webworker wrapper example.
  • Optional debug mode (note this will be slower).
  • Binary Image Converter
    • Option to invert image data.
    • Control over svg path and background color.
    • Arbitrary attributes.
    • Option to scale paths group.
  • Publish
  • Color Image Converter

Installation

npm install vectortracer

The package can also be installed directly from the git repo like so:

npm install https://github.com/alanscodelog/vectortracer

Usage

This is a simple example showing how to create a wrapper function using a promise with setTimeout.

import { BinaryImageConverter, BinaryImageConverterParams, Options } from "vectortracer"

export function imageDataToSvg(
	imageData:ImageData,
	vtracerOptions:BinaryImageConverterParams,
	additionalOptions:Options
): string {
	const converter = new BinaryImageConverter(
		imageData,
		vtracerOptions,
		additionalOptions
	)

	return new Promise(resolve => {
		let done = false
		let progress = 0
		const tick = () => {
			done = converter.tick()
			progress = converter.progress()
			if (!done) {
				setTimeout(tick, 0)
			} else {
				const result = converter.getResult()
				converter.free()
				resolve(result)
			}
		}
		converter.init()
		setTimeout(tick, 0)
	}).catch(err => {
		...
	}) as Promise<string>
}

You can then use the function like so:

const canvas = document.getElementById("my-canvas")
const ctx = canvas.getContext("2d")
const imageData = ctx.getImageData(0, 0, size.width, size.height)

const result = await imageDataToSvg(imageData, vtracerOptions, additionalOptions)
// if you have access to the DOM you can parse it to an svg element like so

const parser = new DOMParser()
const svg = parser.parseFromString(res as string, "image/svg+xml").children[0] as SVGElement

Notes

The code is similar, but simpler than the one use in visioncortex's demo web app code. ImageData can be passed directly from js, instead of having to give it a canvas id and having that fragile connection. This means we can use the library from a webworker. What we do lose is the ability to get an SVG element back, again because we don't have access to the DOM in a webworker.

I have not benchmarked it properly yet, but in the app I wrote this for, the transformation seems to take on average a little bit more time (~20ms), but I get more varied times, sometimes faster, sometimes slower, and there are other things running in the background. Still, I think this is the simplest option* if we want to allow the UI to stay responsive. You can see in the demo app that with large images and expensive parameters the UI can freeze despite its use of setTimeout to try and mitigate this.

To try to avoid any slowdowns from crossing the js/wasm boundary, Tsify with serde-wasm-bindgen is used to provide faster serialization/deserialization (it converts js types directly to/from rust) compared to json serialization/deserialization, which is slower.

* The other possible option is having a wrapper function that takes care of creating a canvas, or using an offscreen canvas in the worker. I wanted to avoid this since for my use case I might not always have a canvas, but I do always have the ImageData.

Building

There is a root level package json that has the needed prepare script.

The pkg/package.json generated by wasm-pack is not used and is actually deleted upon building since it can cause issues because the js is esm, but the package.json is missing "type": "module" and the exports field.

It should theoretically be possible to also use the package from nodejs. It is at least properly importing for me without errors.

About

Wasm bindings to Visioncortex's VTracer library, a rust image vectorizer library.


Languages

Language:Rust 97.6%Language:Shell 2.4%