I build Sticraft, a set of free browser tools. The one I spend most time on is an image vectorizer that turns a JPG or PNG into SVG, DXF or G-code for laser cutters, Cricut machines and pen plotters. Everything runs on the user's device. Nothing is uploaded.
Clean test logos traced fine from day one. Real files from real people did not. This post is a list of the failures I hit and what fixed each one, in case you are building something similar.
The engine
Colour and silhouette tracing use vtracer (visioncortex, 0.6.5) compiled to WebAssembly. The binary is about 143 KB. I self-host it and fetch it on first use, so the page does not pay for it until someone actually traces something. vtracer does proper curve fitting with corner detection, which is much better than midpoint corner cutting.
vtracer has no skeletonization, so the centerline mode (single-line paths for engraving and plotting, not outlines) runs on a separate tracer.
The tracing runs in a Web Worker so the page stays responsive on big images.
Failure 1: notches on every small circle
A 256 px logo traced into a circle with eight small notches, one per octant. They showed up in SVG, DXF and in the laser preview.
Cause: a hard per-pixel threshold turns a small anti-aliased circle into a staircase. The curve fitter reads the points where the stair pattern changes direction as corners.
Fix: do not threshold the native pixels. I build an "on-ness" field, blur it once with a 3x3 binomial kernel to kill JPEG ringing, upsample it (4x up to 400 px, 2x up to 800 px, native above that), threshold the upsampled field, trace at the larger size and scale the paths back. The edge now lands where the anti-aliased source actually crosses the threshold, so the staircase never exists. Cost stays under roughly 2.6 megapixels.
Failure 2: cut files nobody can weed
vtracer's speckle filter drops small black islands. A small white hole inside a shape is part of that shape's outline, though, so holes survive. One traced etching came out with around 1,600 holes under 100 square pixels. None of them can be cut or weeded on a vinyl cutter.
Fix: a connected-region pass on the mask before tracing. Black islands under minArea become background. Enclosed holes are filled only under a quarter of that, because the inside of a small "a" in 15 mm lettering is a hole too and has to stay open. Background that touches the image edge is the outside and is never touched.
On a wolf engraving this took the Cricut cut from 3,130 pieces to 366, and the letter test (the dot on an i, the counter of an a) still came through unchanged.
Failure 3: the background is not one colour
My first version assumed the background was whatever colour the corners were. Real inputs break that constantly:
- a printed logo photographed on a desk, with the phone's shadow across half of it
- old paper that yellows towards one corner
- clip art downloaded with the grey and white "transparency" checkerboard baked into the pixels
Each of these got traced as artwork. A Cricut file full of black blobs, or a laser burning a grid into wood.
Fix: a per-pixel background model. I split the image into a coarse grid of cell medians and walk inward from the border, following gradual colour change (paper tone, light falloff) but stopping at a sharp step, which is where ink starts. Cells the walk never reaches are the artwork; their background is interpolated from the surrounding paper. Then every pixel's local background is mapped to one flat colour, and everything downstream sees a clean card. Photos with no dominant border background are left alone.
How I measured it
I collected 20 deliberately bad inputs from CC0 sources: five phone photos of prints taken at an angle in shadow, five yellowed and stained scans, five images with a baked-in checkerboard, five tiny blurry 120 px files. Before these changes 8 of 20 produced a usable cut or engrave file. After, 17 of 20. The three that still fail are a decorative letter that runs to the paper edge on stained paper, and two 120 px images where the detail is simply gone.
I also re-ran 24 ordinary real images after every change to make sure photos were not being flattened by mistake.
What I would tell someone starting this
- Test on ugly files from day one. Clean logos hide almost every real problem.
- Fix things before the tracer, not after. Cleaning the mask is simple; cleaning curves is not.
- Keep one coordinate space for every export (SVG, DXF, EPS, PDF, G-code). Supersampling only works because the paths are scaled back before anything else sees them.
If you have built a vectorizer and found inputs that break it, I'd like to hear about them.
Disclosure: an AI agent wrote this post for me from my project's code and test notes. The numbers come from the project's own measurements.
Top comments (0)