Lightweight library for arbitrary geometric SVG transformations
Project description
🦎 SVGecko
A lightweight Python library for arbitrary geometric SVG transformations. SVGecko enables you to apply any mathematical transformation function to SVG files, going beyond simple affine transformations to support complex geometric operations.
✨ Features
- Arbitrary Transformations: Apply any mathematical function
(x, y) → (x', y')to SVG coordinates - Comprehensive SVG Support: Handles path commands, coordinate attributes, and CSS transforms
- Multiple Command Types: Supports absolute, relative, and arc path commands
- Style Transform Support: Transforms CSS
translate()functions in style attributes - Easy Integration: Simple API with PIL Image conversion
- Type Safety: Full type annotations for better development experience
🚀 Installation
pip install svgecko
📖 Quick Start
Basic Transformation
import matplotlib.pyplot as plt
from svgecko import SVG
# Load an SVG file
svg = SVG.from_file('example.svg')
# Apply a transformation (shift by 1 unit in both directions)
transformation = lambda point: (point[0] + 1, point[1] + 1)
transformed_svg = svg.transform(transformation)
# Convert to PIL Image and display
image = transformed_svg.to_pil_image()
plt.imshow(image)
plt.show()
Advanced Transformations
import math
from svgecko import SVG
svg = SVG.from_file('logo.svg')
# Rotate around origin by 45 degrees
def rotate_45(point):
x, y = point
angle = math.radians(45)
new_x = x * math.cos(angle) - y * math.sin(angle)
new_y = x * math.sin(angle) + y * math.cos(angle)
return (new_x, new_y)
# Scale by factor of 2
def scale_2x(point):
return (point[0] * 2, point[1] * 2)
# Apply transformations
rotated_svg = svg.transform(rotate_45)
scaled_svg = svg.transform(scale_2x)
# Save results
rotated_svg.to_file('rotated_logo.svg')
scaled_svg.to_file('scaled_logo.svg')
Working with Different SVG Elements
from svgecko import SVG
# SVG with various elements
svg_content = """
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<!-- Path with absolute commands -->
<path d="M10 10 L20 20 L30 10 Z" fill="blue"/>
<!-- Path with relative commands -->
<path d="M50 50 l10 10 l10 -10 z" fill="red"/>
<!-- Path with arc commands -->
<path d="M70 70 A10 10 0 0 1 90 70" fill="green"/>
<!-- Element with CSS transform -->
<rect x="10" y="80" width="20" height="10"
style="transform: translate(5, 5)" fill="orange"/>
</svg>
"""
svg = SVG.from_string(svg_content)
# Apply transformation to all elements
def complex_transform(point):
x, y = point
# Apply a wave-like transformation
new_x = x + math.sin(y * 0.1) * 5
new_y = y + math.cos(x * 0.1) * 5
return (new_x, new_y)
transformed_svg = svg.transform(complex_transform)
📚 API Reference
SVG Class
The main class for working with SVG files.
Methods
-
from_file(file_path: str, encoding: str = 'utf-8') -> SVG- Load SVG from a file
-
from_string(svg_string: str, encoding: str = 'utf-8') -> SVG- Load SVG from a string
-
transform(transformation: Callable[[Tuple[float, float]], Tuple[float, float]], inplace: bool = False) -> SVG- Apply a transformation function to all coordinates
transformation: Function that takes (x, y) and returns (x', y')inplace: If True, modify the current SVG; if False, return a new SVG
-
to_file(file_path: str, encoding: str = 'utf-8') -> None- Save SVG to a file
-
to_string(encoding: str = 'utf-8') -> str- Convert SVG to XML string
-
to_pil_image(**kwargs) -> Image.Image- Convert SVG to PIL Image
- Supports all cairosvg.svg2png parameters (scale, width, height, etc.)
Properties
xml: Access to the underlying XML element treeshape: Tuple of (width, height) as floats
Path and PathCommand Classes
For working with SVG path data directly.
from svgecko import Path, PathCommand
# Parse a path string
path = Path.from_command_string('M10 10 L20 20 Z')
# Transform the path
transformed_path = path.transform(lambda p: (p[0] + 5, p[1] + 5))
# Get the command string
print(transformed_path.command_string) # "M 15.0 15.0 L 25.0 25.0 Z"
🎯 Supported SVG Features
✅ Fully Supported
- Absolute path commands: M, L, C, S, Q, T, H, V, Z
- Relative path commands: m, l, c, s, q, t, h, v (converted to absolute)
- Arc commands: A, a (approximated as line segments)
- Coordinate attributes: x, y, x1, y1, x2, y2, cx, cy, fx, fy
- Points attributes: polyline/polygon points
- CSS transforms: translate(), translateX(), translateY() in style and transform attributes
- File I/O: Load from/save to files and strings
- Image conversion: Convert to PIL Image objects
🔄 Automatic Conversions
- Relative commands (
l,m, etc.) → Absolute commands (L,M, etc.) - Horizontal/Vertical commands (
H,V) → Line commands (L) - Arc commands (
A,a) → Line segments (approximation)
🧪 Examples
Mathematical Transformations
# Spiral transformation
def spiral(point, turns=2):
x, y = point
r = math.sqrt(x*x + y*y)
angle = math.atan2(y, x) + r * turns * 2 * math.pi / 100
return (r * math.cos(angle), r * math.sin(angle))
# Wave distortion
def wave_distort(point):
x, y = point
return (x + math.sin(y * 0.1) * 10, y + math.cos(x * 0.1) * 10)
# Perspective projection
def perspective(point, focal_length=100):
x, y = point
z = 50 # Assume z-coordinate
scale = focal_length / (focal_length + z)
return (x * scale, y * scale)
Visualization Scripts
Install matplotlib and run:
python examples/visualize_transformations.py
python examples/visualize_points.py
The scripts save PNGs into examples/output/ and also display them.
Batch Processing
import os
from pathlib import Path
def process_svg_directory(input_dir, output_dir, transformation):
"""Apply transformation to all SVG files in a directory."""
input_path = Path(input_dir)
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
for svg_file in input_path.glob('*.svg'):
svg = SVG.from_file(str(svg_file))
transformed_svg = svg.transform(transformation)
output_file = output_path / f'transformed_{svg_file.name}'
transformed_svg.to_file(str(output_file))
print(f'Processed: {svg_file.name}')
# Usage
process_svg_directory('input/', 'output/', lambda p: (p[0] * 1.5, p[1] * 1.5))
🛠️ Development
Setup Development Environment
git clone https://github.com/josef-ondrej/svgecko.git
cd svgecko
pip install -e ".[dev]"
Running Tests
pytest
Code Quality
# Format code
black svgecko tests
# Sort imports
isort svgecko tests
# Type checking
mypy svgecko
# Linting
flake8 svgecko tests
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
📝 Changelog
v0.4.0
- ✅ Added support for relative path commands
- ✅ Added support for arc path commands (approximated as line segments)
- ✅ Added support for CSS translate() functions in style attributes
- ✅ Improved type annotations throughout the codebase
- ✅ Added comprehensive Google-style documentation
- ✅ Enhanced test coverage
- ✅ Modernized project structure with pyproject.toml
Project details
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 svgecko-0.4.0.tar.gz.
File metadata
- Download URL: svgecko-0.4.0.tar.gz
- Upload date:
- Size: 22.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
24ba69856511f6cb7fd1e71211da0ecab11793796fbea9ee7e0f86c64bb979c6
|
|
| MD5 |
2b897889f3ec75d260422cad45300dee
|
|
| BLAKE2b-256 |
524bacb9055cd687911f883ffc8556ad5e3aa6bb872f9d5ef84e28c51e5a4c3a
|
File details
Details for the file svgecko-0.4.0-py3-none-any.whl.
File metadata
- Download URL: svgecko-0.4.0-py3-none-any.whl
- Upload date:
- Size: 17.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.25
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42dd02d78dc077b7247d5b2fbb846eda3eee27a3ac5452960d332ae9d9483e6d
|
|
| MD5 |
cc49626ebb3265184c3563104c8e55d3
|
|
| BLAKE2b-256 |
4b889aa2cfae02cf5ee5d5d9832a1e51cf33b9c3667055ab1dfbc42b682b60ad
|