No description
  • Rust 80.1%
  • Go 16.6%
  • Just 2.1%
  • Dockerfile 1%
  • HTML 0.2%
Find a file
2026-03-13 10:03:41 +01:00
go-version task 0: project setup — cargo workspace, Cargo.toml with approved crates, Justfile, CLAUDE.md, .gitignore 2026-02-25 17:30:28 +01:00
src audit: remove dead code, fix docs, drop image crate 2026-02-26 14:44:31 +01:00
tests audit: remove dead code, fix docs, drop image crate 2026-02-26 14:44:31 +01:00
.gitignore docs: replace task 18 HTML proposal with minimalist PBF→SVG vector tile renderer design 2026-03-13 10:03:41 +01:00
.jjignore docs: replace task 18 HTML proposal with minimalist PBF→SVG vector tile renderer design 2026-03-13 10:03:41 +01:00
AGENTS.md audit: remove dead code, fix docs, drop image crate 2026-02-26 14:44:31 +01:00
Cargo.lock chore: bump version to v0.2.0 2026-02-26 14:55:54 +01:00
Cargo.toml chore: bump version to v0.2.0 2026-02-26 14:55:54 +01:00
Containerfile add cross-compilation Containerfile and Justfile recipes 2026-02-25 22:36:15 +01:00
Justfile chore: rename project gpx2img → gpx2svg 2026-02-26 14:02:38 +01:00
README.md audit: remove dead code, fix docs, drop image crate 2026-02-26 14:44:31 +01:00
TODO.md docs: replace task 18 HTML proposal with minimalist PBF→SVG vector tile renderer design 2026-03-13 10:03:41 +01:00

gpx2svg

Convert GPX, KML, or KMZ track files into SVG images with optional OpenStreetMap tile backgrounds.

gpx2svg --in track.gpx --out track.svg
gpx2svg --in track.gpx --out track.svg --map --zoom 14

Install

cargo install --path .

Or build locally:

cargo build --release
# binary at target/release/gpx2svg

Usage

gpx2svg --in <file> [options]
Flag Default Description
--in <path> required Input file: GPX, KML, or KMZ
--out <path> out.svg Output SVG path; - writes to stdout
--width <px> 1000 Canvas width (ignored in map mode)
--height <px> 600 Canvas height (ignored in map mode)
--pad <px> 0 Pixel padding (no-map mode)
--pad-pct <050> 10.0 Padding percentage (map mode)
--bg <color> white Background fill
--stroke <color> #2b6cb0 Track stroke colour (single-input mode; use --colors for multiple tracks)
--sw <float> 3.0 Stroke width in px
--markers / --no-markers on Start/end circle markers
--map / --no-map off Embed OSM tile background
--tile-source <name|url> osm Tile provider (see below)
--zoom <118> 13 Tile zoom level
--map-opacity <01> 0.8 Map tile opacity
--attribution / --no-attribution on Attribution box
--attribution-text <str> Override attribution text
--colors <c1,c2,...> auto Per-track stroke colours (CSV); auto-assigns Okabe-Ito palette
--labels <l1,l2,...> filename stems Per-track legend labels (CSV)
--legend / --no-legend auto Colour legend (auto-on when >1 track)
--tile-cache-ttl <days> 30 Tile cache TTL (0 = never expire)
--verbose / -v off Log per-tile cache hit/miss to stderr

All diagnostic output goes to stderr; stdout carries SVG bytes only.

Output

Output is always SVG. SVG is lossless, scalable, and embeds map tiles as base64 data URIs — no external files needed. For raster or other formats, pipe through a standard tool:

# PNG via rsvg-convert (high quality, fast)
gpx2svg --in track.gpx | rsvg-convert -o out.png

# PNG at specific width
gpx2svg --in track.gpx --map | rsvg-convert -w 1920 -o out.png

# PNG or JPEG via ImageMagick
gpx2svg --in track.gpx | magick svg:- out.png
gpx2svg --in track.gpx | magick svg:- -quality 85 out.jpg

# AVIF
gpx2svg --in track.gpx | rsvg-convert | magick - out.avif

# PDF (vector, lossless)
gpx2svg --in track.gpx | rsvg-convert -f pdf -o out.pdf

Examples

# SVG, no map
gpx2svg --in ride.gpx --out ride.svg

# With OSM tiles at zoom 15, piped to PNG
gpx2svg --in ride.gpx --map --zoom 15 | rsvg-convert -o ride.png

# Write SVG to stdout
gpx2svg --in ride.gpx --out -

# Custom colours, larger canvas
gpx2svg --in ride.gpx --stroke '#e53e3e' --sw 4 --width 1920 --height 1080 --out ride.svg

# Subtle map background
gpx2svg --in ride.gpx --map --map-opacity 0.4 --out ride.svg

# No attribution
gpx2svg --in ride.gpx --no-attribution --out ride.svg

# KML input
gpx2svg --in route.kml --out route.svg --map

# OpenTopoMap tiles
gpx2svg --in track.gpx --map --tile-source otm --out topo.svg

# Multiple GPX files on one map (auto-coloured)
gpx2svg --in morning.gpx evening.gpx --out combined.svg --map

# Override per-track colours and labels
gpx2svg --in a.gpx b.gpx --colors '#e69f00,#56b4e9' --labels 'Monday,Tuesday' --out combined.svg

# Cache management
gpx2svg --cache-info
gpx2svg --clear-cache --tile-source osm

Tile sources

Name Provider
osm (default) OpenStreetMap
otm OpenTopoMap
carto-light Carto Positron
carto-dark Carto Dark Matter
stamen-terrain Stadia Stamen Terrain
stamen-toner Stadia Stamen Toner
esri-satellite ESRI World Imagery

Or supply a custom URL template: --tile-source 'https://example.com/{z}/{x}/{y}.png'

When --map is set, tiles are fetched and cached at ~/.cache/gpx2svg/tiles/ (SHA-256-keyed, persistent across runs). The zoom level is automatically adjusted ±5 levels from the requested value to optimise aspect ratio and keep tile count ≤128.

Please follow the OSM tile usage policy.
Map data © OpenStreetMap contributors.

Repository layout

.               Rust implementation (this crate)
go-version/     Original Go implementation (reference)

License

MIT