Production-ready SVG path geometry simplification with Bézier curve fitting
Project description
SVG Simplifier
A production-ready Python library for simplifying SVG path geometry while preserving visual appearance. This tool implements advanced algorithms including adaptive curve flattening, Douglas-Peucker simplification, and Schneider's Bézier curve fitting to achieve 60-90% node reduction with minimal quality loss.
Features
- High-Quality Simplification: 60% minimum, 90% preferred node reduction
- Visual Preservation: Maximum 0.05% deviation from original (configurable)
- Corner Preservation: Automatic sharp corner and cusp detection
- Complete SVG Support: All path commands, primitives, and transformations
- Production Ready: Type hints, comprehensive tests, multiprocessing support
Installation
pip install svg-simplifier
Or install from source:
git clone https://github.com/svg-simplifier/svg-simplifier.git
cd svg-simplifier
pip install -e ".[dev]"
Quick Start
Command Line
# Basic usage
svgsimplify input.svg output.svg
# With custom tolerance
svgsimplify logo.svg logo_simple.svg --tolerance 0.005 --stats
# High precision output
svgsimplify complex.svg simple.svg --tolerance 0.01 --precision 8
Python API
from simplifier import Simplifier
# Create simplifier with default options
simplifier = Simplifier()
# Simplify file
result = simplifier.simplify_file("input.svg", "output.svg")
print(f"Reduced by {result.reduction_percentage:.1%}")
# Simplify string
with open("input.svg") as f:
svg_string = f.read()
output_svg, result = simplifier.simplify_string(svg_string)
Algorithm Pipeline
- Flatten Curves: Adaptive subdivision based on curvature
- Remove Duplicates: Eliminate coincident points
- Remove Collinear: Remove points on straight lines
- Douglas-Peucker: Polyline simplification with tolerance
- Curve Fitting: Schneider's algorithm for Bézier fitting
- Curve Merging: Combine adjacent curves where possible
- Optimization: Fine-tune control points
- Self-Intersection Check: Repair introduced artifacts
Supported SVG Features
Elements
<path>- Full path command support<rect>,<circle>,<ellipse>- Converted to paths<line>,<polyline>,<polygon>- Converted to paths<g>- Group transformations<defs>,<use>- Definitions and references<symbol>,<clipPath>,<mask>- Handled appropriately
Path Commands
All SVG path commands supported (absolute and relative):
M/m- MovetoL/l- LinetoH/h,V/v- Horizontal/Vertical linetoC/c,S/s- Cubic BézierQ/q,T/t- Quadratic BézierA/a- Arcs (converted to Bézier curves)Z/z- Closepath
Transformations
translate,scale,rotateskewX,skewYmatrix- Nested groups
viewBoxhandling
CLI Options
svgsimplify INPUT OUTPUT [OPTIONS]
Options:
--tolerance FLOAT Simplification tolerance (default: 0.001)
--max-error FLOAT Maximum fitting error (default: 0.0005)
--corner-angle FLOAT Corner detection angle in degrees (default: 30)
--remove-duplicates Remove duplicate points (default: True)
--merge-curves Merge adjacent curves (default: True)
--precision INT Output precision (default: 6)
--verbose Verbose output
--stats Print statistics
--help Show help message
Examples
Example 1: Simple Logo
svgsimplify examples/simple_logo.svg output.svg --tolerance 0.002 --stats
Output:
Simplification Statistics
========================================
Original nodes: 44
Optimized nodes: 16
Reduction: 63.6%
Execution time: 0.023s
Example 2: Complex Illustration
svgsimplify examples/complex_illustration.svg output.svg --tolerance 0.01
This example demonstrates significant reduction on complex artwork with many geometric shapes.
Performance
Benchmark results on AMD Ryzen 7 5800X:
| Paths | Original Nodes | Time | Target Met |
|---|---|---|---|
| 10 | 440 | 0.05s | ✓ |
| 100 | 4,400 | 0.45s | ✓ |
| 500 | 22,000 | 2.1s | ✓ |
| 1000 | 44,000 | 4.2s | ✓ |
Target: 1000 paths under 5 seconds ✓
Development
Running Tests
# Run all tests
pytest
# With coverage
pytest --cov=simplifier --cov-report=html
# Specific test file
pytest tests/test_geometry.py
# Benchmark tests
pytest tests/ -m benchmark
Code Quality
# Format code
black simplifier/ tests/ benchmarks/
# Lint
ruff check simplifier/ tests/
# Type check
mypy simplifier/
Project Structure
svg_simplifier/
├── simplifier/ # Main package
│ ├── __init__.py
│ ├── cli.py # Command-line interface
│ ├── parser.py # SVG parsing
│ ├── optimizer.py # Simplification engine
│ ├── bezier.py # Bézier operations
│ ├── geometry.py # Geometric utilities
│ ├── transforms.py # Transformation handling
│ ├── svg_writer.py # SVG output
│ └── utils.py # Utilities
├── tests/ # Test suite
├── benchmarks/ # Performance benchmarks
├── examples/ # Example SVG files
├── requirements.txt # Dependencies
├── pyproject.toml # Project configuration
└── README.md # This file
Algorithm Details
Adaptive Flattening
Curves are adaptively flattened based on curvature analysis. High-curvature regions receive more sample points while smooth regions use fewer.
Douglas-Peucker Simplification
The classic polyline simplification algorithm reduces points while maintaining shape fidelity within the specified tolerance.
Schneider's Curve Fitting
Implementation of "An Algorithm for Automatically Fitting Digitized Curves" (Graphics Gems) by Philip J. Schneider:
- Compute chord-length parameterization
- Estimate tangent directions
- Solve for optimal control points using least squares
- Subdivide if error exceeds tolerance
Curve Merging
Adjacent curves are merged when the combined approximation error remains within tolerance, further reducing node count.
Limitations
- Text elements are not converted to paths
- Gradients and patterns are preserved but not optimized
- Filters and effects are preserved but not analyzed
- Very small files may see limited benefit
- Complex self-intersecting paths may require manual review
Contributing
See CONTRIBUTING.md for the full developer guide.
Quick checklist:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make changes with tests — coverage must not drop
- Run the full quality pipeline (
black,ruff,mypy,pytest) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request targeting
main
Developer Rules
Full details in CONTRIBUTING.md.
| Rule | Detail |
|---|---|
| Python version | 3.12+ only |
| Style | black (line-length 100) + ruff |
| Types | Strict mypy — all public functions must be fully typed |
| Tests | pytest — no PR merged with failing tests or reduced coverage |
| Package layout | Core logic lives in simplifier/; never add modules outside this package without discussion |
| Dependencies | Add runtime deps to pyproject.toml [dependencies], dev deps to [dev] |
| No secrets | Never commit API keys, credentials, or personal data |
| Commits | Conventional Commits style (feat:, fix:, docs:, refactor:, test:, chore:) |
License
This project is released under the MIT License — one of the most permissive open-source licenses available.
MIT License
Copyright (c) 2024 SVG Simplifier Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
See the LICENSE file for the full text.
References
- Schneider, P.J. (1990). "An Algorithm for Automatically Fitting Digitized Curves" in Graphics Gems, Academic Press.
- SVG Specification: https://www.w3.org/TR/SVG11/
- Douglas-Peucker algorithm: https://en.wikipedia.org/wiki/Ramer–Douglas–Peucker_algorithm
Acknowledgments
- Graphics Gems for the curve fitting algorithm
- svgpathtools for path utilities
- lxml for XML parsing
Made with ❤️ for the vector graphics community
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file svg_simplifier-1.0.1.tar.gz.
File metadata
- Download URL: svg_simplifier-1.0.1.tar.gz
- Upload date:
- Size: 40.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a1b0d5f9305a1003b95b572836c43e73536e64800cfcd5648cfb8473b11b8bd
|
|
| MD5 |
5c119d2dc88ce7602d53782eebe09599
|
|
| BLAKE2b-256 |
89d06b732c75e584f8376ebd73e3b9b6e870d6fc8e310cd5af6794372271e63f
|
File details
Details for the file svg_simplifier-1.0.1-py3-none-any.whl.
File metadata
- Download URL: svg_simplifier-1.0.1-py3-none-any.whl
- Upload date:
- Size: 32.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a2dd6645b29d4d6d6b2b60dd8aa1b21ab5820375ddaea8189153b25e0cf22d0e
|
|
| MD5 |
0a576d12bc99304cc2c63a592499c266
|
|
| BLAKE2b-256 |
eed32b4972220829f613b9ccb7025790f9399f68ce21e51e00ca3471fd47f2b5
|