<h1 align="center">
<img height="250" src="images/framesvg.svg" alt="FrameSVG" />
</h1>
<p align="center">
<strong>Convert animated GIFs to animated SVGs.</strong>
</p>
<p align="center">
<a href="https://github.com/romelium/framesvg/actions/workflows/tests.yml"><img alt="Build Status" src="https://img.shields.io/github/actions/workflow/status/romelium/framesvg/main.yml?branch=main"></a>
<a href="LICENSE"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-blue.svg"></a>
<a href="https://pypi.org/project/framesvg/"><img alt="PyPI" src="https://img.shields.io/pypi/v/framesvg"></a>
<a href="https://pypi.org/project/framesvg/"><img alt="Python Versions" src="https://img.shields.io/pypi/pyversions/framesvg"></a>
</p>
<!-- Be on the left and right of next paragraph -->
<img align="left" hspace=10 src="images/kyubey.svg"/>
<img align="right" hspace=10 src="images/kyubey.svg"/>
`framesvg` is a command-line tool and Python library that converts animated GIFs into animated SVGs. It leverages the power of [VTracer](https://www.visioncortex.org/vtracer/) for raster-to-vector conversion, producing smooth, scalable, and *true vector* animations. This is a significant improvement over embedding raster images (like GIFs) directly within SVGs, as `framesvg` generates genuine vector output that plays automatically and scales beautifully. Ideal for readmes, documentation, and web graphics.
<br clear="both"/>
## Why Use framesvg?
* **True Vector Output:** Unlike simply embedding a GIF within an SVG, `framesvg` creates a true vector animation. This means:
* **Scalability:** The SVG can be resized to any dimensions without losing quality.
* **Smaller File Size (Potentially):** For many GIFs, the resulting SVG will be smaller, especially for graphics with large areas of solid color or simple shapes. Complex, photographic GIFs may be larger, however.
* **Automatic Playback:** The generated SVGs are designed to play automatically in any environment that supports SVG animations (web browsers, github, many image viewers, etc.).
* **Easy to Use:** Simple command-line interface and a clean Python API.
* **Customizable:** Control the frame rate and fine-tune the VTracer conversion process for optimal results.
## Examples
The following examples demonstrate the conversion of GIFs (left) to SVGs (right) using `framesvg`.
<p align="center">
<img height=200 src="images/Code Coding GIF by EscuelaDevRock Git.gif"/>
<img height=200 src="images/Code Coding GIF by EscuelaDevRock Git.svg"/>
<img height=200 src="images/Code Coding GIF by EscuelaDevRock GitHub.gif"/>
<img height=200 src="images/Code Coding GIF by EscuelaDevRock GitHub.svg"/>
<img height=200 src="images/Code Coding GIF by EscuelaDevRock VSCode.gif"/>
<img height=200 src="images/Code Coding GIF by EscuelaDevRock VSCode.svg"/>
<img height=200 src="images/Code Coding GIF by EscuelaDevRock Sublime.gif"/>
<img height=200 src="images/Code Coding GIF by EscuelaDevRock Sublime.svg"/>
</p>
### More Examples
<p align="center">
<img height=200 src="images/Good_Morning_GIF_by_Hello_All.gif"/>
<img height=200 src="images/Good_Morning_GIF_by_Hello_All.svg"/>
<img height=200 src="images/icon_loading_GIF.gif"/>
<img height=200 src="images/icon_loading_GIF.svg"/>
<img height=200 src="images/voila hands GIF by brontron.gif"/>
<img height=200 src="images/voila hands GIF by brontron.svg"/>
</p>
### Complex Examples (Transparent Backgrounds)
These examples demonstrate `binary` color mode. All bright colors in `binary` color mode turns transparent. (If they appear dark, it is due to the transparency. They will look correct on light backgrounds)
<p align="center">
<img height=200 src="images/black and white loop GIF by Sculpture.gif"/>
<img height=200 src="images/black and white loop GIF by Sculpture.svg"/>
<img height=200 src="images/Black And White Loop GIF by Pi-Slices.gif"/>
<img height=200 src="images/Black And White Loop GIF by Pi-Slices.svg"/>
</p>
## Installation
### Using pip (Recommended)
The easiest way to install `framesvg` is via pip:
```bash
pip install framesvg
```
This installs both the command-line tool and the Python library.
### From Source
1. **Clone the repository:**
```bash
git clone https://github.com/romelium/framesvg
cd framesvg
```
2. **Install:**
```bash
pip install .
```
## Usage
### Command-Line Interface
```bash
framesvg input.gif [output.svg] [options]
```
* **`input.gif`:** (Required) Path to the input GIF file.
* **`output.svg`:** (Optional) Path to save the output SVG file. If omitted, the output file will have the same name as the input, but with a `.svg` extension.
**Options:**
* **`-f`, `--fps <value>`:** Sets the frames per second (FPS) for the animation. (Default: 10). Lower values can reduce file size.
* **`-l`, `--log-level <level>`:** Sets the logging level. (Default: INFO). Choices: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`, `NONE`. `DEBUG` provides detailed output for troubleshooting.
* **VTracer Options:** These options control the raster-to-vector conversion process performed by VTracer. Refer to the [VTracer Documentation](https://www.visioncortex.org/vtracer-docs) and [Online Demo](https://www.visioncortex.org/vtracer/) for detailed explanations.
* `-c`, `--colormode <mode>`: Color mode. (Default: `color`). Choices: `color`, `binary`.
* `-i`, `--hierarchical <mode>`: Hierarchy mode. (Default: `stacked`). Choices: `stacked`, `cutout`.
* `-m`, `--mode <mode>`: Conversion mode. (Default: `polygon`). Choices: `spline`, `polygon`, `none`. `spline` creates smoother curves, but `polygon` often results in smaller files.
* `-s`, `--filter-speckle <value>`: Reduces noise and small details. (Default: 4). *This is a key parameter for controlling file size.* Higher values = smaller files, but less detail.
* `-p`, `--color-precision <value>`: Number of significant bits for color quantization. (Default: 8). Lower values = smaller files, but fewer colors.
* `-d`, `--layer-difference <value>`: Controls the number of layers. (Default: 16). Higher values can reduce file size.
* `--corner-threshold <value>`: Angle threshold for corner detection. (Default: 60).
* `--length-threshold <value>`: Minimum path length. (Default: 4.0).
* `--max-iterations <value>`: Maximum number of optimization iterations. (Default: 10).
* `--splice-threshold <value>`: Angle threshold for splitting splines. (Default: 45).
* `--path-precision <value>`: Number of decimal places for path coordinates. (Default: 8).
**Command-Line Examples:**
```bash
# Basic conversion with default settings
framesvg input.gif
# Specify output file and set FPS to 24
framesvg input.gif output.svg -f 24
# Optimize for smaller file size (less detail)
framesvg input.gif -s 8 -p 3 -d 128
# Enable debug logging
framesvg input.gif -l DEBUG
```
### Python API
```python
from framesvg import gif_to_animated_svg_write, gif_to_animated_svg
# Example 1: Convert and save to a file
gif_to_animated_svg_write("input.gif", "output.svg", fps=30)
# Example 2: Get the SVG as a string
animated_svg_string = gif_to_animated_svg("input.gif", fps=12)
print(f"Generated SVG length: {len(animated_svg_string)}")
# ... do something with the string (e.g., save to file, display in a web app)
# Example 3: Customize VTracer options
custom_options = {
"mode": "spline",
"filter_speckle": 2,
}
gif_to_animated_svg_write("input.gif", "output_custom.svg", vtracer_options=custom_options)
```
### API Reference
* **`gif_to_animated_svg_write(gif_path, output_svg_path, vtracer_options=None, fps=10.0, image_loader=None, vtracer_instance=None)`:**
* `gif_path` (str): Path to the input GIF file.
* `output_svg_path` (str): Path to save the output SVG file.
* `vtracer_options` (dict, optional): A dictionary of VTracer options. If `None`, uses `DEFAULT_VTRACER_OPTIONS`.
* `fps` (float, optional): Frames per second. Defaults to 10.0.
* `image_loader` (ImageLoader, optional): Custom image loader.
* `vtracer_instance` (VTracer, optional): Custom VTracer instance.
* Raises: `FileNotFoundError`, `NotAnimatedGifError`, `NoValidFramesError`, `DimensionError`, `ExtractionError`, `FramesvgError`, `IsADirectoryError`.
* **`gif_to_animated_svg(gif_path, vtracer_options=None, fps=10.0, image_loader=None, vtracer_instance=None)`:**
* `gif_path` (str): Path to the input GIF file.
* `vtracer_options` (dict, optional): A dictionary of VTracer options. If `None`, uses `DEFAULT_VTRACER_OPTIONS`.
* `fps` (float, optional): Frames per second. Defaults to 10.0.
* `image_loader` (ImageLoader, optional): Custom image loader.
* `vtracer_instance` (VTracer, optional): Custom VTracer instance.
* Returns: The animated SVG as a string.
* Raises: `FileNotFoundError`, `NotAnimatedGifError`, `NoValidFramesError`, `DimensionError`, `ExtractionError`, `FramesvgError`.
## Tips for Optimizing Large File Size (> 1MB)
* **[Online Demo](https://www.visioncortex.org/vtracer/):** Use this to visualize tweaking values. Experiment to find the best balance between size and quality.
* **`filter-speckle`:** *This is the most impactful setting for reducing file size, especially on complex images.* Increasing it removes small details.
* **`--mode polygon`:** Use the default polygon mode unless smooth curves (spline mode) are absolutely necessary. Polygon mode can significantly reduce file size by a factor of 5 or more.
* **`layer-difference`:** Increase this to reduce the number of layers.
* **`color-precision`:** Reduce the number of colors by lowering this value.
## Dev
### Install Hatch (Recommended)
follow [this](https://hatch.pypa.io/latest/install)
or just
```bash
pip install hatch
```
### Format and lint
```bash
hatch fmt
```
### Testing
```bash
hatch test
```
### Other Hatch Commands
```bash
hatch -h
```
## Contributing
Contributions are welcome! Please submit pull requests or open issues on the [GitHub repository](https://github.com/romelium/framesvg).
Raw data
{
"_id": null,
"home_page": null,
"name": "framesvg",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "Romelium <maintainer@romelium.cc>",
"keywords": "animation, gif, image-processing, svg, vector, vtracer",
"author": null,
"author_email": "Romelium <author@romelium.cc>",
"download_url": "https://files.pythonhosted.org/packages/34/52/e0b6dd5891886a00b5988c514a654a5826ac59251115f66c3d5b9bc0678d/framesvg-0.1.1.tar.gz",
"platform": null,
"description": "<h1 align=\"center\">\n <img height=\"250\" src=\"images/framesvg.svg\" alt=\"FrameSVG\" />\n</h1>\n\n<p align=\"center\">\n <strong>Convert animated GIFs to animated SVGs.</strong>\n</p>\n\n<p align=\"center\">\n <a href=\"https://github.com/romelium/framesvg/actions/workflows/tests.yml\"><img alt=\"Build Status\" src=\"https://img.shields.io/github/actions/workflow/status/romelium/framesvg/main.yml?branch=main\"></a>\n <a href=\"LICENSE\"><img alt=\"MIT License\" src=\"https://img.shields.io/badge/license-MIT-blue.svg\"></a>\n <a href=\"https://pypi.org/project/framesvg/\"><img alt=\"PyPI\" src=\"https://img.shields.io/pypi/v/framesvg\"></a>\n <a href=\"https://pypi.org/project/framesvg/\"><img alt=\"Python Versions\" src=\"https://img.shields.io/pypi/pyversions/framesvg\"></a>\n</p>\n\n<!-- Be on the left and right of next paragraph -->\n<img align=\"left\" hspace=10 src=\"images/kyubey.svg\"/>\n<img align=\"right\" hspace=10 src=\"images/kyubey.svg\"/>\n\n`framesvg` is a command-line tool and Python library that converts animated GIFs into animated SVGs. It leverages the power of [VTracer](https://www.visioncortex.org/vtracer/) for raster-to-vector conversion, producing smooth, scalable, and *true vector* animations. This is a significant improvement over embedding raster images (like GIFs) directly within SVGs, as `framesvg` generates genuine vector output that plays automatically and scales beautifully. Ideal for readmes, documentation, and web graphics.\n\n<br clear=\"both\"/>\n\n## Why Use framesvg?\n\n* **True Vector Output:** Unlike simply embedding a GIF within an SVG, `framesvg` creates a true vector animation. This means:\n * **Scalability:** The SVG can be resized to any dimensions without losing quality.\n * **Smaller File Size (Potentially):** For many GIFs, the resulting SVG will be smaller, especially for graphics with large areas of solid color or simple shapes. Complex, photographic GIFs may be larger, however.\n* **Automatic Playback:** The generated SVGs are designed to play automatically in any environment that supports SVG animations (web browsers, github, many image viewers, etc.).\n* **Easy to Use:** Simple command-line interface and a clean Python API.\n* **Customizable:** Control the frame rate and fine-tune the VTracer conversion process for optimal results.\n\n## Examples\n\nThe following examples demonstrate the conversion of GIFs (left) to SVGs (right) using `framesvg`.\n\n<p align=\"center\">\n<img height=200 src=\"images/Code Coding GIF by EscuelaDevRock Git.gif\"/>\n<img height=200 src=\"images/Code Coding GIF by EscuelaDevRock Git.svg\"/>\n<img height=200 src=\"images/Code Coding GIF by EscuelaDevRock GitHub.gif\"/>\n<img height=200 src=\"images/Code Coding GIF by EscuelaDevRock GitHub.svg\"/>\n<img height=200 src=\"images/Code Coding GIF by EscuelaDevRock VSCode.gif\"/>\n<img height=200 src=\"images/Code Coding GIF by EscuelaDevRock VSCode.svg\"/>\n<img height=200 src=\"images/Code Coding GIF by EscuelaDevRock Sublime.gif\"/>\n<img height=200 src=\"images/Code Coding GIF by EscuelaDevRock Sublime.svg\"/>\n</p>\n\n### More Examples\n\n<p align=\"center\">\n<img height=200 src=\"images/Good_Morning_GIF_by_Hello_All.gif\"/>\n<img height=200 src=\"images/Good_Morning_GIF_by_Hello_All.svg\"/>\n<img height=200 src=\"images/icon_loading_GIF.gif\"/>\n<img height=200 src=\"images/icon_loading_GIF.svg\"/>\n<img height=200 src=\"images/voila hands GIF by brontron.gif\"/>\n<img height=200 src=\"images/voila hands GIF by brontron.svg\"/>\n</p>\n\n### Complex Examples (Transparent Backgrounds)\n\nThese examples demonstrate `binary` color mode. All bright colors in `binary` color mode turns transparent. (If they appear dark, it is due to the transparency. They will look correct on light backgrounds)\n\n<p align=\"center\">\n<img height=200 src=\"images/black and white loop GIF by Sculpture.gif\"/>\n<img height=200 src=\"images/black and white loop GIF by Sculpture.svg\"/>\n<img height=200 src=\"images/Black And White Loop GIF by Pi-Slices.gif\"/>\n<img height=200 src=\"images/Black And White Loop GIF by Pi-Slices.svg\"/>\n</p>\n\n## Installation\n\n### Using pip (Recommended)\n\nThe easiest way to install `framesvg` is via pip:\n\n```bash\npip install framesvg\n```\n\nThis installs both the command-line tool and the Python library.\n\n### From Source\n\n1. **Clone the repository:**\n\n ```bash\n git clone https://github.com/romelium/framesvg\n cd framesvg\n ```\n\n2. **Install:**\n\n ```bash\n pip install .\n ```\n\n## Usage\n\n### Command-Line Interface\n\n```bash\nframesvg input.gif [output.svg] [options]\n```\n\n* **`input.gif`:** (Required) Path to the input GIF file.\n* **`output.svg`:** (Optional) Path to save the output SVG file. If omitted, the output file will have the same name as the input, but with a `.svg` extension.\n\n**Options:**\n\n* **`-f`, `--fps <value>`:** Sets the frames per second (FPS) for the animation. (Default: 10). Lower values can reduce file size.\n* **`-l`, `--log-level <level>`:** Sets the logging level. (Default: INFO). Choices: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`, `NONE`. `DEBUG` provides detailed output for troubleshooting.\n\n* **VTracer Options:** These options control the raster-to-vector conversion process performed by VTracer. Refer to the [VTracer Documentation](https://www.visioncortex.org/vtracer-docs) and [Online Demo](https://www.visioncortex.org/vtracer/) for detailed explanations.\n\n * `-c`, `--colormode <mode>`: Color mode. (Default: `color`). Choices: `color`, `binary`.\n * `-i`, `--hierarchical <mode>`: Hierarchy mode. (Default: `stacked`). Choices: `stacked`, `cutout`.\n * `-m`, `--mode <mode>`: Conversion mode. (Default: `polygon`). Choices: `spline`, `polygon`, `none`. `spline` creates smoother curves, but `polygon` often results in smaller files.\n * `-s`, `--filter-speckle <value>`: Reduces noise and small details. (Default: 4). *This is a key parameter for controlling file size.* Higher values = smaller files, but less detail.\n * `-p`, `--color-precision <value>`: Number of significant bits for color quantization. (Default: 8). Lower values = smaller files, but fewer colors.\n * `-d`, `--layer-difference <value>`: Controls the number of layers. (Default: 16). Higher values can reduce file size.\n * `--corner-threshold <value>`: Angle threshold for corner detection. (Default: 60).\n * `--length-threshold <value>`: Minimum path length. (Default: 4.0).\n * `--max-iterations <value>`: Maximum number of optimization iterations. (Default: 10).\n * `--splice-threshold <value>`: Angle threshold for splitting splines. (Default: 45).\n * `--path-precision <value>`: Number of decimal places for path coordinates. (Default: 8).\n\n**Command-Line Examples:**\n\n```bash\n# Basic conversion with default settings\nframesvg input.gif\n\n# Specify output file and set FPS to 24\nframesvg input.gif output.svg -f 24\n\n# Optimize for smaller file size (less detail)\nframesvg input.gif -s 8 -p 3 -d 128\n\n# Enable debug logging\nframesvg input.gif -l DEBUG\n```\n\n### Python API\n\n```python\nfrom framesvg import gif_to_animated_svg_write, gif_to_animated_svg\n\n# Example 1: Convert and save to a file\ngif_to_animated_svg_write(\"input.gif\", \"output.svg\", fps=30)\n\n# Example 2: Get the SVG as a string\nanimated_svg_string = gif_to_animated_svg(\"input.gif\", fps=12)\nprint(f\"Generated SVG length: {len(animated_svg_string)}\")\n# ... do something with the string (e.g., save to file, display in a web app)\n\n# Example 3: Customize VTracer options\ncustom_options = {\n \"mode\": \"spline\",\n \"filter_speckle\": 2,\n}\ngif_to_animated_svg_write(\"input.gif\", \"output_custom.svg\", vtracer_options=custom_options)\n```\n\n### API Reference\n\n* **`gif_to_animated_svg_write(gif_path, output_svg_path, vtracer_options=None, fps=10.0, image_loader=None, vtracer_instance=None)`:**\n * `gif_path` (str): Path to the input GIF file.\n * `output_svg_path` (str): Path to save the output SVG file.\n * `vtracer_options` (dict, optional): A dictionary of VTracer options. If `None`, uses `DEFAULT_VTRACER_OPTIONS`.\n * `fps` (float, optional): Frames per second. Defaults to 10.0.\n * `image_loader` (ImageLoader, optional): Custom image loader.\n * `vtracer_instance` (VTracer, optional): Custom VTracer instance.\n * Raises: `FileNotFoundError`, `NotAnimatedGifError`, `NoValidFramesError`, `DimensionError`, `ExtractionError`, `FramesvgError`, `IsADirectoryError`.\n\n* **`gif_to_animated_svg(gif_path, vtracer_options=None, fps=10.0, image_loader=None, vtracer_instance=None)`:**\n * `gif_path` (str): Path to the input GIF file.\n * `vtracer_options` (dict, optional): A dictionary of VTracer options. If `None`, uses `DEFAULT_VTRACER_OPTIONS`.\n * `fps` (float, optional): Frames per second. Defaults to 10.0.\n * `image_loader` (ImageLoader, optional): Custom image loader.\n * `vtracer_instance` (VTracer, optional): Custom VTracer instance.\n * Returns: The animated SVG as a string.\n * Raises: `FileNotFoundError`, `NotAnimatedGifError`, `NoValidFramesError`, `DimensionError`, `ExtractionError`, `FramesvgError`.\n\n## Tips for Optimizing Large File Size (> 1MB)\n\n* **[Online Demo](https://www.visioncortex.org/vtracer/):** Use this to visualize tweaking values. Experiment to find the best balance between size and quality.\n* **`filter-speckle`:** *This is the most impactful setting for reducing file size, especially on complex images.* Increasing it removes small details.\n* **`--mode polygon`:** Use the default polygon mode unless smooth curves (spline mode) are absolutely necessary. Polygon mode can significantly reduce file size by a factor of 5 or more.\n* **`layer-difference`:** Increase this to reduce the number of layers.\n* **`color-precision`:** Reduce the number of colors by lowering this value.\n\n## Dev\n\n### Install Hatch (Recommended)\n\nfollow [this](https://hatch.pypa.io/latest/install)\n\nor just\n\n```bash\npip install hatch\n```\n\n### Format and lint\n\n```bash\nhatch fmt\n```\n\n### Testing\n```bash\nhatch test\n```\n\n### Other Hatch Commands\n\n```bash\nhatch -h\n```\n\n## Contributing\n\nContributions are welcome! Please submit pull requests or open issues on the [GitHub repository](https://github.com/romelium/framesvg).\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Convert animated GIFs to animated SVGs.",
"version": "0.1.1",
"project_urls": {
"Homepage": "https://github.com/romelium/framesvg",
"Issues": "https://github.com/romelium/framesvg/issues",
"Repository": "https://github.com/romelium/framesvg.git"
},
"split_keywords": [
"animation",
" gif",
" image-processing",
" svg",
" vector",
" vtracer"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "8d7c84cb7b2d3536de0d170aa71b5d851230f85ea756d8ab6c067b2e61e4db33",
"md5": "352838281166bc83ac4333082c972d8f",
"sha256": "8fabb779aaeb0988fe547ea53ba4c274878f12f8167e1c114a2177e476b80508"
},
"downloads": -1,
"filename": "framesvg-0.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "352838281166bc83ac4333082c972d8f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 9825,
"upload_time": "2025-02-15T18:28:40",
"upload_time_iso_8601": "2025-02-15T18:28:40.224446Z",
"url": "https://files.pythonhosted.org/packages/8d/7c/84cb7b2d3536de0d170aa71b5d851230f85ea756d8ab6c067b2e61e4db33/framesvg-0.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "3452e0b6dd5891886a00b5988c514a654a5826ac59251115f66c3d5b9bc0678d",
"md5": "dd08e45a2f2f18dfe38818ad6f0c592a",
"sha256": "10c4912c5aa209cfa5ff4090b246248bb4e1bebf046f3bbde3a10e5a9a742336"
},
"downloads": -1,
"filename": "framesvg-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "dd08e45a2f2f18dfe38818ad6f0c592a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 9159,
"upload_time": "2025-02-15T18:28:41",
"upload_time_iso_8601": "2025-02-15T18:28:41.236795Z",
"url": "https://files.pythonhosted.org/packages/34/52/e0b6dd5891886a00b5988c514a654a5826ac59251115f66c3d5b9bc0678d/framesvg-0.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-02-15 18:28:41",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "romelium",
"github_project": "framesvg",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "framesvg"
}