Skip to main content

sw(a)g.converter

Locally convert raster images into real vector SVG — actual <path> data with fitted <linearGradient> / <radialGradient> fills. No embedded bitmaps, no cloud service, no API key. Everything runs on your machine.

swag logo.png
sw(a)g.converter   raster → vector
────────────────────────────────────────────────────
╭──────────────────────────────────────────────────────────────╮
│      source  logo.png  320×320  46.4 KB                      │
│     content  icon  (texture 0.00, flat 100%, 334 colours)    │
│      shapes  9 regions  ·  9 gradients  ·  1,935 nodes       │
│  similarity  98.2%                                           │
│      output  logo.svg   36.9 KB  in 1.6s                     │
╰──────────────────────────────────────────────────────────────╯

Why another tracer

Most raster-to-vector tools flatten everything into flat colour patches. Smooth shading becomes a stack of hard-edged bands, and any semi-transparent pixel is painted as if it were opaque — which is what produces the coloured "shadow" you often see around a traced image.

This one does two things differently:

  • Gradients are fitted, not faked. Neighbouring regions are merged for as long as a single linear or radial gradient still explains them, and the gradient stops are sampled from the real pixels. A shaded sphere becomes one path with one gradient instead of twenty concentric slivers.
  • Alpha is respected. The silhouette comes from the alpha channel alone, and edge pixels take their colour from the nearest solid neighbour, so a faint halo stays faint instead of turning into solid paint.

Install

pip install swag-converter

Python 3.10 or newer is the only prerequisite; that command pulls in everything else and puts a swag command on your PATH. Check it landed:

swag --version
Other ways to install

Isolated from your other packages, via pipx:

pipx install swag-converter

Straight from a release, no PyPI involved:

pip install https://github.com/CryptoNerf/swag-converter/releases/download/v0.1.0/swag_converter-0.1.0-py3-none-any.whl

From a clone, for hacking on it:

git clone https://github.com/CryptoNerf/swag-converter
cd swag-converter
pip install -e '.[dev]'

The similarity score is the one optional extra: it needs CairoSVG, so pip install 'swag-converter[quality]' (plus brew install cairo on macOS). Without it conversion works exactly the same and the score reads not measured.

Your first conversion

Point it at any image. There is nothing to configure:

swag logo.png

That writes logo.svg next to the original and prints the report above. Reading it top to bottom:

line what it tells you
source the file it read, its pixel size and weight on disk
content which preset auto picked, and the measurements behind the choice
shapes how many paths, gradients and Bézier nodes the SVG contains
similarity how closely the SVG re-renders to the original, 100% being pixel-identical — reads not measured until you install the optional CairoSVG above
output where the SVG went, how big it is, how long it took

A similarity in the nineties means the vector is a faithful stand-in for the original. If it comes out low, the image is probably photographic — see Photographs, honestly.

Nothing is ever overwritten silently except a .svg of the same name, and no file leaves your machine.

Usage

swag logo.png                         # writes logo.svg next to it
swag icons/ --out svg/                # whole folder, in parallel
swag photo.jpg --preset photo         # stylised vector from a photograph
swag art.png --quality max            # slower, closer to the source
swag *.png --json                     # machine-readable output
option what it does
-o, --out DIR Write SVGs into DIR instead of beside each input
-p, --preset auto (default), icon, illustration, photo, poster
-q, --quality fast, balanced (default), max
--max-edge PX Resize the longer edge before tracing (default 1024, 0 disables)
--background auto (default), always, keep — clear a flat backdrop
-j, --workers N Parallel workers for batches
--no-measure Skip the similarity score

Input can be PNG, JPEG, WebP, GIF, BMP, TIFF, TGA, ICO, HEIC/AVIF — anything Pillow reads. EXIF rotation, grayscale, palette and CMYK all get normalised.

Presets

auto picks one by measuring how much fine detail survives a median filter — grain does, clean edges do not — so drawings are never mistaken for photographs however colourful they are.

preset for result
icon logos, UI icons, flat art crisp edges, few shapes
illustration shaded artwork, stickers, game assets gradients preserved
photo photographs deliberate stylisation, bounded cost
poster any image a few big flat shapes, screen-print look

Photographs, honestly

A photograph is not really vector material: it has texture in every pixel and no region structure to find. --preset photo gives you a clean, deliberate stylisation in seconds rather than a faithful reproduction — expect something closer to a screen print than to the original. If you want fidelity from a photo, keep the raster.

What it will not do is hang: a 3840×2160 photograph converts in about 25 seconds because the working size is capped and the merge stage runs on a priority queue.

Using it as a library

from swag_converter import convert

result = convert("logo.png", "logo.svg", preset="auto", quality="max")
print(result.regions, result.nodes, result.similarity)

How it works

image
  └─ normalise: EXIF, colour mode, size cap, optional backdrop removal
       └─ classify content → preset
            └─ repair edge colour, derive the silhouette from alpha
                 └─ cluster colour in CIELAB, split into connected regions
                      └─ merge neighbours while one gradient still fits them
                           └─ marching squares → cubic Bézier fitting
                                └─ flat / linear / radial paint per region
                                     └─ SVG, then render back to score it

Curve fitting is Schneider's least-squares cubic algorithm, so a square traces to exactly four segments with sharp corners and a circle to about ten smooth ones. Adjacent paths overlap by a fraction of a pixel, which is what stops anti-aliasing leaving hairline seams between them.

Limitations

  • Photographs are stylised, not reproduced — see above.
  • Very large images are downscaled to --max-edge before tracing; raise it for more detail, at a real cost in time and file size.
  • Soft transitions become a boundary between two regions. Adjacent gradients are matched so the colour is continuous across it, but a truly soft edge (a blur, a glow) cannot be represented.
  • Output is larger than the source PNG for detailed images. That is inherent: vector data at this fidelity costs more than a compressed bitmap.

Development

pip install -e '.[dev]'
pytest                      # full suite
pytest -m 'not slow'        # skip the timing guards
python examples/make_samples.py

Releases are cut by pushing a tag; see RELEASING.md.

License

MIT — see LICENSE.

The SVGs you produce are yours; this tool claims nothing over them. Do check the licence of whatever you feed it — vectorising an image does not change who owns it.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

swag_converter-0.1.0.tar.gz (43.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

swag_converter-0.1.0-py3-none-any.whl (40.8 kB view details)

Uploaded Python 3

File details

Details for the file swag_converter-0.1.0.tar.gz.

File metadata

  • Download URL: swag_converter-0.1.0.tar.gz
  • Upload date:
  • Size: 43.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for swag_converter-0.1.0.tar.gz
Algorithm Hash digest
SHA256 bbb91df6d66b1078d8d9724b8c68fb230702f772bc1c54b9ddafeafe744918b9
MD5 f0729361f651b51e04e67554406a1821
BLAKE2b-256 fa61c60a13370801e46e0ca27e5a5639cade6a4d3c6b7a1aa908870bebd97721

See more details on using hashes here.

Provenance

The following attestation bundles were made for swag_converter-0.1.0.tar.gz:

Publisher: release.yml on CryptoNerf/swag-converter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file swag_converter-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: swag_converter-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 40.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for swag_converter-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9b286433752bc1548da9ffc3a8454b72b781f8503278fa9d38b5beb0697a56f2
MD5 e97427112464c3f18016c2fc5c6b288e
BLAKE2b-256 710da2f370e6209444fecab99345f85cec671e7c8e9abc2bec957b0dadb064d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for swag_converter-0.1.0-py3-none-any.whl:

Publisher: release.yml on CryptoNerf/swag-converter

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page