DIAGRAM EDITION  the stages in plain languageReference edition →

Stage 1 of 14

Giving the file a fair reading before anything else runs

Before a single shape is traced, the file has to be checked for things that would otherwise be mistaken for artwork: a sneaky resize, a compressed file pretending to be clean, transparency that has nowhere to go in the maths, and a size the rest of the tool was never calibrated against. This stage settles all of that, quietly, so every later stage can trust the pixels it is handed.

The file is not the same thing as the drawing

It is tempting to think of a PNG or a JPEG as simply "the picture" — open it, trace what is there. But a raster file is one snapshot of a drawing, at one size, saved by one program, and any of those three facts can quietly work against the tracer.

Someone with a small logo who wants a large one often resizes the file first, with the crudest possible method, before it ever reaches this tool. A photo-style compressed file adds faint ripples of colour near edges that were never part of the original artwork. And a file with a transparent background hands the tracer a problem it has no way to solve directly — the maths behind reading an edge (stage 2) needs two solid colours to measure a boundary against, not one colour and a see-through hole.

Intake is where all of that gets sorted out, before the palette, the boundaries, or anything downstream ever looks at a pixel.

Undoing an accidental zoom

Resize a small image with the simplest method a computer offers — "nearest neighbour" — and every pixel becomes a solid square block, four, eight, sixteen times its original size. Nothing new was drawn; the same handful of pixels was just repeated. A tracer that does not know this happened will faithfully draw the staircase of block edges, because as far as it can tell, that staircase is the artwork.

A block upscale, and its exact inverse original, 4x4 viewer resizes 4x -> what arrives, 16x16 of blocky squares every 4x4 block is one flat colour, exactly detected -> averaged back down traced at identical to the original
The blow-up is exactly reversible: average every constant block and the original pixels come back unchanged. Once that pattern is recognised, the tracer works on the small original — and still writes the SVG at the size the file claimed.

This check is deliberately strict — every pixel in every block has to match exactly, with no wiggle room. A looser test would also catch a logo that genuinely contains large flat squares, and undoing those would throw away real artwork. On a 96-pixel logo blown up to 768 pixels, skipping this step means the tracer describes the staircase directly: thirteen colours instead of three, and over fifteen hundred straight little lines walking around pixel corners instead of the handful of smooth curves the artist actually drew.

Telling a compressed file from a clean one

Photo-style compression (the kind JPEG uses) does not blur an edge — it leaves the edge itself mostly alone and instead adds a faint ripple of colour in the flat areas just beside it, an artefact of how the compressor represents smooth regions cheaply. Two different checks were tried to catch this automatically, and both were fooled, for related reasons worth stating honestly rather than glossing over:

  • Measuring how wide an edge is does not see it, because the ripple does not widen the edge — it sits beside it, in territory the width measurement is not looking at.
  • Measuring random noise in flat areas does not see it either, because the ripple only occupies a thin band next to each edge; an icon is mostly empty, so the "typical" noise level across the whole image stays at its floor, exactly as it would on a perfectly clean file.

This was not a hypothetical risk. A real compressed logo measured a native 1.15-pixel edge width against a 1.75-pixel threshold meant to catch resizing damage — comfortably under it — so the safeguard that should have caught the damage stayed off, and the tracer dutifully treated the compression ripple as real ink. The result was 243 separate paths across 1301 separate regions, 89% of which together covered only 5% of the drawing — noise, not artwork, each ripple minted as its own tiny shape.

Same edge width, same noise reading, different history clean file edge width 1.15px, noise at the floor compressed file edge still reads 1.15px; the ripples never widen it The honest fix: ask the file JPEG and one flavour of WebP are always lossy. PNG, GIF, BMP and TIFF never are. The container format says so directly — no inference needed. 243 paths, 1301 faces -> 80 paths, 654 faces artwork intact, ripples gone
Neither pixel-level check can separate lossy ringing from a clean file — one reads the same width either way, the other reads the same noise floor either way. The fix asks a question the pixels cannot answer: what format was this file actually saved in.

A third pixel-level idea was also tried and also refuted: measuring how jagged the colour is in supposedly flat areas. It separated clean files from compressed ones cleanly — until it met a genuinely clean smooth gradient, which scored as more "damaged" than the compressed flat icon, because ordinary 8-bit colour ramps produce the same kind of small jumps a lossy codec does. There is no separating the two from pixel statistics alone. So the fix does not try to get cleverer about pixels — it reads the file's own container format, which states the fact exactly rather than estimating it. A JPEG is lossy. A PNG is not. A WebP says which of its two internal codecs it used, right there in its header.

This matters for a reason beyond one file type. Turning this safeguard on unconditionally, for every file whether it needs it or not, was tried and measured: it costs 10.9% on the tool's own quality benchmark, because on a genuinely clean file, two very similar colours really are two different inks the artist chose, and merging them throws real artwork away. The safeguard has to stay off until there is real evidence — a wide edge, or a compressed file format — that it is needed.

Same logo, four times the pixels, wildly different results

Export the same logo as a 128-pixel PNG and as a 512-pixel PNG. It is the same drawing. It should cost the same number of points and curves to describe in an SVG. For a long time, it did not — and the reason is worth walking through carefully, because it is one of the more surprising things about how this tool was tuned.

Every measurement this tool takes is stated in pixels: how confidently an edge is located, how precisely a coordinate is written down, how big a stray speck has to be before it is worth ignoring. All of those numbers were chosen by testing against images around 128 pixels on a side. Hand the same logo in at 512 pixels and nothing about those numbers changes automatically — but the boundary itself is now drawn with four times as many points, each one sitting four times as far (in raw pixels) from where a simplified curve would put it, for exactly the same shape. The book-keeping that is supposed to discourage adding unnecessary detail barely reacted — it only grew by a small, slow amount, nowhere near enough to offset how much more "wrong" a simplified curve now looks in raw-pixel terms. Faced with that imbalance, the tool kept buying more and more detail it did not actually need, one cheap-looking segment at a time.

Measured directly, on real brand logos, the effect was severe and got worse with size: 3.54 times the artist's own number of points at 128 pixels, 6.02 times at 256, 11.62 times at 512 — for a mark whose actual complexity had not changed at all.

Same shape, priced per pixel versus priced per unit of content 128px export a handful of points 512px export, priced per raw pixel 11.62x the points, same star 512px, priced per unit of content back to a handful The fix: widen the allowed tolerance in proportion to how much bigger the raster is, so a curve is judged against the drawing's own scale rather than raw pixels.
Nothing about the artwork changed between the middle and right panels — only how the tolerance for "close enough" was measured.

The fix is to stop pricing everything in raw pixels and start pricing it per unit of the drawing's own content: work out how many "reference units" bigger this raster is than the 128-pixel size everything was tuned at, and widen the allowed tolerance by that same factor before fitting a single curve. A boundary point's permitted wobble room grows with the image, so a curve that would have been accepted at 128 pixels is accepted again at 512, from the same relative position.

This is turned off by default, because it is a genuine trade rather than a free correctness fix. Under it, a five-pixel square rotated slightly can get mistaken for a circle, and a thin ring two pixels wide can come out broken, in exchange for roughly a fifth fewer points overall. It is offered as an option, not switched on everywhere, because sometimes exact pixel fidelity matters more than a tidy point count.

Worth stating plainly: this correction, as shipped, widens how much wobble a curve is allowed before it fails — but it does not fully rebalance the cost side of the trade the way its own design notes say it should. That is flagged as an open question in the technical reference rather than glossed over here.

When there is nothing solid to measure against

Stage 2's whole method for reading an edge depends on knowing the two colours a boundary sits between — a shape's own colour, and whatever is behind it. A transparent background is not a colour at all, so before tracing starts, every see-through pixel is painted over with something solid.

The obvious choice is white, and white is exactly wrong for a lot of real artwork. A white logo on a transparent background, painted onto white, disappears completely — there is nothing left to trace. A softly translucent panel painted onto white loses its identity and merges into the background it was meant to sit over.

So the colour used to fill in the transparency is chosen by testing what it would hide: for each of a short list of candidate colours (white first, then black, then a few saturated colours real artwork rarely uses), the tool checks how much of the image's meaningfully-drawn content — the outline of the shape, and any softly translucent area — would become indistinguishable from that candidate once painted onto it. The first candidate that would not swallow too much of the real content wins. A soft glow (opacity that fades gradually, like a light source) gets no vote either way, because no single flat colour can honestly stand in for something that was never one flat opacity to begin with.

By default this choice never actually changes anything visible in the output — the image is still matted to plain white — because without an extra flag turned on, transparency has nowhere to go in the final file anyway: a see-through region gets painted solid rather than cut out as a hole. The smarter colour choice only takes effect once that flag is on, and it exists specifically so the file can be produced for use on a background other than white.

Cleaning up genuine damage

Some input is not merely resized or slightly compressed — it is a screenshot, a heavily compressed export, or a genuine photograph of a printed logo. For that kind of damage, there is an optional cleanup step: run the image through a small model that guesses at extra detail, shrink the result back down, and repaint the flat areas with the original file's own colours so the tracer is not trusting the model's colour judgement, only its judgement about where edges should sit.

This step is expensive and not always worth it, so the tool can be told to decide for itself. In that mode, it traces the file once as it arrived, renders that trace back into a picture, and compares the two everywhere the trace claims the drawing is flat. A flat trace that disagrees with the input in supposedly flat territory is a sign of real damage rather than an honest simplification — a shape that is flat by construction should not need to argue with a clean input. Below a measured disagreement threshold, the file is traced as-is. Above it, the cleanup step runs and the file is traced again. On genuinely clean input, running this cleanup step anyway makes results roughly three times worse — which is exactly why the tool checks first rather than always cleaning up "just in case."